2

假设我有这个 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 中匹配href 并迭代它们?我试过这样的事情:

<table id="test_table">\s*<td>(\s*<a href="(?P<url>.*?)">(?P<anchor>.*?)</a>\n)*

但这仅与第一个元素匹配,我在此问题上停留了几个小时,但我无法正确解决,谢谢您的帮助。

4

4 回答 4

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 变得太复杂、太快。不要那样做。

于 2013-03-28T15:57:47.653 回答
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 让事情变得更容易,更少的头痛和更少的咖啡;)

于 2013-03-28T16:04:21.160 回答
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', '#')]
于 2013-03-28T16:40:48.580 回答
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())]
于 2013-03-28T16:51:24.433 回答