pyppeteer -- python版本的puppeteer,一个强大的chronium headless浏览器API
最近搞天猫用了一波儿,记录一下。
先上文档: https://miyakogi.github.io/pyppeteer/
举个最简单的例子入门一下:
比如打开百度,然后截图
# coding:utf8
import asyncio
from pyppeteer import launch async def main():
launch_kwargs = {
# 默认无头模式
# "headless": False,
}
# 启动浏览器
browser = await launch(launch_kwargs)
# 打开标签页
page = await browser.newPage()
# 输入网址并打开
await page.goto("http://www.baidu.com")
# 获取页面元素
title = await page.title()
print(title)
# 关闭浏览器
await browser.close()
return asyncio.get_event_loop().run_until_complete(main())
下面说一些小技巧:
1、启动参数
launch_kwargs = {
# 控制是否为无头模式
"headless": False,
# chrome启动命令行参数
"args": [
# 浏览器代理 配合某些中间人代理使用
"--proxy-server=http://127.0.0.1:8008",
# 最大化窗口
"--start-maximized",
# 取消沙盒模式 沙盒模式下权限太小
"--no-sandbox",
# 不显示信息栏 比如 chrome正在受到自动测试软件的控制 ...
"--disable-infobars",
# log等级设置 在某些不是那么完整的系统里 如果使用默认的日志等级 可能会出现一大堆的warning信息
"--log-level=3",
# 设置UA
"--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36",
],
# 用户数据保存目录 这个最好也自己指定一个目录
# 如果不指定的话,chrome会自动新建一个临时目录使用,在浏览器退出的时候会自动删除临时目录
# 在删除的时候可能会删除失败(不知道为什么会出现权限问题,我用的windows) 导致浏览器退出失败
# 然后chrome进程就会一直没有退出 CPU就会狂飙到99%
"userDataDir": "",
}
注意:同一个用户目录(userDataDir)不能被两个chrome进程使用,如果你要多开,记得分别指定用户目录。否则会报编码错误。
2、设置viewport
自动获取当前屏幕大小并设置viewport
# coding:utf8
import asyncio
from pyppeteer import launch def screen_size():
"""使用tkinter获取屏幕大小"""
import tkinter
tk = tkinter.Tk()
width = tk.winfo_screenwidth()
height = tk.winfo_screenheight()
tk.quit()
return width, height async def main():
launch_kwargs = {
"headless": False
}
# 启动浏览器
browser = await launch(launch_kwargs)
# 打开标签页
page = await browser.newPage()
# 默认 800 * 600 一般是不够的
print(page.viewport)
#
width, height = screen_size()
# 设置网页可视区域大小
await page.setViewport({
"width": width,
"height": height
})
await browser.close()
return asyncio.get_event_loop().run_until_complete(main())
3、导出或加载cookie
# 取出cookie
cookies = await page.cookies()
# 这里可以做些什么 :)
pass
# 然后导入cookie
await page.setCookie(*cookies)
4、选择器
让人极度舒适的一个特性:
使用 page.querySelector如果没有找到指定的对象,则返回None,而不是抛出异常。不管规范不规范,反正比selenium爽多了。
5、hook
在页面开始加载前注入js代码,例如修改掉webdriver属性,让天猫检测不到
# coding:utf8
import asyncio
from pyppeteer import launch async def main():
launch_kwargs = {
"headless": False
}
# 启动浏览器
browser = await launch(launch_kwargs)
# 打开标签页
page = await browser.newPage()
page.evaluateOnNewDocument("""
var _navigator = {};
for (name in window.navigator) {
if (name != "webdriver") {
_navigator[name] = window.navigator[name]
}
}
Object.defineProperty(window, 'navigator', {
get: ()=> _navigator,
})
""")
#
page.goto("http://www.tmall.com") await browser.close()
return asyncio.get_event_loop().run_until_complete(main())
6、关于各种事件的isTrusted
这个js事件属性,用js是无法伪造的,但是用pyppeteer发生的各种操作所触发的事件,是完全真实的,这个归功于CDP吧。
7、卡死
如果在操作过程中不小心点击了某个a标签,导致浏览器新打开了一个标签页,而你的代码还在傻乎乎的使用之前的page对象做操作的时候,整个进程就卡住了
没有超时、没有异常、就是完全的不知道在干啥
当你把新开的标签页手动关闭后,一切就恢复原样。
tips:
避免这种情况的发生,其实也很简单,就是在每个可能误操作点击导致新开标签页的行为后面都强制关闭一下其他标签页:
比如:
# 关闭其他标签页
for _page in await browser.pages():
if _page != page:
_page.close()