为什么在使用硒时仅获得首页数据?

时间:2019-04-05 02:25:51

标签: python selenium-webdriver web-scraping

我使用python软件包selenium自动单击“加载更多”按钮,这是成功的。但是,为什么在“加载更多”后无法获取数据?

我想使用python从imdb检索评论。它只显示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 个答案:

答案 0 :(得分:2)

您的脚本中有几个问题。硬编码的等待非常不一致,并且肯定是最糟糕的选择。在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()

答案 1 :(得分:0)

您的代码很好。太好了。但是,在单击“加载更多”按钮后,您再也不会获取网页的“更新的” HTML。这就是为什么您总是得到相同的25条评论的原因。

使用Selenium来控制Web浏览器时,您正在单击“加载更多”按钮。这将创建一个XHR请求(或更常用的AJAX请求),您可以在Web浏览器开发人员工具的“网络”标签中看到该请求。

最重要的是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来获取包含评论的div框的innerHTML。然后,让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