0


Python 爬虫技术 第19节 Selenium和动态网页抓取

Selenium 是一个强大的自动化测试工具,它最初是为了进行 web 应用的功能性测试而设计的。然而,由于它可以模拟真实用户的行为与浏览器交互,因此也被广泛应用于动态网页的爬取中。

在处理动态网页时,传统的爬虫方法(如使用

requests

BeautifulSoup

)可能无法获取到完整的页面内容,因为这些页面的内容是通过 JavaScript 动态加载的。Selenium 可以驱动浏览器执行 JavaScript 代码,从而能够获取到完全加载后的页面内容。

下面是一个使用 Python 和 Selenium 进行动态网页抓取的基本步骤:

安装必要的库

首先确保安装了

selenium

库。可以使用 pip 安装:

pip install selenium

还需要下载与你的浏览器版本兼容的 WebDriver。例如,如果你使用的是 Chrome 浏览器,那么你需要下载 ChromeDriver 并将其路径添加到系统 PATH 中。

示例代码

这里是一个简单的示例,演示如何使用 Selenium 抓取一个动态生成的网页:

  1. 导入必要的模块:
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
import time
  1. 设置 WebDriver:
options = webdriver.ChromeOptions()# 如果需要无头模式(不打开浏览器窗口)# options.add_argument('headless')
driver = webdriver.Chrome(options=options)
  1. 导航到目标网址:
url ='https://example.com'
driver.get(url)
  1. 等待元素加载:
try:
    element = WebDriverWait(driver,10).until(
        EC.presence_of_element_located((By.ID,"some_element_id")))finally:print("Element loaded.")
  1. 提取数据:
data = driver.find_elements(By.CSS_SELECTOR,'.some_class .another_class')for item in data:print(item.text)
  1. 关闭浏览器:
driver.quit()

解释

  • WebDriver: Selenium 使用 WebDriver 与浏览器交互。在上面的例子中,我们使用了 ChromeDriver。
  • 等待元素: 使用 WebDriverWaitexpected_conditions 来等待某些元素加载完成,这有助于避免因为元素未加载完成而导致的错误。
  • 提取数据: 使用 find_elements 方法来查找页面上的元素,并从中提取数据。

注意事项

  • 性能问题: 使用 Selenium 爬取动态网站会比传统的方法慢得多,因为它实际上是在启动一个真实的浏览器实例。
  • 反爬虫策略: 许多网站都有反爬虫机制,使用 Selenium 也可能会遇到 IP 封锁、验证码等问题。
  • 资源消耗: 启动浏览器实例会占用较多的系统资源,对于大规模爬取任务,可能需要考虑使用更轻量级的解决方案,或者分布式爬取。

以上就是使用 Selenium 进行动态网页抓取的一个简单介绍。如果有具体的网站想要抓取,可以根据实际情况调整上述代码中的选择器和等待条件等。

当然可以。让我们基于之前的示例进一步扩展代码,实现一个更加完整的动态网页抓取脚本。在这个例子中,我们将抓取一个假设的网站,该网站在滚动后加载更多内容。

我们将添加如下功能:

  1. 模拟滚动页面到底部,以便加载所有内容。
  2. 提取特定的数据点。
  3. 处理异常情况。

下面是扩展后的完整代码:

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 selenium.common.exceptions import TimeoutException
import time

defget_driver():# 设置 Chrome 的选项
    options = webdriver.ChromeOptions()# 如果需要无头模式(不打开浏览器窗口)# options.add_argument('headless')# 创建 WebDriver 实例
    driver = webdriver.Chrome(options=options)return driver

defwait_for_element(driver, by, value, timeout=10):try:
        element = WebDriverWait(driver, timeout).until(
            EC.presence_of_element_located((by, value)))return element
    except TimeoutException:print(f"Element not found after {timeout} seconds.")returnNonedefscroll_to_bottom(driver, interval=3):# 获取当前页面的高度
    last_height = driver.execute_script("return document.body.scrollHeight")whileTrue:# 滚动到页面底部
        driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")# 等待页面加载
        time.sleep(interval)# 计算新高度并比较
        new_height = driver.execute_script("return document.body.scrollHeight")if new_height == last_height:break
        last_height = new_height

defmain():
    url ='https://example.com'# 替换为目标网站的 URL
    driver = get_driver()try:
        driver.get(url)# 等待特定元素加载完成
        element = wait_for_element(driver, By.ID,"some_element_id")if element isNone:raise Exception("Required element not found.")# 模拟滚动加载更多内容
        scroll_to_bottom(driver)# 提取数据
        data_elements = driver.find_elements(By.CSS_SELECTOR,".item-class")for element in data_elements:print(element.text)except Exception as e:print(f"An error occurred: {e}")finally:
        driver.quit()if __name__ =="__main__":
    main()

