发布时间:2026/8/15 21:05:23
从“抓不到“到“抓得全“:requests-html网页解析实战,3招拿下JS动态数据 从抓不到到抓得全requests-html网页解析实战3招拿下JS动态数据【免费下载链接】requests-htmlPythonic HTML Parsing for Humans™项目地址: https://gitcode.com/gh_mirrors/re/requests-html凌晨一点同事把一段爬虫代码拍在我桌上帮我看下这个页面明明有数据我抓出来却是空的。他抓的是一个内部培训站的课程列表浏览器里整整齐齐排着三十行课程requests拿回来的 HTML 里却只有一张空壳。这种浏览器有、源码没有的诡异现象几乎每个做数据抓取的人都撞过——问题不在网络请求而在 JavaScript 渲染。这篇文章就用 requests-html 这个网页解析库从一次真实救火出发把静态抓取、JS 渲染、异步批量这三关逐一打通。先搞清抓不到的三种病因排查问题之前先给数据抓取做个快速体检。网页上的数据大体分三种对应三种完全不同的处理策略数据形态典型特征传统方案是否有效纯静态 HTML数据写在返回的源码里✅ 有效懒加载 / 异步接口滚动后 data 才从接口拉回❌ 拿不到JS 动态渲染DOM 由脚本生成❌ 拿不到同事抓的就是第三种。他的原方案是经典的三件套urlopen拿源码、正则抠字符串、BeautifulSoup 收尾。这套组合对付静态页面绰绰有余但遇到前端框架React/Vue 之类生成的页面就彻底哑火——服务端返回的是空骨架真正的数据要靠浏览器里的 JavaScript 去填充。要治这种病思路只有一条把发请求和跑浏览器合并成一件事。requests-html 干的就是这个活它外面套着 requests 的皮里面装着解析引擎还内置了一个无头 Chromium能在抓取时像真人浏览器一样把脚本执行完。第一关HTMLSession 取代裸 requests三行代码建会话先看最基础的动作。requests-html 对 requests 的老用户几乎零迁移成本把requests.get()换成session.get()即可返回的对象在请求能力之外多了一个会解析的.html属性from requests_html import HTMLSession session HTMLSession() response session.get(https://python.org/) # 这行是关键响应对象自带解析能力 page response.html # 一行拿到全部链接自动去重、剔除锚点 print(len(page.links)) print(len(page.absolute_links)) # 绝对地址版本HTMLSession并不是简单包一层它会自动模拟浏览器 User-Agent、自动跟随重定向、复用连接池、持久化 Cookie。这些特性在后面的反爬环节都会派上用场。第二关CSS 选择器与 XPath两把手术刀交替用会话建好了接下来是定位数据。requests-html 的find()方法在项目源码 requests_html.py 的BaseParser类中定义支持完整的 CSS 选择器语法用法和 jQuery 几乎一致# 取第一个 #about 元素 about page.find(#about, firstTrue) # 按 class 筛选所有链接 nav_links page.find(nav a) # 按属性筛选找所有外链 external page.find(a[href^http]) # 按包含文本筛选找含 python 的元素 matches page.find(containingpython)定位到元素后.text拿文本、.attrs拿属性字典、.html拿内层 HTML.links和.absolute_links拿元素内的链接集合。项目测试文件 tests/test_requests_html.py 里有一整套断言可以当用法速查表来读。习惯 XPath 的也不用纠结xpath()方法平行存在项目文档 docs/source/index.rst 里两者都有示例# XPath 同样支持拿整个文档根节点 root page.xpath(/html, firstTrue) print(root.attrs[class]) # 输出 no-js # 直接取所有 a 标签的 href 属性值列表 hrefs page.xpath(//a/href)第三关render() 唤醒沉睡的数据——真正的重头戏现在回到同事的问题。静态抓取解决了但目标站点是 JS 渲染的怎么办答案是render()方法——它在源码 requests_html.py 的HTML类中实现会启动无头 Chromium把页面完整执行一遍再拿回渲染后的 DOM# 渲染整页等 JS 跑完 response.html.render( retries3, # 加载失败自动重试 wait1, # 打开页面后先等 1 秒 scrolldown2, # 向下滚动 2 次触发懒加载 sleep1 # 每次滚动后歇 1 秒 ) # 渲染之后之前空荡荡的选择器终于有结果了 courses response.html.find(.course-item) print(f渲染后抓到 {len(courses)} 个课程)❗注意render()首次运行会往主目录~/.pyppeteer/下载一份 Chromium耗时几分钟之后就不再下载。在服务器上跑之前先确认磁盘和网络环境。render()的几个参数对应着真实用户的行为scrolldown模拟滚动很多页面滚动到哪才加载到哪、sleep给异步请求留出返回时间、retries兜底页面偶发超时。如果页面滚动后仍缺数据把scrolldown和sleep一起调大通常能解决九成问题。⚡进阶玩法render()还能直接执行自定义 JavaScript 并把返回值带回来等于在浏览器里装了个数据探头script () { const items document.querySelectorAll(.course-item); return items.map(el ({ title: el.querySelector(.title).textContent, url: el.querySelector(a).href, })); } result response.html.render(scriptscript) print(result) # 直接拿到结构化列表相对链接不用愁一个方法自动转绝对地址抓链接时最烦的一件事页面里全是/course/42这种相对路径存下来没法直接用。requests-html 内置的_make_absolute()同样定义在BaseParser中专门治这个测试文件里test_links就是靠它把 6 个相对链接全部转成了绝对地址from requests_html import HTML # 不经过网络直接解析 HTML 字符串也行 doc a href/course/42Python 入门/a html HTML(htmldoc, urlhttps://example.com/) # 相对路径自动拼接成完整 URL for link in html.links: print(link) # /course/42 print(html._make_absolute(link)) # https://example.com/course/42_make_absolute()的实现逻辑很实在没有域名就拼上基础地址有域名缺协议就补http(s)已经完整的原样返回。比自己手写urljoin省心得多。批量抓取提速AsyncHTMLSession 一次开多个页面同事的需求很快变成了帮我把十个栏目都抓下来。这时候逐页串行抓就太慢了——每页都要等渲染动辄几秒。requests-html 自带异步方案AsyncHTMLSession对应源码里的arender()方法import asyncio from requests_html import AsyncHTMLSession asession AsyncHTMLSession() async def fetch_courses(url): response await asession.get(url) # 异步渲染效果等同 render() await response.html.arender(scrolldown1, sleep1) return { url: response.html.url, count: len(response.html.find(.course-item)), } async def main(): urls [ https://example.com/python, https://example.com/data, https://example.com/web, ] # 并发跑起来各自返回结果 results await asyncio.gather(*[fetch_courses(u) for u in urls]) for r in results: print(r) asyncio.run(main())提示异步版本能并发但也要节制目标站点扛不住瞬时压力会直接把你 IP 拉黑。批量大时建议分批每批 5~10 个页面并加随机延时。把前面全串起来一个能直接跑的通关脚本下面这个脚本把三关全打通——静态抓取、JS 渲染、批量并发加上去重和结果输出就是同事最终交出去的版本from requests_html import HTMLSession, AsyncHTMLSession import asyncio BASE https://example.com/training def extract_from_page(html): 从渲染完成的页面里抠出课程清单 items [] for el in html.find(.course-item): title_el el.find(.title, firstTrue) link_el el.find(a, firstTrue) if title_el is not None: items.append({ title: title_el.text.strip(), url: html._make_absolute(link_el.attrs[href]), }) return items def fetch_static(url): 第一关不渲染直接抓静态内容 session HTMLSession() response session.get(url) session.close() return response.html def fetch_dynamic(url): 第二关渲染 JS 后再抓 session HTMLSession() response session.get(url) response.html.render(scrolldown2, sleep1) session.close() return response.html async def fetch_many(urls): 第三关异步并发批量抓 asession AsyncHTMLSession() async def one(url): response await asession.get(url) await response.html.arender(scrolldown1, sleep1) return extract_from_page(response.html) return await asyncio.gather(*[one(u) for u in urls]) if __name__ __main__: # 单页 渲染 html fetch_dynamic(f{BASE}/index.html) print(本页课程数:, len(extract_from_page(html))) # 批量异步 pages [f{BASE}/list/{i}.html for i in range(1, 4)] all_items asyncio.run(fetch_many(pages)) merged {item[url]: item for batch in all_items for item in batch} print(批量去重后共:, len(merged), 门课程) for item in list(merged.values())[:5]: print(-, item[title])三个实战中高频踩到的坑坑一抓回来还是空。先确认是不是render()没等够。用response.html.search(xxx...{}yyy)或直接len(html.text)对比渲染前后的内容量能快速判断没抓到还是没渲染完。项目 README 里那个 pythonclock 例子就是标准诊断流程。坑二被反爬拦截。先把render()停掉观察——有时数据其实在静态页里渲染反而触发风控。请求头方面HTMLSession默认已经带了浏览器风格的 User-Agent如果还不行在会话上手动补Accept和Accept-Language并优先通过 Cookie 保持会话状态。坑三下载音频、文件这类资源。抓链接只是第一步真正下载时注意用流式写入别一把梭进内存同时控制并发别让目标服务器过载。让这套抓取方案自己转起来同事的脚本最后跑在了服务器上配了一个简单的定时任务每天凌晨抓一次更新课程表数据落成 JSON 供内部系统消费。想更进一步你可以把抓下来的数据接上 SQLite 做增量归档、接到企业微信/钉钉机器人做变更推送或者把课程页面整页导出成 Markdown 存档。requests-html 的价值在于它把请求—解析—渲染揉成了一个顺手的小工具静态页面用find()动态页面加一个render()量大就换AsyncHTMLSession。同样的三板斧换成抓图片、抓视频、抓文档思路完全一致只是选择器里的标签名不同。下次再遇到浏览器有、源码没有的页面别急着上 Selenium 全家桶——先试试把浏览器塞进 requests 里三行代码问题可能就没了。【免费下载链接】requests-htmlPythonic HTML Parsing for Humans™项目地址: https://gitcode.com/gh_mirrors/re/requests-html创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

