Php 用于从HTML中提取所有链接和锚文本的Regexp

Php 用于从HTML中提取所有链接和锚文本的Regexp,php,regex,string,html-parsing,Php,Regex,String,Html Parsing,我想要一个或多个正则表达式,可以: 1) 以一个大页面的html为例 2) 查找所有链接中包含的URL,例如: <a href="http://example1.com">Test 1</a> <a class="foo" id="bar" href="http://example2.com">Test 2</a> <a onclick="foo();" id="bar" href="http://example3.com">Test

我想要一个或多个正则表达式,可以:

1) 以一个大页面的html为例

2) 查找所有链接中包含的URL,例如:

<a href="http://example1.com">Test 1</a>
<a class="foo" id="bar" href="http://example2.com">Test 2</a>
<a onclick="foo();" id="bar" href="http://example3.com">Test 3</a>

依此类推,它应该提取
'href'
属性中包含的url,而不管
href
之前或之后是什么


3) 提取所有链接的锚文本,例如在上面的示例中,它应该返回'http://example1.com'和锚文本'Test 1',然后'http://example2.com'和'Test 2',依此类推。

尝试以下方法:

//not tested
$regex_pattern = "/<a href=\"(.*)\">(.*)<\/a>/";
//未测试
$regex_pattern=“/(.*)/”;
/]+href\s*=\s*[“”]([^“]+)[“][”][^>]*>(.*)/mis

您需要看一看


就使用正则表达式从HTML提取链接而言,这一个非常健壮:

\b(((src | href | action | url)*(=|:)*(?“|”!*)(?[\w~!*/。?=#和:%+,();\-\[\]+)\k | url*(*(?“?”)(?[\w~!*/。?=&:%+,()\[\]+)\k+)/code>

下面是一个从HTML文档中提取所有“纯”文本(即标记外的内容)的方法:



这将同时提取链接和锚文本。

有什么原因不想使用DOM解析器吗?有什么原因找不到副本吗?可能重复的可能重复的可能重复的可能重复的可能重复的可能重复的可能重复的可能重复的可能重复的可能重复的会在属性值被括在双引号中时中断和包含单引号。当省略引号时,它也会中断,这对于像next|page.htm这样的href值是允许的。请看这一个非常健壮(在这里测试):
\b((src|href | action | url)*(====:)*(?“|'|])(?[\w$!*/。?=&:%+,()-\[\[\]+++)\k;;url*(*(*(?“?”)++)/,[\++-\\\++++--\\\\\+++--[\\\\\\++++++----\\\\\\\\\\\\\\\+++++++----[\\\\\\\\\\\\\\\\\\\\\\\\\\
这与OP给出的示例标记中的第二个和第三个链接不匹配。当然,正确的方法是使用DOM解析器,但也可以使用regex。请参阅GameBit解决方案下面的我的评论。它也适用于您的regex。不,如果属性中有单引号,它不会中断,请尝试。事实上,如果您需要我们e这个正则表达式#很多人只是扔掉了“只使用DOM解析器!”但没有人能给出它能做什么的快速示例。它比我的示例做得更多。值得学习。这个答案是不完整的,我使用这个答案,因为4MB文件只需要54毫秒,而真正的解析器只需要10-30秒:)真是一个伟大的工作,只有一个正则表达式和所有的工作都完成了。今天学会了新的方法。
/<a[^>]+href\s*=\s*["']([^"']+)["'][^>]*>(.*?)<\/a>/mis
<?php

$string = '<a href="http://example1.com">Test 1</a>
<a class="foo" id="bar" href="http://example2.com">Test 2</a>
<a onclick="foo();" id="bar" href="http://example3.com">Test 3</a>';

if(preg_match_all("|<a.*(?=href=\"([^\"]*)\")[^>]*>([^<]*)</a>|i", $string, $matches))
        {
        /*** if we find the word white, not followed by house ***/
        echo 'Found a match';
        print_r($matches);
    }
else
        {
        /*** if no match is found ***/
        echo 'No match found';
        }
?>
<?

$dom = new DomDocument();
$dom->loadHTML($html);
$urls = $dom->getElementsByTagName('a');
<?php
$regexp = "<a\s[^>]*href=(\"??)([^\" >]*?)\\1[^>]*>(.*)<\/a>";
if(preg_match_all("/$regexp/siU", $html, $matches, PREG_SET_ORDER))
{ foreach($matches as $match)
{// $match[2] = link address
// $match[3] = link text}
}
?>