「AI Python 系列」第 03 栏 · Python 爬虫实战 全栏 15 篇 · 零成本跟完 🍃 作者:梅雅达编程笔记 首发:CSDN
摘要: 有些网站找不到API接口,数据全靠JavaScript动态渲染,requests抓不到怎么办?上浏览器自动化。今天介绍DrissionPage——一个国产的浏览器自动化工具,比Selenium更好用、更快。教你打开页面、等待加载、点击按钮、滚动页面、截图,然后从渲染后的页面提取数据。最后对比直接请求API和浏览器自动化的适用场景,知道什么时候该用哪个。
前面几篇讲的 requests 很好用,但有个前提:数据要么在 HTML 里,要么有公开的 API 接口。
但总有些网站:
- 数据是 JavaScript 动态渲染的,F12 也找不到明显的 API
- 需要点击、滑动、登录等交互才能看到数据
- 反爬机制很严,requests 直接被拦
这时候就该上浏览器自动化了。
一、为什么选 DrissionPage
浏览器自动化的老前辈是 Selenium。但 Selenium 配置麻烦、API 设计反人类、速度慢。
DrissionPage 是国产的替代方案,基于 Chrome DevTools Protocol,特点:
- 配置简单:不用下载 chromedriver,不用配路径
- API 友好:语法直观,比 Selenium 好写
- 双模式:既能控制浏览器(像 Selenium),也能直接发请求(像 requests)
- 更快:比 Selenium 快不少
安装:
pip install DrissionPage
前提是你电脑上装了 Chrome 浏览器。
二、基础用法:打开页面、找元素
最简单的例子
from DrissionPage import ChromiumPage
# 创建页面对象
page = ChromiumPage()
# 打开网页
page.get("https://www.baidu.com")
# 找到搜索框,输入内容
search_box = page.ele("@name=wd")
search_box.input("Python 爬虫")
# 点击"百度一下"按钮
search_btn = page.ele("@id=su")
search_btn.click()
# 等待页面加载
page.wait.load_start()
# 获取当前页面标题
print(page.title)
# 关闭浏览器
page.quit()
就这么简单。不用配 driver,不用管版本对应。
元素定位方式
DrissionPage 的定位方式很灵活:
# CSS 选择器(和 BeautifulSoup 一样)
element = page.ele("css:div.class")
element = page.ele("css:#id")
element = page.ele("css:tag > child")
# 属性定位(简写)
element = page.ele("@name=wd") # name 属性等于 wd
element = page.ele("@id=su") # id 属性等于 su
element = page.ele("@class=item") # class 包含 item
# 文本定位
element = page.ele("text:百度一下") # 文本包含"百度一下"
element = page.ele("text:百度一下$") # 文本完全等于"百度一下"
# XPath
element = page.ele("xpath://div[@class='result']")
用哪个看你习惯,我个人喜欢 CSS 选择器 + 属性定位混着用。
三、实战:抓取动态渲染的页面
场景
假设我们要抓一个无限滚动的页面——比如某新闻网站的"加载更多"。
页面一开始只显示 10 条新闻,滑到底部会自动加载更多内容。
代码
from DrissionPage import ChromiumPage
import time
page = ChromiumPage()
page.get("https://example-news-site.com/") # 假设这是目标网址
# 等待初始内容加载
time.sleep(2)
# 滚动到底部,触发加载
all_news = []
last_height = 0
for i in range(5): # 滚动 5 次
# 滚动到页面底部
page.scroll.to_bottom()
time.sleep(2) # 等待新内容加载
# 检查页面高度是否变化(判断是否加载了新内容)
current_height = page.run_js("return document.body.scrollHeight")
if current_height == last_height:
print("没有更多内容了")
break
last_height = current_height
# 提取所有新闻
news_items = page.eles("css:div.news-item")
for item in news_items:
title = item.ele("css:h2").text if item.ele("css:h2") else ""
summary = item.ele("css:p.summary").text if item.ele("css:p.summary") else ""
link = item.ele("css:a").link if item.ele("css:a") else ""
if title:
all_news.append({
"标题": title,
"摘要": summary,
"链接": link
})
print(f"共抓取 {len(all_news)} 条新闻")
# 保存
import pandas as pd
df = pd.DataFrame(all_news)
df.to_csv("news_data.csv", index=False, encoding="utf-8-sig")
page.quit()
关键点
四、等待与截图
等待元素出现
有时候页面加载慢,元素还没渲染出来你就去抓,会报错。
# 等待某个元素出现,最多等 10 秒
element = page.ele("css:div.loading-done", timeout=10)
# 或者手动等待
page.wait.ele_displayed("css:div.content", timeout=10)
截图
调试的时候很有用:
# 全屏截图
page.get_screenshot(path="screenshot.png")
# 只截某个元素
element = page.ele("css:div.main")
element.get_screenshot(path="element.png")
全屏截图
只截某个元素 
五、双模式:浏览器 + 请求
DrissionPage 的一个特色是支持双模式切换。
有时候你只需要发个请求拿数据,不需要开浏览器:
from DrissionPage import SessionPage
# SessionPage 就像 requests,但语法统一
page = SessionPage()
page.get("https://api.example.com/data")
data = page.json
print(data)
或者在 ChromiumPage 里切换:
from DrissionPage import ChromiumPage
page = ChromiumPage()
# 浏览器模式
page.get("https://www.example.com")
title = page.title
# 切换到请求模式(快)
page.set.targets("session")
response = page.get("https://api.example.com/data")
data = response.json
# 切回浏览器模式
page.set.targets("browser")
page.get("https://www.another-site.com")
这个功能很实用:需要渲染的用浏览器,不需要渲染的直接请求,省资源。
六、对比:什么时候用哪个
| 数据在 HTML 里 | requests + BeautifulSoup | 最快,最简单 |
| 有公开 API 接口 | requests 直接请求 | 数据已结构化,省解析 |
| JavaScript 动态渲染,但能找到 API | requests 请求 API | 比浏览器快 |
| JavaScript 渲染,找不到 API | DrissionPage | 只能让浏览器帮你渲染 |
| 需要点击、滑动、登录 | DrissionPage | 浏览器自动化 |
| 反爬严,requests 被拦 | DrissionPage | 浏览器行为更像真人 |
原则:能用 requests 就不用浏览器。
浏览器自动化是最后的手段,因为它慢、吃资源、还可能被检测到。
七、完整代码:抓取 JS 动态渲染的名言网站
写一个完整的例子,用 DrissionPage 抓取一个必须靠浏览器执行 JavaScript 才能渲染出数据的页面,并翻页抓取多页内容:
"""
Day 06 示例代码:用 DrissionPage 抓取 JS 动态渲染的名言网站
作者:梅雅达编程笔记
"""
from DrissionPage import ChromiumPage
import time
import pandas as pd
def scrape_dynamic_page():
page = ChromiumPage()
try:
# 打开目标页面(名言由 JavaScript 动态渲染,requests 抓不到)
page.get("http://quotes.toscrape.com/js/")
# 等待第一条名言被 JS 渲染出来
page.wait.ele_displayed("css:.quote", timeout=10)
quotes = []
# 翻页抓取(最多抓 3 页)
for i in range(3):
# 提取当前页的名言
quote_elements = page.eles("css:.quote")
for q in quote_elements:
# 名言文本
text_ele = q.ele("css:.text")
if text_ele:
text = text_ele.text.strip()
# 作者
author_ele = q.ele("css:.author")
author = author_ele.text.strip() if author_ele else ""
# 标签
tag_eles = q.eles("css:.tag")
tags = "、".join([t.text.strip() for t in tag_eles]) if tag_eles else ""
# 去重
if text and not any(item["名言"] == text for item in quotes):
quotes.append({
"名言": text,
"作者": author,
"标签": tags
})
# 点击 "Next" 进入下一页
next_btn = page.ele("css:li.next > a", timeout=2)
if next_btn:
next_btn.click()
time.sleep(2)
page.wait.ele_displayed("css:.quote", timeout=10)
else:
print("没有下一页了")
break
# 保存
df = pd.DataFrame(quotes)
df.to_csv("quotes.csv", index=False, encoding="utf-8-sig")
print(f"共抓取 {len(quotes)} 条名言")
print("\\nTop 5:")
for i, q in enumerate(quotes[:5], 1):
print(f"{i}. {q['名言']}")
print(f" —— {q['作者']}")
finally:
page.quit()
if __name__ == "__main__":
scrape_dynamic_page()
说明:这个网站(quotes.toscrape.com)是专门给爬虫练习用的,结构稳定、不封 IP。/js/ 后缀的版本里,名言是通过 JavaScript 动态渲染的,用 requests 抓会拿到空页面,正好用来演示"为什么需要浏览器自动化"。
📊 本篇成本透明栏
| API 调用次数 | 0 |
| 消耗 Token | 0 |
| 成本 | ¥0 |
浏览器自动化也是本地操作,不花钱。
练手改造题
改造 1(基础): 用 DrissionPage 打开你常用的网站(比如 B 站、知乎),截图保存到本地,然后提取页面上所有的链接标题。
改造 2(进阶): 找一个需要"点击加载更多"的网站(比如微博、抖音),用 DrissionPage 模拟点击,抓取更多内容。
下期预告
Day 07 · Cookie 与 Session:处理登录状态
有些数据要登录才能看到。Day 07 讲 Cookie、Session、Token 是什么,怎么用 requests.Session 保持登录状态,怎么从浏览器复制 Cookie 绕过登录。
📚 资源与工具
- DrissionPage 文档: https://g1879823.gitlab.io/DrissionPage/
- DrissionPage GitHub: https://github.com/g1879823/DrissionPage
- 本专栏配套代码: CSDN 下载区(每篇更新)
- 梅雅达编程笔记: 专注 Python + AI 实战教程,提供数据采集与自动化定制服务
往期回顾
Day 01 · 爬虫能干啥不能干啥
Day 02 · 环境搭建与第一个爬虫
Day 03 · 列表页抓取:批量拿数据
Day 04 · 详情页 + 翻页:从一条到一百条
Day 05 · Ajax 请求拦截:抓看不到的数据
专栏推荐
- 「AI Python 系列」第 03 栏 · Python 爬虫实战(连载中)
- 「AI Python 系列」第 02 栏 · AI+数据可视化(连载中)
- 「AI Python 系列」第 01 栏 · AI+自动化办公(连载中)
资源领取
- 关注作者获取本栏完整代码和数据集
原创声明:本文为梅雅达编程笔记原创作品,未经允许不得转载。





