Не могу найти тег, который, как я знаю, находится в документе - find_all () возвращает [] - PullRequest
0 голосов
/ 15 февраля 2019

Я использую bs4 для очистки https://www.khanacademy.org/profile/DFletcher1990/ одного профиля пользователя на khanacademy.

Я пытаюсь получить данные статистики пользователя (дата присоединения, накопленный балл энергии, видео завершено).

У меня есть проверка https://www.crummy.com/software/BeautifulSoup/bs4/doc/

Кажется, что: «Самый распространенный тип неожиданного поведения - это то, что вы не можете найти тег, который, как вы знаете, находится в документе.в, но find_all() возвращает [] или find() возвращает None. Это еще одна распространенная проблема со встроенным анализатором HTML Python, который иногда пропускает теги, которые он не понимает. Опять же, решение заключается в установке lxmlили html5lib. "

Я пробовал разные методы парсера, но у меня возникла та же проблема.

from bs4 import BeautifulSoup
import requests

url = 'https://www.khanacademy.org/profile/DFletcher1990/'

res = requests.get(url)

soup = BeautifulSoup(res.content, "lxml")

print(soup.find_all('div', class_='profile-widget-section'))

Мой код возвращает [].

1 Ответ

0 голосов
/ 15 февраля 2019

Содержание страницы загружается с использованием JavaScript.Самый простой способ проверить, является ли содержимое динамическим, - это щелкнуть правой кнопкой мыши и просмотреть источник страницы и проверить, присутствует ли содержимое там.Вы также можете отключить JavaScript в своем браузере и перейти по URL.

Вы можете использовать селен , чтобы получить содержимое

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from bs4 import BeautifulSoup
driver = webdriver.Chrome(executable_path='/path/to/chromedriver')
driver.get("https://www.khanacademy.org/profile/DFletcher1990/")
element=WebDriverWait(driver, 20).until(EC.presence_of_element_located((By.XPATH ,'//*[@id="widget-list"]/div[1]/div[1]/div[2]/div/div[2]/table')))
source=driver.page_source
soup=BeautifulSoup(source,'html.parser')
user_info_table=soup.find('table', class_='user-statistics-table')
for tr in user_info_table.find_all('tr'):
    tds=tr.find_all('td')
    print(tds[0].text,":",tds[1].text) 

Вывод:

Date joined : 4 years ago
Energy points earned : 932,915
Videos completed : 372

Другая доступная опция (поскольку вы уже знакомы с запросами) - это использовать reports-html

from bs4 import BeautifulSoup
from requests_html import HTMLSession
session = HTMLSession()
r = session.get('https://www.khanacademy.org/profile/DFletcher1990/')
r.html.render(sleep=10)
soup=BeautifulSoup(r.html.html,'html.parser')
user_info_table=soup.find('table', class_='user-statistics-table')
for tr in user_info_table.find_all('tr'):
    tds=tr.find_all('td')
    print(tds[0].text,":",tds[1].text) 

Output

Date joined : 4 years ago
Energy points earned : 932,915
Videos completed : 372

Пока чтоДругой вариант - узнать, что делается ajax-запрос, эмулировать его и проанализировать ответ.Этот ответ не всегда должен быть JSON.Но в этом случае контент не отправляется в браузер через ответ Ajax.Он уже присутствует в источнике страницы.

enter image description here

Страница просто использует JavaScript для структурирования этой информации.Вы можете попытаться получить данные из этого тега сценария, это может потребовать некоторого регулярного выражения, а затем сделать json из строки.

...