如何通过匹配字符串在Python中提取父html标签

Posted

技术标签:

【中文标题】如何通过匹配字符串在Python中提取父html标签【英文标题】:How to extract parent html tag in Python by matching the string 【发布时间】:2012-01-30 11:32:42 【问题描述】:

我需要通过匹配html中的字符串来提取html中的父标签。 (IE) 我有很多原始的 html 资源。每个来源都包含带有一些字符的文本值 "VIN:*"**。此文本值(VIN:*)以各种格式放置在每个源中,例如“”、“”等。

然后我需要提取所有值以及“VIN:*”字符串。这意味着我需要获取它的父标签。

例如,

<div class="class1">

                            Stock Number:
                            Z2079
                            <br>
                            **VIN:
                            2T2HK31UX9C110701**
                            <br>
                            Model Code:
                            9424
                            <img class="imgcert" src="/images/Lexus_cpo.jpg">
</div>

这里我有 html 源代码的“VIN”。与此类似,我也有其他 html 源的 VIN,格式也不同。

这些值必须在 Python 中提取。

有没有办法通过匹配Python中的字符串来有效地提取父标签?

【问题讨论】:

永远不要使用正则表达式来解析 HTML。尤其是在 python 中,你可以使用 BeautifulSoup 做得更好...... @saravana ThiefMaster 的 ukase 和断言是我反对的有争议且毫无争议的观点。我这样说是为了平衡他所表达的一般宗教信仰。 (为什么宗教:看到这个答案:***.com/a/1732454/551449) @saravan 正则表达式比 BeautifulSouplxml 快得多 【参考方案1】:

我会强烈建议在这方面使用BeautifulSoup;它为解析 HTML 提供了一些非常方便的功能。例如,在这两种情况下,我将如何查找每个包含“VIN”的文本节点:

soup = your_html_here
vins = soup.findAll(text = lambda(x): x.lower.index('vin') != -1)

从那里,您只需遍历该集合,获取每个节点的父节点,获取所述父节点的内容,然后按照您认为合适的方式解析它们:

for v in vins:
    parent_html = v.parent.contents
    # more code here

【讨论】:

对于 findAll 执行。它遇到:AttributeError: 'builtin_function_or_method' object has no attribute 'index' 对不起,lower() 当然是你要找的。 Ruby 宠坏了我。 soup = BeautifulSoup(htmltext); vins = soup(text=lambda x: 'vin' in x.lower())【参考方案2】:

对于一个如此简单的任务,包括分析字符串,而不是解析它(解析 = 构建文本的树表示),您可以这样做:

正文

ss = '''
Humpty Dumpty sat on a wall
<div class="class1">
    Stock Number:
    Z2079
    <br>
        **VIN:
        2T2HK31UX9C110701**
    <br>
    Model Code:
    9424
    <img class="imgcert" src="/images/Lexus_cpo.jpg">
</div>

Humpty Dumpty had a great fall
<ul cat="zoo">
    Stock Number:
    ARDEN3125
    <br>
        **VIN:
        SHAKAMOSK-230478-UBUN**
    </br>
    Model Code:
    101
    <img class="imgcert" src="/images/Magana_cpo.jpg">
</ul>

All the king's horses and all the king's men
<artifice>
    <baradino>
        Stock Number:
        DERT5178
        <br>
            **VIN:
            Pandaia-67-Moro**
        <br>
        Model Code:
        1234
        <img class="imgcert" src="/images/Pertuis_cpo.jpg">
    </baradino>
    what what what who what
    <somerset who="maugham">
        Nothing to declare
    </somerset>
</artifice>

Couldn't put Humpty Dumpty again
<ending rtf="simi">
    Stock Number:
    ZZZ789
    <br>
        **VIN:
        0000012554-ENDENDEND**
    <br>
    Model Code:
    QS78-9
    <img class="imgcert" src="/images/Sunny_cpo.jpg">
</ending>

qsdjgqsjkdhfqjkdhgfjkqshgdfkjqsdjfkh''' 

代码:

import re

regx = re.compile('<([^ >]+) ?([^>]*)>'
                  '(?!.+?<(?!br>)[^ >]+>.+?<br>.+?</\\1>)'
                  '.*?\*\*VIN:(.+?)\*\*.+?</\\1>',
                  re.DOTALL)

li = [ (mat.group(1),mat.group(2),mat.group(3).strip(' \n\r\t'))
       for mat in regx.finditer(ss) ]

for el in li:
    print '(%-15r, %-25r, %-25r)' % el

结果

('div'          , 'class="class1"'         , '2T2HK31UX9C110701'      )
('ul'           , 'cat="zoo"'              , 'SHAKAMOSK-230478-UBUN'  )
('baradino'     , ''                       , 'Pandaia-67-Moro'        )
('ending'       , 'rtf="simi"'             , '0000012554-ENDENDEND'   )

re.DOTALL 是必要的,以赋予点符号匹配换行符的能力(默认情况下,正则表达式模式中的点匹配除换行符以外的每个字符)

\\1是指定在被检查字符串的这个位置,必须有第一组捕获的相同部分字符串,即([^ &gt;]+)部分

'(?!.+?&lt;(?!br&gt;)[^ &gt;]+&gt;.+?&lt;br&gt;.+?&lt;/\\1&gt;)' 是表示禁止在 HTML 元素的开始标记和结束标记之间遇到的第一个标记 &lt;br&gt; 之前找到除 &lt;br&gt; 之外的标记的部分。 这部分是捕捉VIM之前最接近的前面标签所必需的&lt;br&gt; 如果这部分不存在,则正则表达式

regx = re.compile('<([^ >]+) ?([^>]*)>'
                  '.*?\*\*VIN:(.+?)\*\*.+?</\\1>',
                  re.DOTALL)

捕获以下结果:

('div'          , 'class="class1"'         , '2T2HK31UX9C110701'      )
('ul'           , 'cat="zoo"'              , 'SHAKAMOSK-230478-UBUN'  )
('artifice'     , ''                       , 'Pandaia-67-Moro'        )
('ending'       , 'rtf="simi"'             , '0000012554-ENDENDEND'   )

区别在于“技巧”而不是“巴拉迪诺”

【讨论】:

【参考方案3】:

对于不使用任何 xml/html 解析器的纯字符串版本,您可以尝试正则表达式(重新):

import re

html_doc = """ <div ...VIN ...  /div>"""

results = re.findall('<(.+>).*VIN.*+</\1', html_doc)

【讨论】:

我想指出一个非常相关的答案:***.com/questions/1732348/…

以上是关于如何通过匹配字符串在Python中提取父html标签的主要内容,如果未能解决你的问题,请参考以下文章

python 如何提取特定字符中间的内容

使用正则表达式重新字符串匹配提取 URL 链接 - Python

python 提取字符串中的数字

python通过正则匹配指定字符开头与结束提取中间内容

如何访问SURF的关键点的特征尺度和主导方向在Python?

Java如何从字符串中提取数字