#html #python-3.x #if-statement #beautifulsoup
#HTML #python-3.x #if-оператор #beautifulsoup
Вопрос:
Я создаю веб-скребок, который удаляет онлайн-роман с веб-страницы индекса, и код создает файл epub для каждой книги романа. Переводчик романа настроил веб-страницы для романа в двух разных форматах.
Первый формат — это p
тег с span
тегом внутри. span
тег содержит множество css для каждого раздела абзацев, в зависимости от того, является ли он обычным текстом или инициализируется.
Другой формат — это текст в p
теге без span
тега и без css-кода. Я смог использовать Beautifulsoup для получения части кода, содержащей только роман с веб-страницы. Я застрял, пытаясь создать if
утверждение, в котором говорится, что если span
существует внутри содержимого главы, запустите один код, иначе запустите какой-нибудь другой код.
Я пытался использовать if chapter.find('span') != []:
и if chapter.find_all('span') != []:
из beautifulsoup, но эти коды beautifulsoup возвращают фактические значения, а не логические значения. Я протестировал это, напечатав ‘yes’ или ‘no’, если у главы был тег, но вывод был бы либо только ‘yes’, либо только ‘no’, когда я проверил 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>]
Я пытаюсь создать оператор and if
, который может прочитать главу и сообщить мне, завершается ли span
тег, чтобы я мог выполнить правильный код.
Ответ №1:
В 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
Ответ №2:
Используя ваши фрагменты кода:
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. Я пробовал этот метод, но он выводил только ‘found spam’ в обоих форматах. Я думаю, это потому, что
i.find('spam')
это не логическая функция, а функция, которая возвращает строковое значениеspan
тега