тот же CSS, другой результат в браузере и метод bs4 .select () - PullRequest
0 голосов
/ 14 декабря 2018

Я пытаюсь получить некоторую информацию со следующей веб-страницы: https://web.archive.org/web/19990421025223/http://www.rbc.ru

Я создал селектор, который выделяет нужную таблицу в режиме проверки Chrome:

selector = 'body > table:nth-of-type(2) > tbody:nth-of-type(1)>tr:nth-of-type(1)>td:nth-of-type(5)>table:nth-of-type(1)>tbody:nth-of-type(1)'

однако при запуске сценария с методом bs4 .select ():

import requests
from bs4 import BeautifulSoup
import lxml

url = 'https://web.archive.org/web/19990421025223/http://www.rbc.ru'
headers = {
        'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36'
    }
r = requests.get(url, headers=headers)
soup = BeautifulSoup(r.content, 'lxml')
selector = 'body > table:nth-of-type(2) > tbody:nth-of-type(1)>tr:nth-of-type(1)>td:nth-of-type(5)>table:nth-of-type(1)>tbody:nth-of-type(1)'
print(soup.select(selector=selector))

вывод будет: [] - что сильно отличается от ожидаемого, поскольку он состоит из HTML-кода в браузере.

Что мне здесь не хватает?

Ответы [ 3 ]

0 голосов
/ 14 декабря 2018

Поскольку во время выполнения javascript может отображать всю страницу не так, как источник, bs4 не подходит для сайтов, которые динамически изменяются.

Я бы порекомендовал использовать Selenium, поскольку он фактически открывает веб-сайт и позволяет приостановить поиск до того, как определенный элемент будет отображен.Существуют также другие библиотеки безголовых браузеров, которые эмулируют среду браузера без вывода сообщений, если вы не хотите, чтобы браузер всплывал.

0 голосов
/ 14 декабря 2018

У вас есть 2 проблемы в вашем коде, во-первых, в BeautifulSoup, если вы хотите использовать селектор CSS, символы + > ~ должны быть разделены space, см. здесь , если вы хотите исправить bs4,

Во-вторых, как мой предыдущий ответ на ваши вопросы в исходном тексте страницы нет tbody, это сгенерировано браузером.

А здесь исправлен селектор CSS

selector = 'body > table:nth-of-type(2) > tr:nth-of-type(1) > td:nth-of-type(5) > table:nth-of-type(1)'
0 голосов
/ 14 декабря 2018

Вы не могли ожидать, что сгенерированные браузером селекторы будут надежно работать в BeautifulSoup как , когда страница отображается в браузере, разметка изменяется , в то время как при загрузке страницы в коде Python естьбез рендеринга, и вы получите только исходную не рендеринг HTML-страницы.

Здесь вам нужно найти собственный селектор CSS или другой способ найти элемент table.

Поскольку разметка страницы не очень удобна для HTML-анализа, я бы обнаружил элемент table по одному из имен его столбцов:

table = soup.find("b", text="спрос").find_parent("table")

Обратите внимание, что он работал только для меня, когда я анализировалстраница с снисходительным html5lib парсером :

soup = BeautifulSoup(response.content, "html5lib")
...