Как определить, существует ли дочерний тег 'span' в теге 'p', возвращаемом Beautifulsoup? - PullRequest
0 голосов
/ 29 марта 2019

Я делаю веб-скребок, который удаляет онлайн-роман с индексной веб-страницы, и код создает файл epub для каждой книги романа. Переводчик романа создал веб-страницы для романа в двух разных форматах.

Первый формат - это тег p с тегом span внутри. тег span содержит связку css для каждого раздела абзаца, в зависимости от того, является ли он обычным текстом или инициализированным.

Другой формат - это текст в теге p без тега span и без кода CSS. Я был в состоянии использовать Beautifulsoup, чтобы получить часть кода, которая имеет только роман с веб-страницы. Я застрял, пытаясь сделать заявление if, в котором говорится, что если внутри содержимого главы существует span, запустите один код, иначе запустите другой код.

Я пытался использовать if chapter.find('span') != []: и if chapter.find_all('span') != []: из Beautifulsoup, но эти коды 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 ]

1 голос
/ 29 марта 2019

В Beautiful Soup 4.7+, Beautiful Soup использует новую библиотеку CSS-селекторов под названием Soup Sieve. Использование find_all и find - это прекрасный способ условно фильтровать ваши теги, но я бы хотел показать альтернативный способ, который можно использовать для сложной фильтрации с помощью селекторов CSS. Soup Sieve предоставляет ряд полезных функций, и поскольку Beautiful Soup полагается на него, он должен быть уже установлен, если вы используете Beautiful Soup 4.7 +.

В этом случае мы просто ищем теги p, а затем напрямую используем API Soup Sieve для создания фильтра для сравнения возвращаемых тегов. Просто еще один способ сделать что-то.

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
1 голос
/ 29 марта 2019

Использование фрагментов кода:

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`

Я думаю, это то, что вы ищете.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...