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

时间:2019-03-28 22:01:19

标签: html python-3.x if-statement beautifulsoup

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

第一种格式是带有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标签是否退出,以便我可以执行正确的代码。

2 个答案:

答案 0 :(得分:1)

使用代码段:

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`

我认为这就是您想要的。

答案 1 :(得分:1)

在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