2026/8/15 21:05:23

Linux运维面试题

文章目录一、云计算与传统计算的区别?以吃包子为例:云计算又分为laaS、PaaS、SaaS总结:云计算的本质—《浪潮之巅第四版下册》二、云平台运维需要做哪些安全配置?1.安全组2.ECS主机3.Nginx反向代理4.数据安全第三方防护日志处理四…

2026/8/15 21:00:23

【实践案例】文档工程师帮助业务避坑案例

众所周知,参数类相关文档是技术性较强的文档,参数如何写才能体现公司产品的优势又巧妙的避免技术实现的不足呢?做为某大公司软件服务的文档顾问,我接到上司的需求,要求帮他新增一个性能实现的前提,具体内容…

2026/8/15 23:05:32

GPT-5.4暴击华尔街!白领工作灭绝时刻,美国5.7万科技岗位被血洗

昨天,发布了GPT-5.4,震惊了整个AI圈。 100万token所处的上下文环境, 「编程与智能体」所实现的巨大飞跃跨越情况界限, 原有的use现象或者情况, 所有关乎这类的这些诸多方面, 均全会根本改变AI智能体如今这种在局势上占一定地位状况形态。 「GPT-5.4&am…

2026/8/15 23:05:32

Python自动化监控网页更新并发送提醒

