本文将介绍如何通过Playwright
连接Chrome
/Chromium
浏览器实现登录状态复用的方法。覆盖了Windows
和macOS
不同平台的具体操作。
1. 原理概述
1.1 本地浏览器复用原理
Playwright
提供了 connectOverCDP
方法,允许我们通过 Chrome DevTools Protocol (CDP)
连接到已打开的浏览器实例。这种方式可以直接复用浏览器的会话状态(如 cookies
、localStorage
等),从而避免重复登录。
1.2 环境要求
- • 支持浏览器:
Chrome
/Chromium
/Edge
等基于Chromium
内核的浏览器 - • 远程调试:需通过
--remote-debugging-port
参数启动浏览器 - • 登录准备:首次需手动登录目标网站
2. 浏览器安装与配置
2.1 检查浏览器安装路径
2.1.1 Windows
下安装路径
# 检查Chrome安装
where chrome
# 典型安装路径:
# C:\Program Files\Google\Chrome\Application\chrome.exe
2.1.2 MacOS
下安装路径
# 检查Chrome安装情况
ls /Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome
# 正确输出:
/Applications/Google Chrome.app/Contents/MacOS/Google Chrome
2.2 启动浏览器
2.2.1 Windows
下启动
# 强制终止所有Chrome进程(解决端口占用)
taskkill /IM chrome.exe /F /T
# 标准启动命令(注意路径转义)
& "C:\Program Files\Google\Chrome\Application\chrome.exe" `
--remote-debugging-port=9222 `
--user-data-dir="C:\chrome_debug_profile" `
--disable-extensions `
--disable-background-networking
2.2.2 MacOS
下启动
nohup /Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome \
--remote-debugging-port=9222 \
--user-data-dir=/tmp/chrome_dev_profile \
> /tmp/chrome.log 2>&1 &
参数解析:
- •
--user-data-dir
:创建独立用户目录,避免影响日常使用 - •
nohup
:保持后台运行 - • 输出日志到
/tmp/chrome.log
3. 实战代码实现
3.1 浏览器登录准备
3.1.1 按上述命令启动浏览器
例如MacOS
下,在命令行运行:
nohup /Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome \
--remote-debugging-port=9222 \
--user-data-dir=/tmp/chrome_dev_profile \
> /tmp/chrome.log 2>&1 &
3.1.2 手动登录
在刚才启动的Chrome
浏览器中,输入知乎网址,并手动登录。这里推荐二维码扫描方式,当然,输入用户名密码也是可以的。
# 输入知乎网址,并手动登录
https://www.zhihu.com/signin
3.1.3 保持浏览器运行状态
登录成功以后,保持浏览器运行专题(不要关闭)
3.2 实战代码
实现如下代码 zhihu3.js
并在命令行运行 node zhihu3.js
const { chromium } = require('playwright');
const { expect } = require('@playwright/test'); // 导入 expect
(async () => {
// 连接到已打开的 Chromium 浏览器实例
const browser = await chromium.connectOverCDP('http://127.0.0.1:9222');
const context = browser.contexts()[0]; // 获取默认的浏览器上下文
const page = context.pages()[0]; // 获取第一个页面
// 打开知乎首页
await page.goto('https://www.zhihu.com');
// 检查是否登录成功:验证页面中是否包含“进入创作中心”文本
try {
await expect(page.getByText('进入创作中心')).toBeVisible({ timeout: 15000 });
console.log('登录状态已恢复,可以开始爬取数据!');
} catch (error) {
console.log('登录状态恢复失败,请重新登录。');
await browser.close();
return;
}
// 等待推荐问题列表加载完成
await page.waitForSelector('.TopstoryItem');
// 抓取前 5 条推荐问题的标题
const questions = await page.$$eval('.TopstoryItem', (items) => {
return items.slice(0, 5).map((item) => {
const titleElement = item.querySelector('h2.ContentItem-title');
return titleElement ? titleElement.innerText.trim() : '无标题';
});
});
// 打印抓取到的问题标题
console.log('抓取到的前 5 条推荐问题:');
questions.forEach((question, index) => {
console.log(`${index + 1}. ${question}`);
});
// 关闭浏览器连接
await browser.close();
})();
3.3 代码说明
-
- 连接到已打开的浏览器实例:
- • 使用
chromium.connectOverCDP('http://127.0.0.1:9222')
连接到已启动的Chromium
浏览器实例。 - •
9222
是Chromium
的远程调试端口号。
-
- 获取浏览器上下文和页面:
- • 使用
browser.contexts()[0]
获取默认的浏览器上下文。 - • 使用
context.pages()[0]
获取第一个页面。
-
- 检查登录状态:
- • 使用
expect(page.getByText('进入创作中心')).toBeVisible()
验证页面中是否包含 进入创作中心 文本,确认登录状态。
-
- 抓取数据:
- • 使用
page.$$eval()
提取页面中的推荐问题标题。 - • 通过
slice(0, 5)
限制只抓取前5
条数据。
-
- 关闭连接:
- • 使用
browser.close()
关闭与浏览器的连接。
3.4 运行效果
参考如下截图:
4. 常见问题排查
4.1 端口占用问题
Windows
# Windows查看端口占用
netstat -ano | findstr :9222
MacOS
# macOS/Linux查看端口占用
lsof -i :9222
- • 如果端口
9222
被占用,可以更改为其他端口号,例如--remote-debugging-port=9223
。
4.2 连接失败排查
-
- 检查防火墙设置(
Windows
需放行端口)
- 检查防火墙设置(
-
- 确保使用相同浏览器类型(连接
Chromium
时不要用Chrome
路径)
- 确保使用相同浏览器类型(连接
-
- 验证浏览器版本与
Playwright
兼容性
- 验证浏览器版本与
4.3 页面结构变化:
- • 如果知乎的页面结构发生变化(例如
.TopstoryItem
或h2.ContentItem-title
的类名改变),需要同步更新脚本中的选择器。
4.4 动态加载内容:
- • 如果推荐问题是动态加载的(例如滚动页面时加载更多),可以使用
page.waitForSelector()
或page.evaluate()
结合滚动操作来加载更多内容。
总之,要注意
-
- 确保浏览器已启动:
- • 在运行脚本之前,确保
Chrome/Chromium
浏览器已启动,并且启用了远程调试功能。
-
- 浏览器成功登录了目标网站(知乎)
-
- 代码运行中,不要随意关闭浏览器。
6. 总结
通过连接本地浏览器并复用登录状态,我们可以避免每次运行脚本时都需要重新登录,尤其是在需要验证码的网站(如知乎)中非常实用。这种方法不仅提高了爬虫的效率,还降低了被反爬机制检测到的风险。
和之前保存登录状态道文件再复用的方法相比,本方法减少了脚本登录成功的保存代码编写,直接复用手工登录的结果,更加方便快捷。当然本方法也有局限性,那就是目前只在Google Chrome/Edge/Chromium
浏览器上支持。
文章来源:微信公众号-Playwright实战教程,原始发表时间:2025年01月27日。