【问题标题】:Python3 - BeautifulSoup - Get value between two tags, where values betweenPython3 - BeautifulSoup - 获取两个标签之间的值,其中值之间
【发布时间】:2019-06-24 12:28:55
【问题描述】:

我有以下 HTML 块,由 pdftotext 使用 -bbox-layout 选项生成:

<flow>
<block xMin="21.600000" yMin="86.356000" xMax="178.647000" yMax="116.233001">
    <line xMin="21.600000" yMin="86.356000" xMax="178.647000" yMax="101.833000">
        <word xMin="21.600000" yMin="86.356000" xMax="178.647000" yMax="101.833000">
            My text string located here!</word>
    </line>

</block>
</flow>

[...]
<flow>
<block xMin="223.560000" yMin="323.675000" xMax="345.563500" yMax="339.855500">
    <line xMin="223.560000" yMin="323.675000" xMax="345.563500" yMax="339.855500">
        <word xMin="223.560000" yMin="323.675000" xMax="316.836500" yMax="339.855500">Another string
        </word>
        <word xMin="320.022000" yMin="323.675000" xMax="345.563500" yMax="339.855500">And another!</word>
    </line>
</block>
</flow>

现在,我正在尝试动态解析上述结构,并获取每个&lt;block&gt;[...]&lt;/block&gt; 内容,其中xMinxMax 的值介于两个数字之间。

假设我有以下数字:

areas[0] = (100, 0, 200, 792)
areas[1] = (200, 0, 612, 792)

with open(path_to_html_document) as html_file:
    parsed_html = BeautifulSoup(html_file)
    for (i, area) in enumerate(areas):

        xMinValue, xMaxValue = areas[i][0], areas[i][2]

        block_tags = parsed_html.find_all(
            "block", attrs={"xMin": xMinValue, "xMax": xMaxValue})

        print(block_tags)

上面的代码没有返回任何东西,因为没有匹配的标签。 find_all() 搜索具有特定数字的 block 标签的完全匹配 - 但我正在尝试搜索 block 标签,其中 xMin 和 xMax 是:

areas[0] is between 100 and 200

areas[1] is between 200 and 612

BeautifulSoup 可以做到这一点吗?

【问题讨论】:

    标签: python python-3.x beautifulsoup


    【解决方案1】:

    替换你的代码:

    block_tags = parsed_html.find_all(
                "block", attrs={"xMin": xMinValue, "xMax": xMaxValue})
    print(block_tags)
    

    到:

    block_tags = parsed_html.find_all("block")
    
    for block in block_tags:
        if float(block['xmin']) >= xMinValue and  float(block['xmax']) <= xMinValue:
            print(block)
    

    如果调试html代码print(parsed_html),你会看到html block所有属性都是小写的。

    【讨论】:

    • if float(... 语句中,它是否应该是我们要检查的2x xmin 值?不是xMax
    【解决方案2】:

    试试

    parsed_html.select("block")
    

    并使用键“xMin”和“xMax”过滤结果。

    比如要获取&lt;block xMin="1" xMax="2"&gt;&lt;/block&gt;,可以先获取所有block标签

    all_blocks = parsed_html.select("block")
    

    如果你想得到xMin 为 1 而xMax 为 2 的block 之一,你可以这样:

    target = filter(lambda x: x["xMin"] == "1" and x["xMax"] == 2, all_blocks)
    

    【讨论】:

    • 您介意提供更多信息吗?这如何解决我当前的问题,我需要获取xMinxMax 位于一组数字之间的标签?
    【解决方案3】:

    您可以选择带有属性xMin&lt;block&gt; 和带有CSS 选择器block[xMin][xMax]xMax。然后你通过列表​​理解进行过滤:

    data = '''<flow>
    <block xMin="21.600000" yMin="86.356000" xMax="178.647000" yMax="116.233001">
        <line xMin="21.600000" yMin="86.356000" xMax="178.647000" yMax="101.833000">
            <word xMin="21.600000" yMin="86.356000" xMax="178.647000" yMax="101.833000">
                My text string located here!</word>
        </line>
    
    </block>
    </flow>
    
    <flow>
    <block xMin="223.560000" yMin="323.675000" xMax="345.563500" yMax="339.855500">
        <line xMin="223.560000" yMin="323.675000" xMax="345.563500" yMax="339.855500">
            <word xMin="223.560000" yMin="323.675000" xMax="316.836500" yMax="339.855500">Another string
            </word>
            <word xMin="320.022000" yMin="323.675000" xMax="345.563500" yMax="339.855500">And another!</word>
        </line>
    </block>
    </flow>'''
    
    from bs4 import BeautifulSoup
    
    soup = BeautifulSoup(data, 'lxml')
    
    def blocks_min_max(soup, x_min, x_max):
        return [b for b in soup.select('block[xMin][xMax]') if float(b['xmin']) >= x_min and float(b['xmax']) <= x_max]
    
    for b in blocks_min_max(soup, 10, 200):
        print(b.prettify())
    

    打印:

    <block xmax="178.647000" xmin="21.600000" ymax="116.233001" ymin="86.356000">
     <line xmax="178.647000" xmin="21.600000" ymax="101.833000" ymin="86.356000">
      <word xmax="178.647000" xmin="21.600000" ymax="101.833000" ymin="86.356000">
       My text string located here!
      </word>
     </line>
    </block>
    

    【讨论】:

    • 谢谢安德烈!但是,这给了我以下错误:Unsupported or invalid CSS selector: "block[xMin][xMax]
    • @oliverbj 你用的是什么版本的 BeautifulSoup?我在beautifulsoup4==4.7.1
    猜你喜欢
    • 1970-01-01
    • 2023-03-07
    • 2013-08-08
    • 2018-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-22
    相关资源
    最近更新 更多