0%

pyppeteer 手册

前言

前段时间因为有任务,需要四个电商(京东、淘宝、天猫、拼多多)的数据。而其中京东的没什么反爬,基本是随便抓。拼多多的加密参数有点复杂,而且变化也挺频繁的,用的是 selenium,也没什么可提的。抓淘宝和天猫因为用 selenium 滑块过不了,于是就改成了 pyppeteer。现在我说一下使用的心得。有些细节因为当时没有记录,现在也记不起来了。

首先 pip install pyppeteer , 这时候我们先看一下 websockets 这个库的版本,因为必须保证这个库是 7.0 的版本。8.0 和 6.0 虽然可以使用,但是在访问多个网页会出现一些无法解决的异常。现在安装 pyppeteer,websockets 的版本默认是 8.0,我们需要先 pip uninstall websockets 卸载 8.0,然后 pip install websockets==7.0。然后我们按照 https://github.com/miyakogi/pyppeteer/pull/160/files 这个网页修改 pyppeteer 的源码(如果是 anaconda,则路径是 anaconda 安装路径\Lib\site-packages\pyppeteer\connection.py 这个文件)。这样准备工作就完成了,这样操作之后就可以避免很多异常。

需要这么费劲的折腾,是因为 pyppeteer 这个库已经很久没有做大的更新了,虽然有点小的改动,但是基本的 bug 还是没有解决。所以如果有 js 基础,最好还是使用 JavaScript 的 puppeteer 这个工具,这个是谷歌出品的,一直在更新维护,基本没有 bug。

补充:有时候会出现明明网页加载完成了,但是还是会出现超时的情况。不知道是什么 bug,解决方法也很简单,只要捕获这个异常,然后该做啥做啥。

以下有的方法前面带 coroutine 这个关键字,有点没有,这是因为带这个参数的方法都是异步方法,这种方法必须被 async 关键字修饰,调用的时候也必须 await 关键字修饰。不过我们既然使用浏览器爬虫了,肯定已经不在乎效率了,异步等于在等网站封,所以只需要遵守某些规则即可(不懂的请百度 asyncio 的使用),实际上还是同步运行。另外,虽然 page.on()这个方法是存在的,但是官方文档中并未给出详细的说明,甚至我查看 pyppeteer 的源码也未找到这个函数,不知道是怎么回事。但是参考 puppeteer 的文档也是可以用的,不过报错居多,我也就没有深究了。

API 参考

启动器

  1. pyppeteer.launcher.launch()
    启动 Chrome 进程并返回浏览器实例

参数:

  • ignoreHTTPSErrors(bool):是否忽略 HTTPS 错误。默认为 False
  • headless(bool):是否在无头模式下运行浏览器。默认为 True 除非 appModedevtools 选项 True
  • executablePath (str):运行 Chromium 或 Chrome 可执行文件的路径,而不是默认捆绑的 Chromium
  • slowMo (int | float):按指定的毫秒数减慢 pyppeteer 操作。
  • args (List [str]):传递给浏览器进程的附加参数(标志)。
  • dumpio(bool):是否管道浏览器进程 stdout 和 stderr 进入 process.stdoutprocess.stderr。默认为 False
  • userDataDir (str):用户数据目录的路径。
  • env(dict):指定浏览器可见的环境变量。默认与 python 进程相同。
  • devtools(bool):是否为每个选项卡自动打开 DevTools 面板。如果是此选项 Trueheadless 则将设置该选项 False
  • logLevel(int | str):用于打印日志的日志级别。默认值与根记录器相同。
  • autoClose(bool):脚本完成时自动关闭浏览器进程。默认为 True
  • loop(asyncio.AbstractEventLoop):事件循环(实验)。

  • ignoreHTTPSErrors:意思很明显,不解释
  • headless:不解释
  • executablePath:这个一般是默认的路径就行
  • slowMo:我一般会加这个参数,至于效果吗,好像有点。
  • args:常用的有[‘–no-sandbox’,’–disable-gpu’, ‘–disable-setuid-sandbox’,’–window-size=1440x900’]
  • dumpio: 不知道为什么,如果不加 dumpio=True 有时会出现浏览器卡顿
  • userDataDir:selenium 的 userdata 可以保留 cookie,下次启动可以达到免登录,而这个参数没什么用
  • env:看需求
  • devtools:用的不深,没用过
  • logLevel:没什么用,在 Linux 下还是打印大量的日志
  • autoClose:默认就好,不过如果你需要保持浏览器状态,可以不关闭,下次直接连接这个已存在的浏览器
  • loop:暂时不知道有什么用
  1. pyppeteer.launcher.connect()
    连接到现有的 Chrome

