假设我有这个HTML代码:
<table id="test_table">
<td>
<a href="#">#</a>
<a href="#">#</a>
<a href="#">#</a>
<a href="#">#</a>
<a href="#">#</a>
<a href="#">#</a>
<a href="#">#</a>
<a href="#">#</a>
</td>
</table>
<table id="test_table2">
<td>
<a href="#">#33</a>
<a href="#">#33</a>
<a href="#">#33</a>
<a href="#">#33</a>
<a href="#">#33</a>
<a href="#">#33</a>
<a href="#">#33</a>
<a href="#">#33</a>
</td>
</table>
我想只在#test_table中匹配hrefs并迭代它们?我试过这样的事情:
<table id="test_table">\s*<td>(\s*<a href="(?P<url>.*?)">(?P<anchor>.*?)</a>\n)*
但这只与第一个元素匹配,我被困在这几个小时,我无法正确,谢谢你的帮助。
答案 0 :(得分:3)
对于HTML,请使用正确的工具。请改用HTML解析器,例如BeautifulSoup:
from bs4 import BeautifulSoup
soup = BeautifulSoup(html)
table = soup.find('table', id='test_table')
for anchor in table.find_all('a'):
print anchor['href'], anchor.string
不要使用正则表达式,将HTML与此类表达式匹配会变得太复杂,太快。不要那样做。
答案 1 :(得分:1)
不要使用正则表达式来解析HTML,为此使用LXML。
使用iPython的示例(测试是您的文件)
In [55]: import lxml.html
In [56]: x = lxml.html.fromstring(open("test").read())
In [57]: for i in x.iterlinks():
print i # print ALL links
....:
(<Element a at 0x1bb7110>, 'href', '#', 0)
(<Element a at 0x1ba8c50>, 'href', '#', 0)
(<Element a at 0x1ba89b0>, 'href', '#', 0)
(<Element a at 0x1ba8e30>, 'href', '#', 0)
(<Element a at 0x1ba8c50>, 'href', '#', 0)
(<Element a at 0x1ba89b0>, 'href', '#', 0)
(<Element a at 0x1ba8e30>, 'href', '#', 0)
(<Element a at 0x1ba8c50>, 'href', '#', 0)
(<Element a at 0x1bb7110>, 'href', '#', 0)
(<Element a at 0x1ba89b0>, 'href', '#', 0)
(<Element a at 0x1ba8c50>, 'href', '#', 0)
(<Element a at 0x1ba8e30>, 'href', '#', 0)
(<Element a at 0x1ba89b0>, 'href', '#', 0)
(<Element a at 0x1ba8c50>, 'href', '#', 0)
(<Element a at 0x1ba8e30>, 'href', '#', 0)
(<Element a at 0x1ba89b0>, 'href', '#', 0)
In [58]: path = x.xpath("./table[@id='test_table']")[0]
In [59]: for i in path.iterlinks():
....: print i
....:
(<Element a at 0x1bb7110>, 'href', '#', 0)
(<Element a at 0x1bb7050>, 'href', '#', 0)
(<Element a at 0x1ba89b0>, 'href', '#', 0)
(<Element a at 0x1ba8e30>, 'href', '#', 0)
(<Element a at 0x1bb7050>, 'href', '#', 0)
(<Element a at 0x1ba89b0>, 'href', '#', 0)
(<Element a at 0x1ba8e30>, 'href', '#', 0)
(<Element a at 0x1bb7050>, 'href', '#', 0)
使用Xpath可以让事情变得更容易,减少头痛和减少咖啡;)
答案 2 :(得分:0)
另请查看PyQuery,我喜欢它提供的jQuery熟悉程度:
>>> from pyquery import PyQuery as pq
>>> html = '''<table id="test_table">
... <td>
... <a href="#">#</a>
... <a href="#">#</a>
... <a href="#">#</a>
... <a href="#">#</a>
... <a href="#">#</a>
... <a href="#">#</a>
... <a href="#">#</a>
... <a href="#">#</a>
... </td>
... </table>
... <table id="test_table2">
... <td>
... <a href="#">#33</a>
... <a href="#">#33</a>
... <a href="#">#33</a>
... <a href="#">#33</a>
... <a href="#">#33</a>
... <a href="#">#33</a>
... <a href="#">#33</a>
... <a href="#">#33</a>
... </td>
... </table>'''
>>> d = pq(html)
>>> for a in d('#test_table').find('a'):
... print a.attrib.items()
...
...
[('href', '#')]
[('href', '#')]
[('href', '#')]
[('href', '#')]
[('href', '#')]
[('href', '#')]
[('href', '#')]
[('href', '#')]
答案 3 :(得分:0)
您的正则表达式确实捕获HTML的正确部分。
问题是当你有一个以+或*结尾的捕获组(例如((?P<anchor>.*?)*
)时,groups()
方法只返回最后一组。
例如:
sss='''<table id="test_table">
<td>
<a href="#">#</a>
<a href="#">#</a>
<a href="#">#</a>
<a href="#">#</a>
<a href="#">#</a>
<a href="#">#</a>
<a href="#">#</a>
<a href="#last_url">#last_anch</a>
</td>
</table>
<table id="test_table2">
<td>
<a href="#">#33</a>
<a href="#">#33</a>
<a href="#">#33</a>
<a href="#">#33</a>
<a href="#">#33</a>
<a href="#">#33</a>
<a href="#">#33</a>
<a href="#">#33</a>
</td>
</table>'''
import re
res='<table id="test_table">\s*<td>(\s*<a href="(?P<url>.*?)">(?P<anchor>.*?)</a>\n)*'
m=re.search(res,sss)
print m.groups()
<强>输出:强>
(' <a href="#last_url">#last_anch</a>\n', '#last_url', '#last_ach')
我不同意你应该总是使用像BeautifulSoup这样的专用HTML处理器的其他海报。这些开销可能很高,而且对于简单的任务,可能需要更长的代码。
另一种方法是使用以下两个re:
res='<table id="test_table">.*?</table>'
mm=re.search(res,sss,re.DOTALL)
results=[m.group('url','anchor') for m in re.finditer('<a href="(?P<url>.*?)">(?P<anchor>.*?)</a>',mm.group())]