Skip to content

Commit cab2096

Browse files
committed
完善文档
1 parent 31215a6 commit cab2096

13 files changed

Lines changed: 532 additions & 347 deletions

File tree

README.md

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,22 +20,24 @@
2020

2121
### 1.拥有强大的监控,保障数据质量
2222

23-
![](http://markdown-media.oss-cn-beijing.aliyuncs.com/2021/09/14/16316112326191.jpg)
23+
![](http://markdown-media.oss-cn-beijing.aliyuncs.com/2022/10/12/16655595870715.jpg)
2424

2525
监控面板:[点击查看详情](http://feapder.com/#/feapder_platform/feaplat)
2626

27-
### 2. 内置多维度的报警(支持 钉钉、企业微信、邮箱)
27+
### 2. 内置多维度的报警(支持 钉钉、企业微信、飞书、邮箱)
2828

2929
![](http://markdown-media.oss-cn-beijing.aliyuncs.com/2020/12/20/16084718974597.jpg)
3030
![](http://markdown-media.oss-cn-beijing.aliyuncs.com/2020/12/29/16092335882158.jpg)
3131
![](http://markdown-media.oss-cn-beijing.aliyuncs.com/2020/12/20/16084718683378.jpg)
3232

3333

34-
### 3. 简单易用,内置三种爬虫,可应对各种需求场景
34+
### 3. 简单易用,内置四种爬虫,可应对各种需求场景
3535

3636
- `AirSpider` 轻量爬虫:学习成本低,可快速上手
3737

38-
- `Spider` 分布式爬虫:支持断点续爬、爬虫报警、数据自动入库等功能
38+
- `Spider` 分布式爬虫:支持断点续爬、爬虫报警等功能,可加快爬虫采集速度
39+
40+
- `TaskSpider` 任务爬虫:从任务表里取任务做,内置支持对接redis、mysql任务表,亦可扩展其他任务来源
3941

4042
- `BatchSpider` 批次爬虫:可周期性的采集数据,自动将数据按照指定的采集周期划分。(如每7天全量更新一次商品销量的需求)
4143

@@ -44,7 +46,6 @@
4446
## 文档地址
4547

4648
- 官方文档:http://feapder.com
47-
- 国内文档:https://boris-code.gitee.io/feapder
4849
- 境外文档:https://boris.org.cn/feapder
4950
- github:https://github.com/Boris-code/feapder
5051
- 更新日志:https://github.com/Boris-code/feapder/releases

docs/README.md

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,21 +16,23 @@
1616

1717
### 1.拥有强大的监控,保障数据质量
1818

19-
![](http://markdown-media.oss-cn-beijing.aliyuncs.com/2021/09/14/16316112326191.jpg)
19+
![](http://markdown-media.oss-cn-beijing.aliyuncs.com/2022/10/12/16655595870715.jpg)
2020

2121
监控面板:[点击查看详情](http://feapder.com/#/feapder_platform/feaplat)
2222

23-
### 2. 内置多维度的报警(支持 钉钉、企业微信、邮箱)
23+
### 2. 内置多维度的报警(支持 钉钉、企业微信、飞书、邮箱)
2424

2525
![](http://markdown-media.oss-cn-beijing.aliyuncs.com/2020/12/20/16084718974597.jpg)
2626
![](http://markdown-media.oss-cn-beijing.aliyuncs.com/2020/12/29/16092335882158.jpg)
2727
![](http://markdown-media.oss-cn-beijing.aliyuncs.com/2020/12/20/16084718683378.jpg)
2828

29-
### 3. 简单易用,内置三种爬虫,可应对各种需求场景
29+
### 3. 简单易用,内置四种爬虫,可应对各种需求场景
3030

3131
- `AirSpider` 轻量爬虫:学习成本低,可快速上手
3232

33-
- `Spider` 分布式爬虫:支持断点续爬、爬虫报警、数据自动入库等功能
33+
- `Spider` 分布式爬虫:支持断点续爬、爬虫报警等功能,可加快爬虫采集速度
34+
35+
- `TaskSpider` 任务爬虫:从任务表里取任务做,内置支持对接redis、mysql任务表,亦可扩展其他任务来源
3436

3537
- `BatchSpider` 批次爬虫:可周期性的采集数据,自动将数据按照指定的采集周期划分。(如每7天全量更新一次商品销量的需求)
3638

@@ -39,7 +41,6 @@
3941
## 文档地址
4042

4143
- 官方文档:http://feapder.com
42-
- 国内文档:https://boris-code.gitee.io/feapder
4344
- 境外文档:https://boris.org.cn/feapder
4445
- github:https://github.com/Boris-code/feapder
4546
- 更新日志:https://github.com/Boris-code/feapder/releases

docs/_sidebar.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@
2020
* [响应-Response](source_code/Response.md)
2121
* [代理使用说明](source_code/proxy.md)
2222
* [用户池说明](source_code/UserPool.md)
23-
* [浏览器渲染](source_code/浏览器渲染.md)
23+
* [浏览器渲染-Selenium](source_code/浏览器渲染-Selenium.md)
24+
* [浏览器渲染-Playwright](source_code/浏览器渲染-Playwright)
2425
* [解析器-BaseParser](source_code/BaseParser.md)
2526
* [批次解析器-BatchParser](source_code/BatchParser.md)
2627
* [Spider进阶](source_code/Spider进阶.md)
Lines changed: 258 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,258 @@
1+
# 浏览器渲染-Playwright
2+
3+
采集动态页面时(Ajax渲染的页面),常用的有两种方案。一种是找接口拼参数,这种方式比较复杂但效率高,需要一定的爬虫功底;另外一种是采用浏览器渲染的方式,直接获取源码,简单方便
4+
5+
框架支持playwright渲染下载,每个线程持有一个playwright实例
6+
7+
8+
## 使用方式:
9+
10+
1. 修改配置文件的渲染下载器:
11+
12+
```
13+
RENDER_DOWNLOADER="feapder.network.downloader.PlaywrightDownloader"
14+
```
15+
2. 使用
16+
17+
```python
18+
def start_requests(self):
19+
yield feapder.Request("https://news.qq.com/", render=True)
20+
```
21+
22+
在返回的Request中传递`render=True`即可
23+
24+
框架支持`chromium`、`firefox`、`webkit` 三种浏览器渲染,可通过[配置文件](source_code/配置文件)进行配置。相关配置如下:
25+
26+
```python
27+
PLAYWRIGHT = dict(
28+
user_agent=None, # 字符串 或 无参函数,返回值为user_agent
29+
proxy=None, # xxx.xxx.xxx.xxx:xxxx 或 无参函数,返回值为代理地址
30+
headless=False, # 是否为无头浏览器
31+
driver_type="chromium", # chromium、firefox、webkit
32+
timeout=30, # 请求超时时间
33+
window_size=(1024, 800), # 窗口大小
34+
executable_path=None, # 浏览器路径,默认为默认路径
35+
download_path=None, # 下载文件的路径
36+
render_time=0, # 渲染时长,即打开网页等待指定时间后再获取源码
37+
wait_until="networkidle", # 等待页面加载完成的事件,可选值:"commit", "domcontentloaded", "load", "networkidle"
38+
use_stealth_js=False, # 使用stealth.min.js隐藏浏览器特征
39+
page_on_event_callback=None, # page.on() 事件的回调 如 page_on_event_callback={"dialog": lambda dialog: dialog.accept()}
40+
storage_state_path=None, # 保存浏览器状态的路径
41+
url_regexes=None, # 拦截接口,支持正则,数组类型
42+
save_all=False, # 是否保存所有拦截的接口, 配合url_regexes使用,为False时只保存最后一次拦截的接口
43+
)
44+
```
45+
46+
- `feapder.Request` 也支持`render_time`参数, 优先级大于配置文件中的`render_time`
47+
48+
- 代理使用优先级:`feapder.Request`指定的代理 > 配置文件中的`PROXY_EXTRACT_API` > webdriver配置文件中的`proxy`
49+
50+
- user_agent使用优先级:`feapder.Request`指定的header里的`User-Agent` > 框架随机的`User-Agent` > webdriver配置文件中的`user_agent`
51+
52+
## 设置User-Agent
53+
54+
> 每次生成一个新的浏览器实例时生效
55+
56+
### 方式1:
57+
58+
通过配置文件的 `user_agent` 参数设置
59+
60+
### 方式2:
61+
62+
通过 `feapder.Request`携带,优先级大于配置文件, 如:
63+
64+
```python
65+
def download_midware(self, request):
66+
request.headers = {
67+
"User-Agent": "xxxxxxxx"
68+
}
69+
return request
70+
```
71+
72+
## 设置代理
73+
74+
> 每次生成一个新的浏览器实例时生效
75+
76+
### 方式1:
77+
78+
通过配置文件的 `proxy` 参数设置
79+
80+
### 方式2:
81+
82+
通过 `feapder.Request`携带,优先级大于配置文件, 如:
83+
84+
```python
85+
def download_midware(self, request):
86+
request.proxies = {
87+
"https": "https://xxx.xxx.xxx.xxx:xxxx"
88+
}
89+
return request
90+
```
91+
92+
## 设置Cookie
93+
94+
通过 `feapder.Request`携带,如:
95+
96+
```python
97+
def download_midware(self, request):
98+
request.headers = {
99+
"Cookie": "key=value; key2=value2"
100+
}
101+
return request
102+
```
103+
104+
或者
105+
106+
```python
107+
def download_midware(self, request):
108+
request.cookies = {
109+
"key": "value",
110+
"key2": "value2",
111+
}
112+
return request
113+
```
114+
115+
或者
116+
117+
```python
118+
def download_midware(self, request):
119+
request.cookies = [
120+
{
121+
"domain": "xxx",
122+
"name": "xxx",
123+
"value": "xxx",
124+
"expirationDate": "xxx"
125+
},
126+
]
127+
return request
128+
```
129+
130+
## 拦截数据示例
131+
132+
> 注意:主函数使用run方法运行,不能使用start
133+
134+
```python
135+
from playwright.sync_api import Response
136+
from feapder.utils.webdriver import (
137+
PlaywrightDriver,
138+
InterceptResponse,
139+
InterceptRequest,
140+
)
141+
142+
import feapder
143+
144+
145+
def on_response(response: Response):
146+
print(response.url)
147+
148+
149+
class TestPlaywright(feapder.AirSpider):
150+
__custom_setting__ = dict(
151+
RENDER_DOWNLOADER="feapder.network.downloader.PlaywrightDownloader",
152+
PLAYWRIGHT=dict(
153+
user_agent=None, # 字符串 或 无参函数,返回值为user_agent
154+
proxy=None, # xxx.xxx.xxx.xxx:xxxx 或 无参函数,返回值为代理地址
155+
headless=False, # 是否为无头浏览器
156+
driver_type="chromium", # chromium、firefox、webkit
157+
timeout=30, # 请求超时时间
158+
window_size=(1024, 800), # 窗口大小
159+
executable_path=None, # 浏览器路径,默认为默认路径
160+
download_path=None, # 下载文件的路径
161+
render_time=0, # 渲染时长,即打开网页等待指定时间后再获取源码
162+
wait_until="networkidle", # 等待页面加载完成的事件,可选值:"commit", "domcontentloaded", "load", "networkidle"
163+
use_stealth_js=False, # 使用stealth.min.js隐藏浏览器特征
164+
# page_on_event_callback=dict(response=on_response), # 监听response事件
165+
# page.on() 事件的回调 如 page_on_event_callback={"dialog": lambda dialog: dialog.accept()}
166+
storage_state_path=None, # 保存浏览器状态的路径
167+
url_regexes=["wallpaper/list"], # 拦截接口,支持正则,数组类型
168+
save_all=True, # 是否保存所有拦截的接口
169+
),
170+
)
171+
172+
def start_requests(self):
173+
yield feapder.Request(
174+
"http://www.soutushenqi.com/image/search/?searchWord=%E6%A0%91%E5%8F%B6",
175+
render=True,
176+
)
177+
178+
def parse(self, reqeust, response):
179+
driver: PlaywrightDriver = response.driver
180+
181+
intercept_response: InterceptResponse = driver.get_response("wallpaper/list")
182+
intercept_request: InterceptRequest = intercept_response.request
183+
184+
req_url = intercept_request.url
185+
req_header = intercept_request.headers
186+
req_data = intercept_request.data
187+
print("请求url", req_url)
188+
print("请求header", req_header)
189+
print("请求data", req_data)
190+
191+
data = driver.get_json("wallpaper/list")
192+
print("接口返回的数据", data)
193+
194+
print("------ 测试save_all=True ------- ")
195+
196+
# 测试save_all=True
197+
all_intercept_response: list = driver.get_all_response("wallpaper/list")
198+
for intercept_response in all_intercept_response:
199+
intercept_request: InterceptRequest = intercept_response.request
200+
req_url = intercept_request.url
201+
req_header = intercept_request.headers
202+
req_data = intercept_request.data
203+
print("请求url", req_url)
204+
print("请求header", req_header)
205+
print("请求data", req_data)
206+
207+
all_intercept_json = driver.get_all_json("wallpaper/list")
208+
for intercept_json in all_intercept_json:
209+
print("接口返回的数据", intercept_json)
210+
211+
# 千万别忘了
212+
driver.clear_cache()
213+
214+
215+
if __name__ == "__main__":
216+
TestPlaywright(thread_count=1).run()
217+
```
218+
可通过配置的`page_on_event_callback`参数自定义事件的回调,如设置`on_response`的事件回调,亦可直接使用`url_regexes`设置拦截的接口
219+
220+
## 操作浏览器对象示例
221+
222+
> 注意:主函数使用run方法运行,不能使用start
223+
224+
```python
225+
import time
226+
227+
from playwright.sync_api import Page
228+
229+
import feapder
230+
from feapder.utils.webdriver import PlaywrightDriver
231+
232+
233+
class TestPlaywright(feapder.AirSpider):
234+
__custom_setting__ = dict(
235+
RENDER_DOWNLOADER="feapder.network.downloader.PlaywrightDownloader",
236+
)
237+
238+
def start_requests(self):
239+
yield feapder.Request("https://www.baidu.com", render=True)
240+
241+
def parse(self, reqeust, response):
242+
driver: PlaywrightDriver = response.driver
243+
page: Page = driver.page
244+
245+
page.type("#kw", "feapder")
246+
page.click("#su")
247+
page.wait_for_load_state("networkidle")
248+
time.sleep(1)
249+
250+
html = page.content()
251+
response.text = html # 使response加载最新的页面
252+
for data_container in response.xpath("//div[@class='c-container']"):
253+
print(data_container.xpath("string(.//h3)").extract_first())
254+
255+
256+
if __name__ == "__main__":
257+
TestPlaywright(thread_count=1).run()
258+
```
Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# 浏览器渲染
1+
# 浏览器渲染-Selenium
22

33
采集动态页面时(Ajax渲染的页面),常用的有两种方案。一种是找接口拼参数,这种方式比较复杂但效率高,需要一定的爬虫功底;另外一种是采用浏览器渲染的方式,直接获取源码,简单方便
44

@@ -73,16 +73,6 @@ def download_midware(self, request):
7373

7474
通过 `feapder.Request`携带,优先级大于配置文件, 如:
7575

76-
```python
77-
def download_midware(self, request):
78-
request.proxies = {
79-
"http": "http://xxx.xxx.xxx.xxx:xxxx"
80-
}
81-
return request
82-
```
83-
84-
或者
85-
8676
```python
8777
def download_midware(self, request):
8878
request.proxies = {
@@ -114,6 +104,21 @@ def download_midware(self, request):
114104
return request
115105
```
116106

107+
或者
108+
109+
```python
110+
def download_midware(self, request):
111+
request.cookies = [
112+
{
113+
"domain": "xxx",
114+
"name": "xxx",
115+
"value": "xxx",
116+
"expirationDate": "xxx"
117+
},
118+
]
119+
return request
120+
```
121+
117122
## 操作浏览器对象
118123

119124
通过 `response.browser` 获取浏览器对象

0 commit comments

Comments
 (0)