使用 Selenium 爬取动态网页数据 —— 实战与坑点详解

本文记录了笔者在爬取网页数据过程中遇到的各种技术挑战,包括页面动态渲染、JavaScript 注入等问题,并最终给出一个可运行的完整方案。

文章目录

    • 网页获取不到数据
    • 🚀 尝试用 Selenium 渲染页面

网页获取不到数据

某网页数据依赖大量 JavaScript 动态渲染。笔者最初尝试通过直接请求页面源代码的方法(如 requests)来获取页面中的源代码内容,看看HTML的网页结构,结果发现页面核心数据并未写死在 HTML 中,而是通过 JS 模块懒加载,并渲染到 DOM 后才可见。

如下为典型的 script 标签:

<script nonce="..." type="module" src="//c-cdn.qixin.com/web/_web/UbfmNsyd.js" crossorigin>
</script>

直接请求 HTML 无法获得数据的,使用 BeautifulSoup 解析 <script> 可能也没用,因为内容可以是异步加载、并由 JS 渲染进 DOM 。

下述是一个下载网页源代码保存到本地 html 的 python代码:

import requests# 目标网页 URL
url = '替换成你要爬的网页地址'# 自定义请求头,防止被识别为爬虫
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 ''(KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36'
}# 发送 GET 请求
response = requests.get(url, headers=headers)# 判断请求是否成功
if response.status_code == 200:# 保存为本地 HTML 文件with open('page.html', 'w', encoding='utf-8') as f:f.write(response.text)print("网页源代码已保存为 page.html")
else:print(f"请求失败,状态码: {response.status_code}")

保存到本地的HTML 文件:
在这里插入图片描述
所需要的数据都在 <script> 里面。

request库不能运行js代码,我们需要使用 selenium 借助浏览器运行js代码,完成dom的渲染。

🚀 尝试用 Selenium 渲染页面

为了解决数据渲染问题,我们使用 Selenium 启动一个真实的 Chrome 浏览器,让 JavaScript 有机会执行,待页面加载完毕后再提取数据

装包:

pip install selenium webdriver-manager
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from webdriver_manager.chrome import ChromeDriverManager
url = "https://www.qixin.com/company/7b752b1d-8d49-4a67-9472-04cef0b301ec"options = webdriver.ChromeOptions()## Chrome,无头模式(不弹窗)
# options.add_argument('--headless')  # 去掉这行可以看到浏览器
# options.add_argument('--disable-gpu')driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()), options=options
)driver.get(url)
input(">扫码登陆,确认开始?")# urls: 网址列表
for url in urls:lock = Falsewhile 1:try:driver.get(url)# 等待目标数据出现(最多等 30 秒)WebDriverWait(driver, 30).until(# EC.presence_of_element_located((By.CLASS_NAME, "table"))EC.presence_of_element_located((By.CSS_SELECTOR,"#__nuxt > div > ... > div > div.credit-number",)))lock = Falseexcept Exception as e:lock = Trueuser_input = input("在网页上验证码,输入 skip 跳过,否则继续运行").strip()if user_input == "skip":lock = Falseif lock == False:breaktext = driver.find_element(By.XPATH, '//*[@id="__nuxt"]/div/.../div[2]').text.strip()print(text)

值得注意的是 javascritps 如果需要加载外部的js文件,存在网络传输的时间,如果在 driver.get(url) 后立即调用 driver.find_element 则找不到对应的值,因为js还没有执行完毕。上述代码使用 WebDriverWait 等待 js 运行完成。

💡 小贴士(Tip):
把 WebDriverWait 换成 sleep 一个较长的时间也是可以的,因为本质上都是等待 js 运行完成,但更推荐 使用WebDriverWait 。

WebDriverWait(driver, 30).until(# EC.presence_of_element_located((By.CLASS_NAME, "table"))EC.presence_of_element_located((By.CSS_SELECTOR,"#__nuxt > div > ... > div > div.credit-number",))
)

#__nuxt > div > … > div > div.credit-number 是 网页上目标数据的 css。
上述代码 一直等待目标数据在网页上渲染完成,最多等待30秒。
等到目标数据渲染成功后,使用 driver.find_element 就可以得到正确的目标数据。

为了尽可能多地保留每一条数据,使用while循环重复请求每个url,直到获取到正确的目标数据才退出,如果遇到报错,会被 try except 捕获到异常,当代码正确执行,lock为False会跳出 while,爬取下一个 url。