参数:

  • browserWSEndpoint(str):要连接的浏览器 WebSocket 端点。(必填
  • ignoreHTTPSErrors(bool):是否忽略 HTTPS 错误。默认为 False
  • slowMo (int | float):按指定的毫秒数减慢 pyppeteer 的速度。
  • logLevel(int | str):用于打印日志的日志级别。默认值与根记录器相同。
  • loop(asyncio.AbstractEventLoop):事件循环(实验)。

browserWSEndpoint:格式是 ws://${host}:${port}/devtools/browser/<id>。以前浏览器的 wsEndpoint 这个值,可以通过 brower = pyppeteer.launcher.launch() dev = brower. wsEndpoint 保存这个值就可以下次启动了

  1. pyppeteer.launcher.executablePath()
    获取默认 Chrome 的可执行路径

浏览器类

pyppeteer.browser.Browser()
这个类是由 launch()返回的实例

  • browserContexts: 返回所有打开的浏览器上下文的列表,在新创建的浏览器中,这将返回单个实例
  • coroutine close(): 关闭连接并终止浏览器进程
  • coroutine createIncognitoBrowserContext(): 创建一个新的隐身浏览器上下文。这不会与其他浏览器上下文共享 cookie /缓存
  • coroutine disconnect(): 断开浏览器
  • coroutine newPage(): 在此浏览器上创建新页面并返回其对象
  • coroutine pages(): 获取此浏览器的所有页面。返回格式为列表,包含所有页面
  • process:返回此浏览器的进程
  • target(): 获取浏览器中所有活动目标的列表
  • coroutine userAgent():返回浏览器的原始 UA
  • coroutine version(): 获取浏览器的版本
  • wsEndpoint: 返回 WebSocket 端点 url

页面类

pyppeteer.page.Page()
由 brower.newPage()或者 brower.pages()得到

  • coroutine J():别名 querySelector(),看名字就知道通过 CSS 选择器来选出元素
  • coroutine JJ(): 别名 querySelectorAll()
  • coroutine Jeval(): 功能比 page.J()功能多一点,可以选出网页文本或者属性指
  • coroutine JJeval(): querySelectorAllEval()
  • coroutine Jx(): 别名 xpath()
  • coroutine addScriptTag(): 将脚本标记添加到此页面, 返回 ElementHandle
    其中一个 url,path 或 content 选择是必要的。
    • url (字符串):要添加的脚本的 URL。
    • path (字符串):要添加的本地 JavaScript 文件的路径。
    • content (字符串):要添加的 JavaScript 字符串。
    • type(字符串):脚本类型。使用 module 以加载一个 JavaScript ES6 模块。
  • coroutine addStyleTag(): 将样式或链接标记添加到此页面, 返回 ElementHandle
    其中一个 urlpathcontent 选择是必要的。
    • url (字符串):要添加的链接标记的 URL。
    • path (字符串):要添加的本地 CSS 文件的路径。
    • content (字符串):要添加的 CSS 字符串。
  • coroutine authenticate(): 提供 http 身份验证的凭据
  • coroutine bringToFront(): 将页面置于前面
  • browser: 获取该页面所属的浏览器
  • coroutine click(): 相当于鼠标左键单击匹配的元素,参数是 CSS 选择器的字符串。如果没有匹配到元素,则会引发 PageError
    可选参数:
    • button(str): ,left,right 或 middle,默认为 left。
    • clickCount (int):默认为 1。
    • delay(int | float):等待时间 mousedown 和 mouseup 以毫秒为单位的时间。默认为 0。

注意
如果此方法触发导航事件并且存在单独的事件,则 waitForNavigation()最终可能会出现产生意外结果的竞争条件。单击并等待导航的正确模式如下:

1

await asyncio.gather(

page.waitForNavigation(waitOptions),

page.click(selector, clickOptions),

)
​```

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66

大概意思是 click()触发如果会跳转网页,则需要 page.waitForNavigation()这个函数来等待。但点击事件和触发事件是同时的,所以需要将这两个事件绑定,代码如上。

- coroutine close(): 关闭此页面

- coroutine content(): 获取页面的完整 HTML 内容

- coroutine cookies(): 获取 cookie。参数为 URL,如果未指定 URL,则此方法返回当前页面 URL 的 cookie。如果指定了 URL,则仅返回这些 URL 的 cookie

- coverage: 返回 coverage

- coroutine deleteCookie(): 删除 cookie,参数为 cookie 字段参数,比如 name、url、domain、path 等

- coroutine emulate(): 模拟给定的设备指标和用户代理。相当于同时设置了 setUserAgent()、setViewport()

- coroutine emulateMedia(): 模拟页面的 CSS 媒体类型。参数为:screen、print、None。

- coroutine evaluate(): 在浏览器上执行 js 并获取结果

- coroutine evaluateHandle(): 同上,只是会返回一个值。至于是什么,没用过

- coroutine evaluateOnNewDocument(): 也是执行 js,至于区别。好像是在页面跳转时执行

- coroutine exposeFunction(): 将 python 函数添加到浏览器的 window 对象中 name。不知道有什么用

- coroutine focus(): 聚焦匹配的元素。如果不存在,抛出 PageError

- frames:获取此页面的所有 frame

- coroutine goBack():返回上一个网页。如果不存在,则返回 None

- coroutine goForward(): 跳转到下一页。如果不存在,则返回 None

- coroutine goto(): 访问某个 URL。
参数:

- url:。。。
- timeout:。。。
- waitUntil:什么情况下算成功访问。没看懂参数的几个值有什么用

- coroutine hover(): 鼠标悬停匹配的元素

- isClosed(): 判断页面是否关闭

- keyboard: 获取 keyboard 对象

- mainFrame: 获取 frame 页面的主要内容

- coroutine metrics(): 好像是获取页面中的信息

- mouse: 获取 mouse 对象

- coroutine reload(): 刷新网页

- coroutine screenshot(): 截图
参数:

- `path`(str):保存图像的文件路径。屏幕截图类型将从文件扩展名中推断出来。

- `type`(str):指定屏幕截图类型,可以是 `jpeg` 或 `png`。默认为 `png`。

- `quality`(int):图像的质量,在 0-100 之间。不适用于 `png` 图像。

- `fullPage`(bool):如果为 true,请截取完整的可滚动页面。默认为 `False`。

-
clip
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101

(字典):指定页面剪切区域的对象。此选项应包含以下字段:

- `x` (int):剪辑区域左上角的 x 坐标。
- `y` (int):剪辑区域左上角的 y 坐标。
- `width` (int):剪切区域的宽度。
- `height` (int):剪切区域的高度。

- `omitBackground` (bool):隐藏默认的白色背景并允许捕获具有透明度的屏幕截图。

- `encoding`(str):图像的编码可以是 `'base64'` 或 `'binary'`。默认为 `'binary'`。

- coroutine select(): 选择选项并返回所选值。如果未找到元素,抛出 ElementHandleError。

- coroutine setCacheEnabled(): 为每个请求启用/禁用缓存。默认启用

- coroutine setContent(): 将 HTML 加到网页

- coroutine setCookie(): 设置 cookie

- setDefaultNavigationTimeout(): 更改默认的最大导航超时。默认 30 秒

- coroutine setJavaScriptEnabled(): 设置 JavaScript 启用/禁用

- coroutine setExtraHTTPHeaders(): 设置默认 headers 头,值为一个字典

- coroutine setRequestInterception(): 启用/禁用请求拦截。配合 page.on()

- coroutine setUserAgent(): 设置要在此页面中使用的 UA

- coroutine setViewport(): 设置窗口大小。
参数:

- `width` (int):以像素为单位的页面宽度。
- `height` (int):以像素为单位的页面高度。
- `deviceScaleFactor` (float):默认为 1.0。
- `isMobile`(bool):默认为 `False`。
- `hasTouch`(bool):默认为 `False`。
- `isLandscape`(bool):默认为 `False`。

- coroutine tap(): 点击与之匹配的元素

- coroutine title(): 获取页面标签

- tracing:获取 tracing 对象

- coroutine type(): 往输入框中输入内容,第一个参数为 CSS 选择器,第二个为文本内容

- url:获取此页面的 url

- waitFor(): 等待页面上匹配的函数,超时或元素。参数可以是 int 或者 float,单位毫秒。也可以是 CSS 选择器

- waitForFunction():

- coroutine waitForNavigation(): 等到网页跳转

- coroutine waitForRequest(): 等待请求

- coroutine waitForResponse(): 等待回应

- waitForSelector(): 等到页面上出现匹配的元素。其实 waitFor()也有同样功能。

- waitForFunction(): 等到函数完成并返回一个值

- coroutine waitForXPath(): 等到 xpath 页面上出现匹配的元素

- workers: 获取页面的所有 worker。至于是什么,我不知道

- coroutine xpath(): ..

## worker 类

page.on('workercreated', 函数) 这个函数传入的参数就是 worker 类

- coroutine evaluate(): 同上
- coroutine evaluateHandle():同上
- coroutine executionContext():同上
- url: 同上

## 键盘类

- coroutine down(): 如果没有参数,则是按下鼠标左键。如果是键盘的某个值比如 shift、A 等键,则是相当于按下这些键。
- coroutine press(): 同 down(),但是上面是不会释放鼠标或者键盘,需要调用 up 方法释放鼠标。
- coroutine sendCharacter:将字符发送到页面。没用过
- coroutine type(): 同上
- coroutine up(): 释放由 down 按下的键或者鼠标

## 鼠标类

- coroutine click(): 按下(x, y)处的按钮
参数:
- `button`(STR): ,left(左键)、right(右键)或 middle(中键),默认为 `left`。
- `clickCount` (int):默认为 1。
- `delay`(int | float):等待时间 `mousedown` 和 `mouseup` 以毫秒为单位的时间。默认为 0。
- coroutine down(): 同上
- coroutine move(): 移动鼠标光标。
- coroutine up(): 同上

## tracing 类

创建可在 Chrome DevTools 或时间线查看器打开的跟踪文件 ,使用如下

await page.tracing.start({‘path’: ‘trace.json’})

await page.goto(‘https://www.google.com')

await page.tracing.stop()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136

- coroutine start(): 开始跟踪
- coroutine stop(): 停止跟踪

不好用,可能是我不知道用

## Dialog 类

`page.on( 'dialog', 函数)`,函数的参数就是这个类

- coroutine accept(): 接受对话框
- defaultValue: 如果对话框提示,则获取默认提示值
- coroutine dismiss(): 关闭对话框
- message: 获取对话框消息
- type: 获取对话框类型。类型有:`alert`,`beforeunload`,`confirm`,或 `prompt`

## frame 类

- coroutine J():同上
- coroutine JJ():同上
- coroutine JJeval(): 同上
- coroutine Jeval(): 同上
- coroutine Jx(): 同上
- coroutine addScriptTag(): 同上
- coroutine addStyleTag(): 同上
- childFrames: 获取子框架
- coroutine click(): 同上
- coroutine content(): 同上
- coroutine evaluate(): 同上
- coroutine evaluateHandle(): 同上
- coroutine executionContext(): 同上
- coroutine focus(): 同上
- coroutine hover(): 同上
- isDetached(): 如果此框架已分离,则返回 True
- name:获取 frame 的名称,如果没有则返回 ID
- parentFrame:获取父框架
后面这些属性和 page 类一模一样

## ElementHandle 类

- coroutine J()
- coroutine JJ()
- coroutine JJeval()
- coroutine Jeval()
- asElement
- coroutine boundingBox(): 返回此元素的边界框,如果元素不可见,则返回 None
- coroutine boxModel():返回元素框
- coroutine click()
- coroutine contentFrame(): 返回元素句柄的 frame
- coroutine focus()
- coroutine hover()
- coroutine isIntersectingViewport(): 如果元素在视口中可见,则返回 True
- coroutine press()
- coroutine screenshot()
- coroutine tap()
- coroutine type()
- coroutine uploadFile(): 上传文件

## request 类

page.on('request', 函数) 这个函数传入的参数就是 request 类

- coroutine abort(): 中断请求

- coroutine continue_(): 使用可选的请求覆盖继续请求

参数:

- `url` (str):如果设置,请求 URL 将被更改。
- `method`(str):如果设置,则更改请求方法(例如 `GET`)。
- `postData` (str):如果设置,则更改发布数据或请求。
- `headers` (dict):如果设置,则更改请求 HTTP 标头

- failure(): 返回错误文本

- frame : 返回匹配的 frame 对象

- headers: 返回此请求的 HTTP 标头字典

- isNavigationRequest(): ??

- method:返回此请求的方法

- postData: 返回此请求的帖子正文

- redirectChain: request 类重定向的所有请求

- resourceType:渲染引擎感知的此请求的资源类型

- coroutine respond(): 通过给定的参数修改请求

参数:

- `status` (int):响应状态代码,默认为 200。
- `headers` (dict):可选的响应头。
- `contentType`(str):如果设置,则等于设置 `Content-Type` 响应头。
- `body` (str | bytes):可选的响应主体。

- response(): 返回匹配的 response 对象

- url: 此请求的 URL

## response 类

- buffer(): 返回相应的字节内容
- fromCache: 如果响应是从缓存提供的,则返回 True。缓存可能是浏览器的磁盘缓存或者内存,而不是服务器响应的
- fromServiceWorker: 如果响应由服务器提供,则返回 True
- headers: 返回此响应的 HTTP 标头字典
- coroutine json(): 获取响应正文的 JSON
- ok: 返回 bool 此请求是否成功
- request: 获取匹配的 request 对象
- securityDetails: 返回与此响应关联的安全详细信息
- status: 响应的状态代码
- coroutine text(): 获取响应正文的文本
- url : 响应的 URL

## target 类

我到现在还没明白这是干什么的

- browser: 获取目标所属的浏览器
- browserContext: 返回目标所属的浏览器上下文
- coroutine createCDPSession(): 创建附加到目标的 Chrome Devtools 协议会话
- opener: 获取打开此目标的目标
- coroutine page(): 获取此目标的页面
- type: 获取此目标的类型
- url: 获取此目标的网址

## CDPSession 类

- coroutine detach(): 从目标分离会话
- send() :

## Debugging

对于调试,您可以设置 for 和 功能 `logLevel` 选项。但是,此选项会打印太多日志,包括 pyppeteer 的 SEND / RECV 消息。为了只显示被抑制的错误消息,您应该设置 logging.DEBUG 为 True

import asyncio
import pyppeteer
from pyppeteer import launch

pyppeteer.DEBUG = True # print suppressed errors as error log

async def main():

browser = await launch()

...  # do something

asyncio.get_event_loop().run_until_complete(main())

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143

## 实践

```python
import asyncio
from asyncio.tasks import wait
from logging import lastResort
import time


from pyquery import PyQuery as pq

# 第一步 去除浏览器自动化参数
# 必须在 from pyppeteer import launch 前去除参数
# 去除自动化 启动参数
# from pyppeteer import launcher
# launcher.AUTOMATION_ARGS.remove("--enable-automation")
from pyppeteer import launch

browser = None
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",
],
"dumpio": True,
# 当界面开多了时会卡住,设置这个参数就不会了
# 用户数据保存目录 这个最好也自己指定一个目录
# 如果不指定的话,chrome会自动新建一个临时目录使用,在浏览器退出的时候会自动删除临时目录
# 在删除的时候可能会删除失败(不知道为什么会出现权限问题,我用的windows) 导致浏览器退出失败
# 然后chrome进程就会一直没有退出 CPU就会狂飙到99%
"userDataDir": "./userdata",
}


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():
global browser
if browser is None:
browser = await launch(launch_kwargs)