在跟进行业动态之际, 是不是老是忧心会错过关键的网页更新, 像竞争对手官网呈现新品发布的页面, 合作方政策调整所涉及的通知页面, 每日通过手动方式去刷新并查看着实耗费时间, 倘若有所遗漏便极有可能对业务决策造成影响。千万别让信息滞后致使工作节奏被拖缓, 它能够助力你自…

2026/8/15 23:05:32

机器学习泛化理论:均匀稳定性与无对数矩界推导

在机器学习理论中,算法的泛化能力是衡量其从训练数据学习并推广到未见数据的关键指标。一个核心问题是:我们能否仅通过算法在训练集上的表现,来严格地界定其在未知数据上的预期风险?这催生了泛化误差界的研究。其中,均…

2026/8/15 23:05:32

IT行业现状与未来趋势简单分析

你眼中的IT行业现状与未来趋势随着技术持续取得进步, IT行业已然成为推动全球经济以及社会发展的关键力量,涉及云计算、大数据、人工智能, 还有物联网、5G通信以及区块链, 这些技术正重塑我们生活与工作的方式, 你眼中IT行业的现状以及未来发展趋势是怎样的? 不管您…

2026/8/15 23:00:32

彻底解决MySQL中文变问号:从字符集原理到utf8mb4实战配置