代码解释

  1. get_driver(): 设置 Chrome 驱动程序。
  2. wait_for_element(): 等待指定的元素出现。
  3. scroll_to_bottom(): 模拟滚动至页面底部的动作。 - 使用 JavaScript 执行 window.scrollTo(0, document.body.scrollHeight); 来滚动页面。- 每次滚动后等待一段时间让页面加载新内容。- 重复这个过程直到页面不再增长。
  4. main(): 主函数,包含整个流程。 - 初始化 WebDriver。- 导航到目标网站。- 等待关键元素出现。- 滚动页面到底部。- 提取数据。- 关闭 WebDriver。

注意事项

  • 异常处理: 我们使用了 try-except 块来捕获可能出现的异常,比如元素找不到或网络连接问题。
  • 性能优化: 对于大型网站,滚动间隔时间可能需要适当增加,以确保页面有足够的时间加载所有内容。
  • 资源管理: 在脚本结束时,确保通过 driver.quit() 释放资源。

请根据实际的目标网站调整 CSS 选择器、等待条件等。如果需要进一步的帮助,请告诉我具体的目标网站和想要抓取的数据类型。

好的,我们可以进一步完善代码,使其更加健壮并且能够处理更多的异常情况。同时,我们可以加入一些额外的功能,比如日志记录和重试机制。

以下是改进后的代码:

import logging
import time
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 selenium.common.exceptions import TimeoutException, NoSuchElementException
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager

defsetup_logger(name, log_file, level=logging.INFO):"""创建日志记录器"""
    formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
    handler = logging.FileHandler(log_file)
    handler.setFormatter(formatter)
    
    logger = logging.getLogger(name)
    logger.setLevel(level)
    logger.addHandler(handler)return logger

defget_driver():"""初始化 WebDriver"""
    options = webdriver.ChromeOptions()# options.add_argument('headless')  # 无头模式# 自动管理 ChromeDriver 版本
    service = Service(ChromeDriverManager().install())
    driver = webdriver.Chrome(service=service, options=options)return driver

defwait_for_element(driver, by, value, timeout=10):"""等待元素出现"""try:
        element = WebDriverWait(driver, timeout).until(
            EC.presence_of_element_located((by, value)))return element
    except TimeoutException:
        logger.error(f"Element not found after {timeout} seconds.")returnNonedefscroll_to_bottom(driver, interval=3, max_attempts=3):"""滚动到页面底部,直到没有新内容加载为止"""
    attempts =0
    last_height = driver.execute_script("return document.body.scrollHeight")while attempts < max_attempts:# 滚动到页面底部
        driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")# 等待页面加载
        time.sleep(interval)# 计算新高度并比较
        new_height = driver.execute_script("return document.body.scrollHeight")if new_height == last_height:
            attempts +=1else:
            attempts =0
            last_height = new_height

    if attempts >= max_attempts:
        logger.warning("Reached maximum scroll attempts without new content.")defextract_data(driver):"""提取页面上的数据"""try:
        data_elements = driver.find_elements(By.CSS_SELECTOR,".item-class")for element in data_elements:print(element.text)except NoSuchElementException:
        logger.error("No data elements found.")defmain():
    url ='https://example.com'# 替换为目标网站的 URL
    logger = setup_logger('web_scraper','scraper.log')

    driver = get_driver()try:
        driver.get(url)# 等待特定元素加载完成
        element = wait_for_element(driver, By.ID,"some_element_id")if element isNone:raise Exception("Required element not found.")# 模拟滚动加载更多内容
        scroll_to_bottom(driver)# 提取数据
        extract_data(driver)except Exception as e:
        logger.error(f"An error occurred: {e}")finally:
        driver.quit()if __name__ =="__main__":
    main()

新增功能

  1. 日志记录:- 使用 logging 模块记录日志信息。- 日志文件名为 scraper.log,你可以根据需要更改文件名和日志级别。
  2. 自动管理 ChromeDriver:- 使用 webdriver_manager 自动安装和管理 ChromeDriver,无需手动下载和配置路径。
  3. 重试机制:- 在 scroll_to_bottom 函数中增加了最大尝试次数,以防止无限循环。
  4. 异常处理:- 在 extract_data 函数中加入了对 NoSuchElementException 的处理。
  5. 更详细的错误信息:- 当发生异常时,将详细信息记录到日志文件中。

使用说明

  • 日志文件: 更改 setup_logger 函数中的 log_file 参数来指定日志文件的位置。
  • 无头模式: 若要启用无头模式(即不显示浏览器窗口),取消注释 options.add_argument('headless') 行。
  • 目标网站: 替换 url 变量中的 URL 为你想要抓取的实际网站地址。
  • CSS 选择器: 根据实际的 HTML 结构修改 .item-class 选择器。

请根据实际需求调整这些参数,并确保你的环境已经安装了必要的库(如

webdriver_manager

)。如果需要进一步的帮助或有其他具体需求,请随时告诉我。

标签: python 爬虫 selenium

本文转载自: https://blog.csdn.net/hummhumm/article/details/140732372
版权归原作者 hummhumm 所有, 如有侵权,请联系我们删除。

“Python 爬虫技术 第19节 Selenium和动态网页抓取”的评论:

还没有评论