【问题标题】:Why do I only get first page data when using selenium?为什么我在使用 selenium 时只获得首页数据?
【发布时间】:2019-08-26 21:17:45
【问题描述】:

我使用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 条。

【问题讨论】:

    标签: python selenium-webdriver web-scraping


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

      您的代码很好。甚至很棒。但是,在点击“加载更多”按钮后,您永远不会获取网页的“更新”HTML。这就是为什么您总是得到相同的 25 条评论。

      当您使用 Selenium 控制网络浏览器时,您点击的是“加载更多”按钮。这将创建一个 XHR 请求(或更通常称为 AJAX 请求),您可以在 Web 浏览器的开发人员工具的“网络”选项卡中看到该请求。

      底线是JavaScript(在网络浏览器中运行)更新页面。但是在您的 Python 程序中,您只能使用 Requests 库静态地获取页面的 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
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-12-08
        • 2021-07-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-10-22
        • 2013-11-26
        相关资源
        最近更新 更多