Есть ли какая-либо причина, по которой мой оператор if для поиска текста в элементе тега bs4 терпит неудачу?

#python #if-statement #web-scraping #beautifulsoup

#python #if-statement #очистка веб-страниц #beautifulsoup

Вопрос:

Я пытаюсь найти и распечатать все теги h3, которые содержат интересующие меня месяцы. Для этого я попытался создать цикл for для моего объекта bs4( head ), и оператор if внутри него указывает на печать строки, которая удовлетворяет условию; что в данном случае было бы, если строка (месяц) находится в строке. Проблема, с которой я сталкиваюсь, заключается в том, что даже если указанные мной месяцы существуют в объекте / строках bs4, они не печатаются в моем операторе if.

Я попытался добавить год к месяцам, и это, казалось, решило проблему, хотя и не идеально. Кроме того, я протестировал логику своего метода, составив краткий список некоторых строк (вручную) и запустив цикл for с этим списком вместо объекта bs4( head )

 import requests
from bs4 import BeautifulSoup

page=requests.get('https://www.england.nhs.uk/statistics/statistical-work-areas/delayed-transfers-of-care/statistical-work-areas-delayed-transfers-of-care-delayed-transfers-of-care-data-2018-19/')

soup=BeautifulSoup(page.text,'html.parser')
text=soup.find(class_='rich-text')
head = text.find_all('h3')

for row in head:
    for r1 in ['January','February']:
        if r1 in row:
            print(row)
        else:
            continue
  

Ожидаемые результаты
<h3>February 2019</h3>
<h3>January 2019</h3>

Результаты, которые я получаю, не существуют, поскольку ничего не распечатывается

Комментарии:

1. используйте row.text вместо этого, поскольку row это не строка

Ответ №1:

Это потому row , что это не строковый тип, но это <class 'bs4.element.Tag'> . Следовательно in , проверка завершается неудачей.

Один обходной путь будет приведен к строке в проверке:

 if r1 in str(row): # or row.text
  

Код:

 for row in head:
    for r1 in ['January','February']:
        if r1 in str(row):  # or row.text
            print(row)
  

Я целенаправленно избегал else to if , потому что это не служит никакой цели.

Необязательно,

 for row in head:
    if any(r1 in row.text for r1 in ['January','February']):
        print(row)
  

Комментарии:

1. Привет, Остин, спасибо за ответ, хотя я не уверен, почему работает код, который я изначально опубликовал, когда я добавляю year в список в моем операторе if, на данный момент строка по-прежнему является объектом bs4, а не строкой. Только когда я убираю год, он не может найти условие.

Ответ №2:

Другой способ получения ежемесячных публикаций DTOC с использованием bs4 4.7.1

 import requests
from bs4 import BeautifulSoup as bs

url = 'https://www.england.nhs.uk/statistics/statistical-work-areas/delayed-transfers-of-care/statistical-work-areas-delayed-transfers-of-care-delayed-transfers-of-care-data-2018-19/'

r = requests.get(url)
soup = bs(r.content, 'lxml')
publications = [item.next_sibling.next_sibling.text for item in soup.select('#main-content p:has( h3)')][1:]
print(publications)
  

Для страницы:

 #main-content p:has( h3)
  

фильтры для p тегов с родительским элементом, имеющим id main-content , которые имеют соседний h3 тег родственного элемента. [1:] Игнорирует первый элемент в возвращаемом списке, поскольку это не месяц, а Statistical Press Notice заголовок

Комментарии:

1. Не могли бы вы объяснить, как вы фильтруете публикации с помощью next_sibling, я пытался сделать это в обычном цикле for, включая next_sibling в каждую итерацию, но, похоже, это не работает, я получаю полный раздел, возвращающий, а не публикации

2. Я полностью понимаю, к чему вы клоните, но я изо всех сил пытаюсь понять, как :has() работает селектор css. Я понимаю h3 , что это даст нам следующий <h3> тег, но я не уверен, как указание <p> должно включать следующий <h3> тег. Правильно ли я предполагаю, что происходит :has() проверка тега h3 , можно ли выполнить с любым из <p> тегов, которые у нас были в нашем html, и если это возможно, то он будет соответствовать этим <p> тегам?

3. выберите только теги p, которые имеют (имеют) соседний тег h3 developer.mozilla.org/en-US/docs/Web/CSS/:has

4. итак, я попробовал ту же логику soup.select('#main-content h3:has( a)')[2:] , но я заменил p на тег h3, а соседний тег h3 на тег a. Но когда я пытаюсь напечатать что-нибудь вроде элемента или следующего родственного элемента в цикле for, я получаю пустое.

5. все еще DTOCs ежемесячно? кстати, я работаю с этими файлами каждый второй четверг месяца 🙂