1. 问题现象与根源剖析最近在帮一个朋友排查他们项目里的一个“灵异”事件:一个运行了好几年的后台系统,突然在某个新功能上线后,用户提交的中文内容存入数据库后,全部变成了问号“???”。开发团队一开始以为是新代码的锅&…

2026/8/15 9:46:30

如何快速生成中国车牌图片:Python开源工具完整指南

如何快速生成中国车牌图片:Python开源工具完整指南 【免费下载链接】chinese_license_plate_generator 中国车牌生成器 项目地址: https://gitcode.com/gh_mirrors/ch/chinese_license_plate_generator 中国车牌生成器是一个基于Python的开源项目&#xff0c…

2026/8/15 7:22:41

当 LLM 遇见大文档:主流开源项目如何处理上下文超限

从 Agentic Loop 到 Repo Map,七种策略与六类陷阱引言:128K vs 10MB 的硬冲突 2026 年的 LLM 上下文窗口已达到 128K ~ 1M token(≈ 0.5MB ~ 4MB 文本),但 LLM 想要处理的真实数据规模远远超过这个量级:真实…

2026/8/15 0:04:00

AI 电动婴儿车智能功率 辅助控制、电源管理的完整选型方案

2026年随着 AI 技术在电动孕婴童用品中的深度渗透(如智能避障、自适应速度控制、能量回收),电动婴儿车对功率器件提出更高要求:高效率、小型化、低功耗、高可靠性。微碧半导体(VBsemi)基于 Trench 及 SGT 工…

2026/8/15 0:04:00

论文AIGC检测不达标完整教程!低门槛用5款工具逐步复检!

论文提交前自己先查一遍AI率,是2026年毕业生的常规动作。学校要求论文AI率低于30%,乃至于20%才能答辩… 很多同学发现一个尴尬的事情:同一篇论文,知网查出来AI率35%,维普查可能是48%,大雅、朱雀又是另外的数…

2026/8/15 9:46:39

实测才敢推 AI论文网站 2026最新测评与推荐

2026年真正好用的AI论文网站,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。一、综…

2026/8/15 4:56:16

2026必备!AI论文网站测评:最新推荐与深度对比

2026年真正好用的AI论文网站,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。 一、…

2026/8/15 9:46:30

摆脱论文困扰!盘点2026年全网爆红的的AI论文写作工具

一天写完毕业论文在2026年已不再是天方夜谭。2026年最炸裂、实测能大幅提速的AI论文写作工具,覆盖选题构思、文献整理、内容生成、格式排版等核心场景,真正帮你高效搞定论文难题。 一、全流程王者:一站式搞定论文全链路(一天定稿首…