注意,讲解的模块叫做 Pyppeteer,不是 Puppeteer。
Puppeteer 是 Google 基于 Node.js 开发的一个工具,有了它我们可以通过 JavaScript 来控制 Chrome 浏览器的一些操作,当然也可以用作网络爬虫上,其 API 极其完善,功能非常强大。
而 Pyppeteer 又是什么呢?它实际上是 Puppeteer 的 Python 版本的实现,但他不是 Google 开发的,是一位来自于日本的工程师依据 Puppeteer 的一些功能开发出来的非官方版本。
pip install pyppeteer -i https://pypi.douban.com/simple
国内无法访问 可以使用国内镜像
chromium下载地址:https://npm.taobao.org/mirrors/chromium-browser-snapshots/
下载之后解压之后,通过executablePath
属性指定运行浏览器了
我这里上传了到了csdn你也可以从这下
https://download.csdn.net/download/qq_27648991/12513423
可以参考puppeteer官方文档,因为pyppeteer的语法跟他一样
#!/usr/bin/python
# -*- coding: UTF-8 -*-
"""
@time:2020/04/04
"""
import asyncio
from pyppeteer import launch
async def main():
# 浏览器 启动参数
start_parm = {
# 启动chrome的路径
"executablePath": r"C:\Users\yq\AppData\Local\pyppeteer\pyppeteer\local-chromium\722234\chrome-win\chrome.exe",
# 关闭无头浏览器 默认是无头启动的
"headless": False,
}
# 创建浏览器对象,可以传入 字典形式参数
browser = await launch(**start_parm)
# 创建一个页面对象, 页面操作在该对象上执行
page = await browser.newPage()
await page.goto('https://www.httpbin.org/headers') # 页面跳转
page_text = await page.content() # 页面内容
print(page_text)
input('==========')
await browser.close() # 关闭浏览器对象
asyncio.get_event_loop().run_until_complete(main()) # 创建异步池并执行main函数。
总结常用的启动参数
属性 | 参数 | 描述 |
---|---|---|
executablePath | str | chrome.exe运行的路径 |
ignorehttpserrrors | bool | 忽略https错误,默认false |
headless | bool | True 开始无头浏览器 False关闭无头 |
dumpio | bool | 设置True 解决浏览器多开卡死 (没有测试过) |
下面是args的参数设置 | 下面是args的参数设置 | 下面是args的参数设置 |
–disable-infobars | - | 关闭自动化提示框 |
–window-size=1920,1080 | str | 设置浏览器大小吗,1920是宽,1080是宽 |
–log-level=30 | str | 日志保存等级, 建议设置越好越好,要不然生成的日志占用的空间会很大 30为warning级别 |
–start-maximized | - | 窗口最大化模式 |
–proxy-server=http://localhost:1080 | str | 设置代理 |
userDataDir=D:\userData\ | str | 用户文件保存地址 |
来源于网络copy的
#!/usr/bin/python
# -*- coding: UTF-8 -*-
"""
@time:2020/04/04
"""
import asyncio
import logging
import tkinter
from pyppeteer import launch, launcher
from lxml import etree
async def main():
# 浏览器 启动参数
start_parm = {
# 启动chrome的路径
"executablePath": r"C:\Users\yq\AppData\Local\pyppeteer\pyppeteer\local-chromium\722234\chrome-win\chrome.exe",
# 关闭无头浏览器
"headless": False,
"args": [
'--disable-infobars', # 关闭自动化提示框
# '--window-size=1920,1080', # 窗口大小
'--log-level=30', # 日志保存等级, 建议设置越好越好,要不然生成的日志占用的空间会很大 30为warning级别
'--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36', # UA
'--no-sandbox', # 关闭沙盒模式
'--start-maximized', # 窗口最大化模式
# '--proxy-server=http://localhost:1080' # 代理
r'userDataDir=D:\project_demo\python_demo\spider_demo\JavaScript 逆向系列课\userdata' # 用户文件地址
],
}
await page.goto('https://www.httpbin.org/headers')
page_text = await page.content()
input('----------------')
await browser.close()
asyncio.get_event_loop().run_until_complete(main())
但窗口设置最大化(–start-maximized)或窗口大小(–window-size=1920,1080)时,发现自己页面可视区域没有变化。成下面图片显示效果
设置可视化参数,代码如下
# !/usr/bin/python
# -*- coding: UTF-8 -*-
"""
@time:2020/04/04
"""
import asyncio
import tkinter
from pyppeteer import launcher
# 注意 在导入launch之前先把默认参数改了
# 去除自动化 启动参数
launcher.AUTOMATION_ARGS.remove("--enable-automation")
from pyppeteer import launch
async def main():
# 浏览器 启动参数
start_parm = {
# 启动chrome的路径
"executablePath": r"C:\Users\yq\AppData\Local\pyppeteer\pyppeteer\local-chromium\722234\chrome-win\chrome.exe",
# 关闭无头浏览器
"headless": False,
"args": [
'--disable-infobars', # 关闭自动化提示框
'--no-sandbox', # 关闭沙盒模式
'--start-maximized', # 窗口最大化模式
],
}
browser = await launch(**start_parm)
page = await browser.newPage()
# 查看当前 桌面视图大小
tk = tkinter.Tk()
width = tk.winfo_screenwidth()
height = tk.winfo_screenheight()
tk.quit()
print(f'设置窗口为:width:{width} height:{height}')
# 设置网页 视图大小
await page.setViewport(viewport={'width': width, 'height': height})
await page.goto('https://www.baidu.com')
input('----------------')
await browser.close()
asyncio.get_event_loop().run_until_complete(main())
这时就显示正常了。
pyppeteer跟selenium一样会有浏览器特征,所以需要修改,隐藏特征防止被识别。
主要有下面两点:
--enable-automation
window.navigator.webdriver
等检测代码示例
#!/usr/bin/python
# -*- coding: UTF-8 -*-
"""
@time:2020/04/04
"""
import asyncio
import logging
import tkinter
from pyppeteer import launcher
# 第一步 去除浏览器自动化参数
# 必须在 from pyppeteer import launch 前去除参数
# 去除自动化 启动参数
launcher.AUTOMATION_ARGS.remove("--enable-automation")
from pyppeteer import launch
from lxml import etree
async def main():
# 浏览器 启动参数
start_parm = {
# 启动chrome的路径
"executablePath": r"C:\Users\yq\AppData\Local\pyppeteer\pyppeteer\local-chromium\722234\chrome-win\chrome.exe",
# 关闭无头浏览器
"headless": False,
"args": [
'--disable-infobars', # 关闭自动化提示框
# '--window-size=1920,1080', # 窗口大小
'--log-level=30', # 日志保存等级, 建议设置越好越好,要不然生成的日志占用的空间会很大 30为warning级别
'--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36', # UA
'--no-sandbox', # 关闭沙盒模式
'--start-maximized', # 窗口最大化模式
# '--proxy-server=http://localhost:1080' # 代理
r'userDataDir=D:\project_demo\python_demo\spider_demo\JavaScript 逆向系列课\userdata' # 用户文件地址
],
}
browser = await launch(**start_parm)
page = await browser.newPage()
tk = tkinter.Tk()
width = tk.winfo_screenwidth()
height = tk.winfo_screenheight()
tk.quit()
await page.setViewport(viewport={'width': width, 'height': height})
# 第二步,修改 navigator.webdriver检测
# 其实各种网站的检测js是不一样的,这是比较通用的。有的网站会检测运行的电脑运行系统,cpu核心数量,鼠标运行轨迹等等。
# 反爬js
js_text = """
() =>{
Object.defineProperties(navigator,{ webdriver:{ get: () => false } });
window.navigator.chrome = { runtime: {}, };
Object.defineProperty(navigator, 'languages', { get: () => ['en-US', 'en'] });
Object.defineProperty(navigator, 'plugins', { get: () => [1, 2, 3, 4, 5,6], });
}
"""
await page.evaluateOnNewDocument(js_text) # 本页刷新后值不变,自动执行js
await page.goto('https://www.httpbin.org/headers')
page_text = await page.content()
print(page_text)
input('==========')
await browser.close()
asyncio.get_event_loop().run_until_complete(main())
可以对出现的请求,进行拦截 类似mitmproxy。
#!/usr/bin/python
# -*- coding: UTF-8 -*-
"""
@time:2020/04/04
"""
import asyncio
import json
from jsonpath import jsonpath
from pyppeteer import launcher
launcher.AUTOMATION_ARGS.remove("--enable-automation")
from pyppeteer import launch
from pyppeteer.network_manager import Request, Response
async def intercept_request(req:Request):
await req.continue_() # 请求,看源码可以重新编写请求
async def intercept_response(res:Response):
if 'ext2020/apub/json/prevent.new' in res.url:
print('拦截到请求')
json_text = await res.text()
title_li = jsonpath(json.loads(json_text), '$..title')
for title in title_li:
print(title)
pass
async def main():
# 浏览器 启动参数
start_parm = {
# 启动chrome的路径
"executablePath": r"C:\Users\yq\AppData\Local\pyppeteer\pyppeteer\local-chromium\722234\chrome-win\chrome.exe",
# 关闭无头浏览器 默认是无头启动的
"headless": False,
"args": [
'--disable-infobars', # 关闭自动化提示框
# '--no-sandbox', # 关闭沙盒模式
'--start-maximized', # 窗口最大化模式
'--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36',
# UA
],
}
# 创建浏览器对象,可以传入 字典形式参数
browser = await launch(**start_parm)
# 创建一个页面对象, 页面操作在该对象上执行
page = await browser.newPage()
await page.setJavaScriptEnabled(enabled=True)
# 启用拦截器
await page.setRequestInterception(True)
page.on('request', intercept_request)
page.on('response', intercept_response)
js_text = """
() =>{
Object.defineProperties(navigator,{ webdriver:{ get: () => false } });
window.navigator.chrome = { runtime: {}, };
Object.defineProperty(navigator, 'languages', { get: () => ['en-US', 'en'] });
Object.defineProperty(navigator, 'plugins', { get: () => [1, 2, 3, 4, 5,6], });
}
"""
await page.evaluateOnNewDocument(js_text) # 本页刷新后值不变,自动执行js
await page.goto('https://news.qq.com/') # 页面跳转
await browser.close()
asyncio.get_event_loop().run_until_complete(main()) # 创建异步池并执行main函数。