BeautifulSoup не извлекает все данные

#python #web-scraping #beautifulsoup

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

Вопрос:

Я пытаюсь получить все комментарии от пользователя reddit с помощью beautifulsoup. Вот код:

 from urllib.request import urlopen as ureq
from bs4 import BeautifulSoup as soup

url = "https://www.reddit.com/user/IHateTheLetterF/"
client = ureq(url)

page_html = client.read()



pagesoup = soup(page_html, "html5lib")

comments = pagesoup.findAll("p",{"class":"_1qeIAgB0cPwnLhDF9XSiJM"})

 

Это работает, если я пытаюсь получить некоторые комментарии, но по какой-то причине он извлекает только 16 комментариев, а у пользователя явно больше 16 комментариев. Я пробовал использовать разные анализаторы, такие как lxml, html.parser и html5lib, но все они извлекают только 16 комментариев. Как ни странно, тот же самый код вчера получил 22 комментария. Любая помощь будет оценена

Ответ №1:

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

Вместо этого вы должны использовать selenium с webdriver для загрузки всех комментариев перед очисткой.

Вы можете попробовать загрузить исполняемый файл ChromeDriver здесь . И если вы вставите его в ту же папку, что и ваш скрипт, вы можете запустить:

Редактировать: использование скроллера custon для принудительной загрузки новых комментариев на страницу

 import os
import time
from selenium import webdriver
from bs4 import BeautifulSoup

# configure driver
chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument("--headless")
chrome_driver = os.getcwd()   "\chromedriver.exe"
driver = webdriver.Chrome(options=chrome_options, executable_path=chrome_driver)

url = "https://www.reddit.com/user/IHateTheLetterF/comments/"
driver.get(url)
scroll_pause_time = 3  # You can try with your own pause time.

screen_height = driver.execute_script("return window.screen.height;")  # get screen height
i = 1

while True:
    driver.execute_script("window.scrollTo(0, {screen_height}*{i});".format(screen_height=screen_height, i=i))  # scroll screen height
    i  = 1  # times looped
    time.sleep(scroll_pause_time)  # wait content to load
    scroll_height = driver.execute_script("return document.body.scrollHeight;")  # check current scroll height
    
    # Check your content
    soup = BeautifulSoup(driver.page_source, "html.parser")
    comments = soup.findAll("p", {"class": "_1qeIAgB0cPwnLhDF9XSiJM"})
    print(len(comments))
    
    # Finish loops when you cant scroll anymore
    if (screen_height) * i > scroll_height:
        break 
 

Я позволил ему работать в течение нескольких минут и уже получил более 200 комментариев.

Хотя это может сработать, я предлагаю вам поискать propper API для этого.

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

1. Это, безусловно, лучше, чем раньше, но очевидно, что у пользователя более 60 комментариев?

2. По-видимому, reddit использует бесконечную систему прокрутки. Я отредактирую ответ, чтобы создать пользовательский скроллер, но вам следует проверить наличие API-интерфейсов propper