Python 使用正则表达式解析 HTML

Posted

技术标签:

【中文标题】Python 使用正则表达式解析 HTML【英文标题】:Python parsing HTML Using Regular Expressions 【发布时间】:2014-06-26 05:51:15 【问题描述】:

我正在尝试浏览网站的 html 并对其进行解析,以寻找班级的最大入学人数。我尝试在 HTML 文件的每一行中检查一个子字符串,但这会尝试解析错误的行。所以我现在正在使用正则表达式。我现在有 \t\t\t\t\t\t\t<td class="odd">([0-9])|([0-9][0-9])|([0-9][0-9][0-9])<\/td>\r\n 作为我的正则表达式,但这个正则表达式匹配最大注册人数以及节号。还有另一种方法可以解决我试图从网页中提取的内容吗? HTML 代码 sn-p 如下:

<tr>
    <td class="tableHeader">Section</td>
    <td class="odd">001</td>
</tr>

<tr>
    <td class="tableHeader">Credits</td>
    <td class="even" align="left">  4.00</td>
</tr>

<tr>
<td class="tableHeader">Title</td>
<td class="odd">Linear Algebra</td>
</tr>

<tr>
    <td class="tableHeader">Campus</td>
    <td class="even" align="left">University City</td>
</tr>

<tr>
    <td class="tableHeader">Instructor(s)</td>
    <td class="odd">Guang  Yang</td>
</tr>
<tr>
    <td class="tableHeader">Instruction Type</td>
    <td class="even">Lecture</td>
</tr>

<tr>
    <td class="tableHeader">Max Enroll</td>
    <td class="odd">30</td>
</tr>

【问题讨论】:

阅读:***.com/a/1732454/3001761 不同意这个骗局,不是问是否可以用正则表达式完成,而是错误地尝试这样做。 这不是重复的。该 OP 正试图实际匹配标签名称、类名等。我只是试图以一种我没有得到节号和最大注册号的方式提取内容。我只需要获取 Max Enroll 号码的帮助。 好吧,与其坐在那里侮辱我处理这个问题的方式,不如为我指出正确的方向更有成效,不是吗? 这就是我在全大写免责声明中提供链接的原因。 I could also write it using <blink></blink> using toilet? 【参考方案1】:

DO NOT PARSE HTML USING REGEXP.

为正确的工作使用正确的工具。

让我们打个比方来解释为什么它是错误的:这就像试图让5 year old 理解Hamlet,而他没有vocabulary and grammar 来理解Shakespeare's,当他会得到可以process more abstract concepts。

使用lxmlBeautifulSoup 来执行此操作。

例如:获取所有偶数和所有赔率的列表:

>>> from lxml import etree
>>> tree = etree.HTML(your_html_text)
>>> odds = tree.xpath('//td[@class="odd"]/text()')
>>> evens = tree.xpath('//td[@class="even"]/text()')
>>> odds
['001', 'Linear Algebra', 'Guang  Yang', '30']
>>> evens
['  4.00', 'University City', 'Lecture']

编辑:

我只是想以这样一种方式提取内容,其中我没有获得部分编号和最大注册编号。我只需要获取 Max Enroll 号码的帮助。

好的,现在我得到了你想要的,所以这里是使用 lxml 的解决方案:

>>> for elt in tree.xpath('//tr'):
...     if elt.xpath('td[@class="tableHeader"]')[0].text == "Max Enroll":
...         elt.xpath('td[@class="odd"]|td[@class="even"]')[0].text
... 
'30'

您只有最大注册人数。

使用 BeautifulSoup 会更容易一些:

>>> bs = BeautifulSoup(your_html_text)
>>> for t in bs.findAll('td', attrs='class': 'tableHeader'):
...   if t.text == "Max Enroll":
...     print t.findNext('td').text
'30'

【讨论】:

soup.find('td', text="Max Enroll").find_next_sibling('td').text 会更容易。 确实,虽然我在这里给出了更通用的方法,所以 OP 可以适应他的数据集。【参考方案2】:

使用专门解析html的工具,如BeautifulSoup:

Beautiful Soup 是一个 Python 库,用于从 HTML 和 XML 文件。它与您最喜欢的解析器一起使用以提供惯用的 导航、搜索和修改解析树的方法。它 通常可以节省程序员数小时或数天的工作时间。

例如,您可以通过以下方式获得您想要的东西:

from bs4 import BeautifulSoup

data = """your html here"""

soup = BeautifulSoup(data)
print soup.find('td', text="Max Enroll").find_next_sibling('td').text

打印:

30

【讨论】:

如果我选择这种方法,我将无法很容易地将这个脚本提供给朋友们使用,因为它将使用他们(很可能)不会在他们的计算机上安装的库最初,正确吗? @heinst 好吧,BeautifulSoup 是一个可以轻松安装的第三方库。只需包含带有脚本依赖项的requirements.txt 文件并将其提供给您的朋友。【参考方案3】:

替代zmo's answer,使用BeautifulSoup

from bs4 import BeautifulSoup

data = """
<snipped html>
"""

soup = BeautifulSoup(data)

for tableHeaders in soup.find_all('td', class_="tableHeader"):
    if tableHeaders.get_text() == "Max Enroll":
        print tableHeaders.find_next_siblings('td', class_="odd")[0].get_text()

输出:

30

【讨论】:

以上是关于Python 使用正则表达式解析 HTML的主要内容,如果未能解决你的问题,请参考以下文章

python正则表达式解析(re)

如何使用Python中的正则表达式解析文件名?

17.python全栈之路:正则表达式全面解析

在 HTML 单元格中使用 HTML 解析 Python 正则表达式 [重复]

python爬虫--解析网页几种方法之正则表达式

计算器——python正则表达式