page = await browser.newPage()
width, height = screen_size()
# 设置网页可视区域大小
# await page.setViewport({
# "width": width,
# "height": height
# })
# 第二步,修改 navigator.webdriver检测
# 其实各种网站的检测js是不一样的,这是比较通用的。有的网站会检测运行的电脑运行系统,cpu核心数量,鼠标运行轨迹等等。
# 反爬js
# 隐藏浏览器驱动信息,防检测
await page.evaluateOnNewDocument(
"Object.defineProperty(" 'navigator, "webdriver", {get: () => undefined})'
)
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.setUserAgent(
"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.67 Safari/537.36"
)

await page.goto("http://sxdxjwc.ctgu.edu.cn/index.jsp")

await page.screenshot(path="example.png", quality=100, fullPage=True)
latest_notice = await page.querySelector("div.jwtz_nr > ul > ul > li:nth-child(1)")
url = await (await latest_notice.getProperty("href")).jsonValue()
print(str(url))
print(page.url)
title = await page.evaluate("(element) => element.textContent", latest_notice)
print(title)
url = await page.evaluate("(element) => element.URL", latest_notice)
print("获取的链接", url)
await page.click(
"body > div.width > div.maina > div.jwtz > div.jwtz_nr > ul > ul > li:nth-child(1)"
)
await asyncio.sleep(1)
# await page.waitForNavigation(timeout=0)
# await asyncio.wait(
# [
# page.click(
# "body > div.width > div.maina > div.jwtz > div.jwtz_nr > ul > ul > li:nth-child(1)"
# ),
# page.waitForNavigation({"timeout": 0}),
# ]
# )

pages = await browser.pages()
print("所有的页面", pages)
for p in pages:
print(p.title,p.url)
# pages[0].close()
# await page.click(
# "body > div.width > div.maina > div.jwtz > div.jwtz_nr > ul > ul > li:nth-child(1)"
# )
# await page.waitFor(1)


# page.mouse # 模拟真实点击
# time.sleep(10)
# page.bringToFront()
cookies = await page.cookies()
print(cookies)
# 然后导入cookie
# await page.setCookie(*cookies)
# browser.retainLastPage()
# 前进
# await page.goForward()
# page=pages[1]
await pages[-1].screenshot(path="news.png", quality=100, fullPage=True)
# await page.waitFor(2) # 停顿
await browser.close()
asyncio.get_event_loop().run_until_complete(main())

转自:https://ld246.com/article/1566221786951

iBoy wechat
欢迎您扫一扫上面的微信公众号,订阅我的博客!