每一次报错,都会被 input 中断,可能是需要用户在网页上输入验证码,用户在输入完验证码后,输入任意字符会继续爬取。若不是需要验证码,而是该网页报错(比如:404),那么用户可以输入 skip 实现跳过当前页面的爬取。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/80130.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【信息系统项目管理师】法律法规与标准规范——历年考题(2024年-2020年)

手机端浏览☞【信息系统项目管理师】法律法规与标准规范——历年考题&#xff08;2024年-2020年&#xff09; 2024年上半年综合知识【占比分值3′】 42、关于招标投标的描述&#xff0c;不正确的是&#xff08;属于同一集团组织成员的投标人可以按照该组织要求协同投标&#xf…

多模态大语言模型arxiv论文略读(五十六)

DesignQA: A Multimodal Benchmark for Evaluating Large Language Models’ Understanding of Engineering Documentation ➡️ 论文标题&#xff1a;DesignQA: A Multimodal Benchmark for Evaluating Large Language Models’ Understanding of Engineering Documentation …

Docker 渡渡鸟镜像同步站 使用教程

Docker 渡渡鸟镜像同步站 使用教程 &#x1f680; 介绍 Docker.aityp.com&#xff08;渡渡鸟镜像同步站&#xff09;是一个专注于为国内开发者提供 Docker 镜像加速和同步服务的平台。它通过同步官方镜像源&#xff08;如 Docker Hub、GCR、GHCR 等&#xff09;&#xff0c;为…

Unity:AddTorque()(增加旋转力矩)

目录 什么是 AddTorque()&#xff1f; 第一性原理出发&#xff1a;什么是 Torque&#xff08;力矩&#xff09;&#xff1f; Torque 公式 Unity 中 AddTorque 的工作原理 参数属性 &#x1f50d; Linear Drag&#xff08;线性阻力&#xff09; 线性阻力模拟的现实情况&…

async/await的另一种食用方法

在JavaScript/TypeScript的异步编程中&#xff0c;async/await让我们的代码看起来更像是同步的&#xff0c;极大地提高了可读性。然而&#xff0c;错误处理仍然是一个需要仔细考虑的问题。今天我要分享一种优雅的错误处理模式&#xff0c;它能让你的异步代码更加简洁。 传统tr…

计算机网络 - stp生成树实验

【实验假设】 我们使用 Cisco Packet Tracer 或类似的模拟软件&#xff0c;或物理的 Cisco 交换机。 交换机初始为默认配置&#xff08;或已通过 write erase 和 reload 清除配置&#xff09;。 PC 已配置 IP 地址如下&#xff08;示例&#xff09;&#xff1a; PC0: 192.168…

浅析 Spring 中 FactoryBean 的实现与使用

浅析 Spring 中 FactoryBean 的实现与使用 一、FactoryBean核心机制剖析二、高级应用场景与实战三、框架级应用案例解析四、FactoryBean常见面试题 一、FactoryBean核心机制剖析 1. 本质与双重角色 FactoryBean是Spring容器中用于定制化对象创建的核心接口&#xff08;org.spri…

vue3 element-plus 输入框回车跳转页面问题处理

问题描述&#xff1a; 当页面搜索条件只有一个的情况下&#xff0c;输入框不管有没有值&#xff0c;回车后会跳转页面 解决办法&#xff0c;给表单添加 submit.prevent <el-form ref"ruleForm" :model"search" label-width"120px" class&qu…

(51单片机)LCD展示动画(延时函数)(LCD1602教程)

前言&#xff1a; 前面我们说过&#xff0c;之前LCD1602模块有点难&#xff0c;但是现在&#xff0c;我们通过几遍博客的学习&#xff0c;今天来讲一下LCD1602的原理 演示视频&#xff1a; LCD1602流动 源代码&#xff1a; main.c #include <STC89C5xRC.H> #include &q…

深入了解 OpenIddict:实现 OAuth 2.0 和 OpenID Connect 协议的 .NET 库

在现代 Web 开发中&#xff0c;身份验证和授权是安全性的重要组成部分。随着对安全性的要求不断增加&#xff0c;OAuth 2.0 和 OpenID Connect&#xff08;OIDC&#xff09;协议已经成为许多应用程序的标准身份验证方式。而 OpenIddict&#xff0c;作为一个用于实现 OAuth 2.0 …

