找到单词但不在链接中

时间:2013-06-11 14:32:10

标签: php regex html-parsing

我需要一个reg表达式,它将在html中找到目标单词(因此在标签中)但不在锚点或脚本标签中。 我已经进行了多年的实验并想出了这个

(?!<(script|a).*?>)(\btype 2 diabetes\b)(?!<\/(a|script)>)

假设在这种情况下要替换的目标是2型糖尿病

我认为这是常见问题,但所有引用都是锚的一部分,而不是在锚或脚本标签中,而是在它们和其他标签中

这是一个测试数据 我使用了http://regexpal.com/http://gskinner.com/RegExr/ 用上面的表达式和下面的测试数据,试试我可能只是不能排除 位于锚点或脚本标记中,而不排除锚点或脚本标记之间的位。

在下面的测试数据中只有“2型糖尿病”内的

<p></p>
应该抓住

<a href="https://www.testsite.org.uk">
<div><img alt="logo" src="/images/logo.png" height="115" width="200" /></div>
<h2>Healthy Living for People with type 2 Diabetes</h2>
</a>
<p>type 2 Diabetes</p>
<a id="logo" href="https://www.help-diabetes.org.uk">
<div><img alt="logo" src="/images/logo.png" height="115" width="200" /></div>
<h2>Healthy Living for People with type 2 Diabetes</h2>
</a>

2 个答案:

答案 0 :(得分:0)

要在避免 a 脚本标记出现目标词时进行替换,您必须尝试在目标词之前匹配这些标记(及其内容)。例如:

$subject = <<<LOD
<a href="https://www.testsite.org.uk">
<div><img alt="logo" src="/images/logo.png" height="115" width="200" /></div>
<h2>Healthy Living for People with type 2 Diabetes</h2>
</a>
<p>type 2 Diabetes</p>
<a id="logo" href="https://www.help-diabetes.org.uk">
<div><img alt="logo" src="/images/logo.png" height="115" width="200" /></div>
<h2>Healthy Living for People with type 2 Diabetes</h2>
</a>
LOD;

$targets = array('type 2 diabetes', 'scarlet fever', 'bubonic plague');

$pattern = '~<(a|script)\b.+?</\1>|\b(?>' . implode('|', $targets) . ')\b~si';

$result = preg_replace_callback($pattern,
    function ($m) { return (isset($m[1])) ? $m[0] : '!!!rabbit!!!'; },
    $subject);

echo htmlspecialchars($result);

回调函数在设置第一个捕获goup或替换字符串时返回 a 脚本标记。

请注意,如果您想要对每个目标词进行特定替换,则可以使用关联数组:

$corr = array( 'type 2 diabetes' => 'marmot',
               'scarlet fever'   => 'nutria',
               'bubonic plague'  => 'weasel'  );

$pattern = '~<(a|script)\b.+?</\1>|\b(?>'
         . implode('|', array_keys($corr)) . ')\b~si';

$result = preg_replace_callback($pattern,
    function ($m) use ($corr) {
        return (isset($m[1])) ? $m[0] : $corr[strtolower($m[0])];
    },
    $subject);

请记住,处理html的最佳方法是使用DOM

答案 1 :(得分:0)

Do not use regex for this problem。使用html解析器。这是python中使用BeautifulSoup的解决方案:

from BeautifulSoup import BeautifulSoup

with open('Path/to/file', 'r') as content_file:
    content = content_file.read()

soup = BeautifulSoup(content)

matches = [el for el in soup(text=re.compile(r'type 2 diabetes')) if el.name not in ['a','script']]

# now you can modify the matched elements

with open('Path/to/file.modified', 'w') as output_file:
    output_file.write(str(soup))