【问题标题】:Python + BeautifulSoup: How to get wrapper out of HTML based on text?Python + BeautifulSoup:如何根据文本从 HTML 中获取包装器?
【发布时间】:2017-11-03 05:45:52
【问题描述】:

想要获得关键文本的包装。例如,在 HTML 中:

…
<div class=“target”>chicken</div>
<div class=“not-target”>apple</div>
…

并通过基于文本“鸡”,想回&lt;div class=“target”&gt;chicken&lt;/div&gt;

目前,有以下内容来获取 HTML:

import requests
from bs4 import BeautifulSoup

req = requests.get(url).txt
soup = BeautifulSoup(r, ‘html.parser’)

只需执行soup.find_all(‘div’,…) 并遍历所有可用的div 即可找到我正在寻找的包装器。

但不必遍历每个div,根据定义的文本在 HTML 中获取包装器的正确和最佳方式是什么?

提前谢谢你,一定会接受/支持答案!

【问题讨论】:

  • @internety 给了例如soup.find_all('div', string='chicken') 尝试但只返回一个空数组。
  • 不要使用花引号
  • 在说更多之前,请阅读我指出你的全部答案 :)
  • @internety 但它没有 href 或者说它没有任何其他属性。他们所展示的正是我目前的做法,获取所有“div”并一一搜索我正在寻找的内容。想知道是否有一个搜索解决方案,而不必解析所有内容。

标签: python html css python-2.7 beautifulsoup


【解决方案1】:
# coding: utf-8

html_doc = """
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title> Last chicken leg on stock! Only 500$ !!! </title>
  </head>
  </body>
    <div id="layer1" class="class1">
        <div id="layer2" class="class2">
            <div id="layer3" class="class3">
                <div id="layer4" class="class4">
                    <div id="layer5" class="class5">
                      <p>My chicken has <span style="color:blue">ONE</span> leg :P</p>
                        <div id="layer6" class="class6">
                            <div id="layer7" class="class7">
                              <div id="chicken_surname" class="chicken">eat me</div>
                                <div id="layer8" class="class8">
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
  </body>
</html>"""

from bs4 import BeautifulSoup as BS
import re
soup = BS(html_doc, "lxml")


# (tag -> text) direction is pretty obvious that way
tag = soup.find('div', class_="chicken")
tag2 = soup.find('div', {'id':"chicken_surname"})
print('\n###### by_cls:')
print(tag)
print('\n###### by_id:')
print(tag2)

# but can be tricky when need to find tag by substring
tag_by_str = soup.find(string="eat me")
tag_by_sub = soup.find(string="eat")
tag_by_resub = soup.find(string=re.compile("eat"))
print('\n###### tag_by_str:')
print(tag_by_str)
print('\n###### tag_by_sub:')
print(tag_by_sub)
print('\n###### tag_by_resub:')
print(tag_by_resub)

# there are more than one way to access underlying strings
# both are different - see results
tag = soup.find('p')

print('\n###### .text attr:')
print( tag.text, type(tag.text) )

print('\n###### .strings generator:')
for s in tag.strings:   # strings is an generator object
    print s, type(s)

# note that .strings generator returns list of bs4.element.NavigableString elements
# so we can use them to navigate, for example accessing their parents:
print('\n###### NavigableString parents:')
for s in tag.strings:  
    print s.parent

# or even grandparents :)
print('\n###### grandparents:')
for s in tag.strings:  
    print s.parent.parent

【讨论】:

  • 我的问题是,如果您要查找的字符串有多个相同的标签,我必须遍历所有标签才能找到目标标签,正确 -例如假设有两个p 标签,那么tag = soup.find('p') 不一定有效?我正在寻找的是一种在一次尝试中找到字符串标签的方法,而无需解析所有内容。
  • @Jo Ko:“无需解析所有内容”IMO 在 HTML 文档中的每个元素搜索都需要解析整个文档 :) 不同的方法,在需要解析仅部分可用的文档时使用(即长池 HTTP ) 是使用增量解析器,有关该方法的更多信息,请参阅parse HTML incrementally
猜你喜欢
  • 2016-03-24
  • 1970-01-01
  • 1970-01-01
  • 2010-09-18
  • 1970-01-01
  • 2020-05-03
  • 1970-01-01
  • 1970-01-01
  • 2014-05-22
相关资源
最近更新 更多