Почему я получаю только данные первой страницы при использовании селена? - PullRequest
2 голосов
/ 05 апреля 2019

Я использую пакет python selenium для автоматического нажатия кнопки «загрузить еще», что успешно. Но почему я не могу получить данные после «загрузить еще»?

Я хочу сканировать обзоры из imdb, используя python. Он отображает только 25 отзывов, пока я не нажму кнопку «загрузить еще». Я использую пакет python selenium для автоматического нажатия кнопки «загрузить еще», что успешно. Но почему я не могу получить данные после «загрузить больше» и просто повторно получить первые 25 отзывов?

import requests
from bs4 import BeautifulSoup
from selenium import webdriver      
import time



seed = 'https://www.imdb.com/title/tt4209788/reviews'
movie_review = requests.get(seed)
PATIENCE_TIME = 60
LOAD_MORE_BUTTON_XPATH = '//*[@id="browse-itemsprimary"]/li[2]/button/span/span[2]' 

driver = webdriver.Chrome('D:/chromedriver_win32/chromedriver.exe')
driver.get(seed)

while True:
    try:
        loadMoreButton = driver.find_element_by_xpath("//button[@class='ipl-load-more__button']")

        review_soup = BeautifulSoup(movie_review.text, 'html.parser')
        review_containers = review_soup.find_all('div', class_ ='imdb-user-review')
        print('length: ',len(review_containers))
        for review_container in review_containers:
            review_title = review_container.find('a', class_ = 'title').text
            print(review_title)

        time.sleep(2)
        loadMoreButton.click()
        time.sleep(5)
    except Exception as e:
        print(e)
        break

print("Complete")

Мне нужны все отзывы, но теперь я могу получить только первые 25.

Ответы [ 2 ]

2 голосов
/ 05 апреля 2019

У вас есть несколько проблем в вашем скрипте. Жестко заданное ожидание очень противоречиво и, безусловно, является худшим вариантом. То, как вы записали свою логику очистки в цикле while True:, замедлит процесс анализа, собирая одни и те же элементы снова и снова. Более того, каждый заголовок приводит к огромному разрыву строк в выводе, который необходимо правильно удалить. Я немного изменил ваш сценарий, чтобы отразить предложение, которое я дал выше.

Попробуйте получить желаемый результат:

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

URL = "https://www.imdb.com/title/tt4209788/reviews"

driver = webdriver.Chrome()
wait = WebDriverWait(driver,10)

driver.get(URL)
soup = BeautifulSoup(driver.page_source, 'lxml')

while True:
    try:
        driver.find_element_by_css_selector("button#load-more-trigger").click()
        wait.until(EC.invisibility_of_element_located((By.CSS_SELECTOR,".ipl-load-more__load-indicator")))
        soup = BeautifulSoup(driver.page_source, 'lxml')
    except Exception:break

for elem in soup.find_all(class_='imdb-user-review'):
    name = elem.find(class_='title').get_text(strip=True)
    print(name)

driver.quit()
0 голосов
/ 05 апреля 2019

Ваш код в порядке.Отлично даже.Но вы никогда не получите «обновленный» HTML-код для веб-страницы после нажатия кнопки «Загрузить еще».Вот почему вы постоянно получаете одни и те же 25 обзоров.

Когда вы используете Selenium для управления веб-браузером, вы нажимаете кнопку «Загрузить еще».Это создает XHR-запрос (или более часто называемый AJAX-запрос), который вы можете увидеть на вкладке «Сеть» инструментов разработчика вашего веб-браузера.

Суть в том, что JavaScript (который запускается в веб-браузере ) обновляет страницу.Но в вашей программе на Python вы получаете только HTML один раз для страницы, статически использующей библиотеку запросов.

seed = 'https://www.imdb.com/title/tt4209788/reviews'
movie_review = requests.get(seed) #<-- SEE HERE? This is always the same HTML. You fetched in once in the beginning.
PATIENCE_TIME = 60

Чтобы решить эту проблему, вам нужно использовать Selenium, чтобы получить innerHTMLокна div, содержащего отзывы.Затем заставьте BeautifulSoup снова проанализировать HTML.Мы хотим избегать повторного захвата HTML-кода всей страницы, поскольку требуются вычислительные ресурсы для многократного анализа обновленного HTML-кода.

Итак, найдите div на странице, содержащей обзоры, ипроанализируйте это снова с BeautifulSoup.Примерно так должно работать:

while True:
    try:
        allReviewsDiv = driver.find_element_by_xpath("//div[@class='lister-list']")
        allReviewsHTML = allReviewsDiv.get_attribute('innerHTML')
        loadMoreButton = driver.find_element_by_xpath("//button[@class='ipl-load-more__button']")
        review_soup = BeautifulSoup(allReviewsHTML, 'html.parser')
        review_containers = review_soup.find_all('div', class_ ='imdb-user-review')
        pdb.set_trace()
        print('length: ',len(review_containers))
        for review_container in review_containers:
            review_title = review_container.find('a', class_ = 'title').text
            print(review_title)

        time.sleep(2)
        loadMoreButton.click()
        time.sleep(5)
    except Exception as e:
        print(e)
        break
...