欢迎光临
我们一直在努力

Day 06 · 浏览器自动化:DrissionPage 实战

「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()

关键点

  • page.scroll.to_bottom():滚动到页面底部
  • time.sleep(2):等待新内容加载,别太急
  • page.eles():返回所有匹配的元素列表(注意是 eles 不是 ele)
  • element.text:获取元素文本
  • element.link:获取链接的 href 属性

  • 四、等待与截图

    等待元素出现

    有时候页面加载慢,元素还没渲染出来你就去抓,会报错。

    # 等待某个元素出现,最多等 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+自动化办公(连载中)

    资源领取

    • 关注作者获取本栏完整代码和数据集

    原创声明:本文为梅雅达编程笔记原创作品,未经允许不得转载。

    赞(0)
    未经允许不得转载:171主机测评 » Day 06 · 浏览器自动化:DrissionPage 实战
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址