Веб-парсинг с BS4, как установить диапазон, где искать - PullRequest
0 голосов
/ 17 июня 2020

Я пытаюсь очистить раздел «События» на этой странице википедии: https://en.wikipedia.org/wiki/2020. Страница не имеет самого простого HTML для навигации, поскольку большинство тегов не вложены, а являются родственниками.

Я хочу убедиться, что единственные данные, которые я очищаю, находятся между двумя тегами h2, показанными ниже.
Вот сокращенный HTML:

<h2>                  #I ONLY WANT TO SEARCH BETWEEN HERE
    <span id="Events">Events</span>
</h2>
<h3>...</h3>
<ul>...</ul>
<h3>...</h3>
<ul>
    <li>
        <a title="June 17"</a>   #My code below is looking for this, if not found it jumps to another section
    </li>
</ul>
<h3>...</h3>
<ul>...</ul>
<h2>                 #AND HERE. DON"T WANT TO GO PAST HERE
    <span id="Predicted_and_scheduled_events">Predicted_and_scheduled_events</span>
</h2>

Если не ясно, каждый тег (кроме диапазона) является родственным. Мой код в настоящее время работает, если дата присутствует между двумя тегами h2, однако, если дата не указана, он будет go в другой раздел страницы для извлечения данных, что мне не нужно.

Вот мой код:

import sys
import requests
import bs4
res = requests.get('https://en.wikipedia.org/wiki/2020')
res.raise_for_status()
soup = bs4.BeautifulSoup(res.text,"lxml")
todaysNews = soup.find('a', {"title": "June 17"}) #goes to date's stories

Ответы [ 2 ]

1 голос
/ 17 июня 2020

BS имеет множество полезных функций и параметров. Стоит прочитать всю документацию.

Он имеет функцию для получения родительского элемента, следующих братьев и сестер, элементов с любым заголовком и т. Д. c.


Сначала я ищу <span id="Events">Events</span>, затем получаю его parent element <h2> и у меня есть начало данных.

Затем я могу получить next_siblings и запустить for -l oop, пока не получу элемент с именем h2 и не получу конец данных.

In for -l oop Я могу проверить все элементы ul и выполнить прямой поиск li элемент без вложенных li элементов (recursive=False), а внутри li я могу получить первый a, который имеет title с любой текст ({"title": True})

import requests
import bs4

res = requests.get('https://en.wikipedia.org/wiki/2020')
res.raise_for_status()

soup = bs4.BeautifulSoup(res.text, 'lxml')

# found start of data `h2`
start = soup.find('span', {'id': 'Events'}).parent

# check sibling items
for item in start.next_siblings:

    # found end of data `h2`
    if item.name == 'h2': 
        break

    if item.name == 'ul':

        # only direct `li` without nested `li`
        for li in item.find_all('li', recursive=False): 

            # `a` which have `title`
            a = li.find('a', {'title': True}) 

            if a:
                print(a['title'])

Результат:

January 1
January 2
January 3
January 5
January 7
January 8
January 9
January 10
January 12
January 16
January 18
January 28
January 29
January 30
January 31
February 5
February 11
February 13
February 27
February 28
February 29
March 5
March 8
March 9
March 11
March 12
March 13
March 14
March 16
March 17
March 18
March 20
March 23
March 24
March 26
March 27
March 30
April 1
April 2
April 4
April 5
April 6
April 7
April 8
April 9
April 10
April 12
April 14
April 15
April 17
April 18
April 19
April 20
April 21
April 22
April 23
April 25
April 26
April 27
April 28
April 29
April 30
May 1
May 3
May 4
May 5
May 6
May 7
May 9
May 10
May 11
May 12
May 14
May 15
May 16
May 18
May 19
May 21
May 22
May 23
May 24
May 26
May 27
May 28
May 30
May 31
June 1
June 2
June 3
June 4
June 6
June 7
June 8
June 9
June 16
0 голосов
/ 17 июня 2020

Вы можете использовать селектор CSS с ",", а затем проверить имя тега.

CSS селектор h2:contains("Events") ~ ul > li выберет всех ul > li братьев и сестер до <h2>, который содержит строку "Events".

import requests
from bs4 import BeautifulSoup

url = 'https://en.wikipedia.org/wiki/2020'
soup = BeautifulSoup(requests.get(url).content, 'html.parser')

for tag in soup.select('h2:contains("Events") ~ ul > li, h2:contains("Predicted and scheduled events")'):
    if tag.name == 'li':
        print(tag.a.text)
    else:
        break

Печать:

January 1
January 2
January 3
January 5
January 7
January 8
January 9
January 10
January 12
January 16
January 18
January 28
January 29
January 30
January 31
February 5
February 11
February 13
February 27
February 28
February 29
March 5
March 8
March 9
March 11
March 12
March 13
March 14
March 16
March 17
March 18
March 20
March 23
March 24
March 26
March 27
March 30
April 1
April 2
April 4
April 5
April 6
April 7
April 8
April 9
April 10
April 12
April 14
April 15
April 17
April 18
April 19
April 20
April 21
April 22
April 23
April 25
April 26
April 27
April 28
April 29
April 30
May 1
May 3
May 4
May 5
May 6
May 7
May 9
May 10
May 11
May 12
May 14
May 15
May 16
May 18
May 19
May 21
May 22
May 23
May 24
May 26
May 27
May 28
May 30
May 31
June 1
June 2
June 3
June 4
June 6
June 7
June 8
June 9
June 16
...