如何识别beautifulsoup返回的'p'标签中是否存在'span'子标签?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何识别beautifulsoup返回的'p'标签中是否存在'span'子标签?相关的知识,希望对你有一定的参考价值。

我正在制作一个网络剪贴簿,从索引网页上抓取一个在线小说,代码为小说的每本书创建和epub文件。小说的翻译以2种不同的格式为小说设置了网页。

第一种格式是带有p标签的span标签。 span标签在段落的每个部分都有一堆css,具体取决于其正常文本还是初始化。

另一种格式是p标签中的文本,没有span标签,也没有css代码。我已经能够使用Beautifulsoup来获取只有网页上的小说的部分代码。我试图制作一个if语句,如果span存在于章节内容中,请运行一个代码,否则运行其他代码。

我尝试过使用来自beautifulsoup的if chapter.find('span') != []:if chapter.find_all('span') != []:,但这些beautifulsoup代码返回实际值,而不是布尔值。如果章节有标签,我通过打印'是'或'否'来测试这个,但是当我检查2个不同的章节以确保它们没有不同的格式时,输出将只是'是',或者只是'否' 。

我正在使用的代码:

    #get link for chapter 1 from index
    r = requests.get(data[1]['link'])
    soup = BeautifulSoup(r.content, 'html.parser')

    # if webpage announcement change 0 to 1
    chapter = soup.find_all('div', {"class" : "fr-view"})[0].find_all('p')

根据章节,输出为:

    #chapter equals this
    [<p dir="ltr"><span style="color: rgb(0, 0, 0); background-color: transparent; font-weight: 400; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap">Chapter 1 - title</span></p>,
    <p dir="ltr"><span style="color: rgb(0, 0, 0); background-color: transparent; font-weight: 400; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap">stuff</span></p>,
    <p dir="ltr"><span style="color: rgb(0, 0, 0); background-color: transparent; font-weight: 400; font-style: italic; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap">italizes</span><span style="color: rgb(0, 0, 0); background-color: transparent; font-weight: 400; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap"> stuff</span></p>]

要么:

    #chapter equals this
    [<p>Chapter 6 - title</p>,
    <p>stuff</p>]

我正在尝试制作和if语句,可以阅读章节,并告诉我,如果span标签退出,所以我可以执行正确的代码。

答案

在Beautiful Soup 4.7+中,Beautiful Soup使用一个名为Soup Sieve的新CSS选择器库。使用find_allfind是一种有条件地过滤标签的好方法,但我想展示一种可以用来用CSS选择器进行复杂过滤的替代方法。 Soup Sieve提供了许多有用的功能,因为Beautiful Soup依赖于它,如果您使用的是Beautiful Soup 4.7+,它应该已经安装。

在这种情况下,我们只搜索p标签,然后直接利用Soup Sieve的API创建一个过滤器来比较返回的标签。只是另一种做事的方式。

from bs4 import BeautifulSoup
import soupsieve as sv

html = """

<p dir="ltr"><span style="color: rgb(0, 0, 0); background-color: transparent; font-weight: 400; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap">Chapter 1 - title</span></p>,
<p dir="ltr"><span style="color: rgb(0, 0, 0); background-color: transparent; font-weight: 400; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap">stuff</span></p>,
<p dir="ltr"><span style="color: rgb(0, 0, 0); background-color: transparent; font-weight: 400; font-style: italic; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap">italizes</span><span style="color: rgb(0, 0, 0); background-color: transparent; font-weight: 400; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap"> stuff</span></p>

<p>Chapter 6 - title</p>,
<p>stuff</p>
"""

soup = BeautifulSoup(html, "html.parser")
css_match = sv.compile(':has(span)')
for i in soup.select('p'):
    if css_match.match(i):
        print('found span')
    else:
        print('no span')

产量

found span
found span
found span
no span
no span
另一答案

使用您的代码段:

html = """

<p dir="ltr"><span style="color: rgb(0, 0, 0); background-color: transparent; font-weight: 400; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap">Chapter 1 - title</span></p>,
<p dir="ltr"><span style="color: rgb(0, 0, 0); background-color: transparent; font-weight: 400; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap">stuff</span></p>,
<p dir="ltr"><span style="color: rgb(0, 0, 0); background-color: transparent; font-weight: 400; font-style: italic; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap">italizes</span><span style="color: rgb(0, 0, 0); background-color: transparent; font-weight: 400; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap"> stuff</span></p>

<p>Chapter 6 - title</p>,
<p>stuff</p>
"""

你可以试试这个:

soup = BeautifulSoup(html, "lxml")
my_p = soup.find_all('p')
for i in my_p:
    if i.find('span'):
        print('found span')
    else:
        print('no span')

输出:

found span`
found span
found span
no span
no span`

我想这就是你要找的东西。

以上是关于如何识别beautifulsoup返回的'p'标签中是否存在'span'子标签?的主要内容,如果未能解决你的问题,请参考以下文章

如何解决'连接中止'。使用BeautifulSoup在Python中出错

beautifulsoup 无法识别 lxml

如何使用 BeautifulSoup 从表中抓取特定列并作为熊猫数据框返回

Beautifulsoup4 没有返回页面上的所有链接

如何在 python 中使用 beautifulsoup4 来抓取标签中的内容

如何在 BeautifulSoup 中删除空格