【C++游戏引擎开发】第30篇:物理引擎(Bullet)—软体动力学系统

一、软体动力学理论体系 1.1 连续体力学基础 1.1.1 变形梯度张量 物体运动可描述为映射函数: x = ϕ ( X , t ) \mathbf{x} = \phi(\mathbf{X},t) x

Android Compose 层叠布局(ZStack、Surface)源码深度剖析(14)

Android Compose 层叠布局&#xff08;ZStack、Surface&#xff09;源码深度剖析 一、引言 在 Android 应用开发领域&#xff0c;用户界面&#xff08;UI&#xff09;的设计与实现一直是至关重要的环节。随着技术的不断演进&#xff0c;Android Compose 作为一种全新的声明式…

性能优化实践:内存优化技巧

性能优化实践&#xff1a;内存优化技巧 在Flutter应用开发中&#xff0c;内存优化是提升应用性能的关键环节之一。本文将从实战角度深入探讨Flutter内存优化的各种技巧&#xff0c;帮助你构建高性能的Flutter应用。 一、内存分析工具使用 1. DevTools内存分析器 启动DevTool…

2025-05-07 Unity 网络基础8——UDP同步异步通信

文章目录 1 UDP 概述1.1 通信流程1.2 TCP 与 UDP1.3 UDP 分包1.4 UDP 黏包 2 同步通信2.1 服务端2.2 客户端2.3 测试 3 异步通信3.1 Bgin / End 方法3.2 Async 方法 1 UDP 概述 1.1 通信流程 ​ 客户端和服务端的流程如下&#xff1a; 创建套接字 Socket。用 Bind() 方法将套…

如何减少锁竞争并细化锁粒度以提高 Rust 多线程程序的性能?

在并发编程中&#xff0c;锁&#xff08;Lock&#xff09;是一种常用的同步机制&#xff0c;用于保护共享数据免受多个线程同时访问造成的竞态条件&#xff08;Race Condition&#xff09;。然而&#xff0c;不合理的锁使用会导致严重的性能瓶颈&#xff0c;特别是在高并发场景…

AGV智能搬运机器人:富唯智能引领工业物流高效变革

在智能制造与工业4.0深度融合的今天&#xff0c;物流环节的高效与精准已成为企业核心竞争力的关键。富唯智能凭借其自主研发的AGV智能搬运机器人&#xff0c;以创新技术重塑工业物流标准&#xff0c;助力企业实现降本增效的跨越式发展。 一、技术突破&#xff1a;精准导航与智能…

K8s 资源分类

K8s 资源分类图谱 内置资源的分类 1、工作负载相关&#xff1a; Pod&#xff1a;最小的部署单元&#xff0c;包含一个或多个容器。 Deployment&#xff1a;管理无状态应用的副本和滚动更新。 StatefulSet&#xff1a;适用于有状态应用&#xff08;如数据库&#xff09;&#…

VLM-AD:通过视觉语言模型监督实现端到端自动驾驶

《VLM-AD: End-to-End Autonomous Driving through Vision-Language Model Supervision》2024年12月发表&#xff0c;来自Cruise和美国东北大学的论文。 人类驾驶员依靠常识推理来驾驭多样化和动态的现实世界场景。现有的端到端&#xff08;E2E&#xff09;自动驾驶&#xff0…

目标检测中的损失函数(三) | SIoU WIoUv1 WIoUv2 WIoUv3

&#x1f680;该系列将会持续整理和更新BBR相关的问题&#xff0c;如有错误和不足恳请大家指正&#xff0c;欢迎讨论&#xff01;&#xff01;&#xff01; SCYLLA-IoU&#xff08;SIoU&#xff09;来自挂在2022年arxiv上的文章&#xff1a;《SIoU Loss: More Powerful Learnin…

http Status 400 - Bbad request 网站网页经常报 HTTP 400 错误,清缓存后就好了的原因

目录 一、HTTP 400 错误的常见成因(一)问题 URL(二)缓存与 Cookie 异常(三)请求头信息错误(四)请求体数据格式不正确(五)文件尺寸超标(六)请求方法不当二、清缓存为何能奏效三、其他可以尝试的解决办法(一)重新检查 URL(二)暂时关闭浏览器插件(三)切换网络环…