-- Illustrations by Tom Haugomat --
陈键冬
Python中文社区专栏作者,pyecharts开源项目核心开发者。
GitHub:chenjiandongx
项目地址
1. `https
:
//github.com/chenjiandongx/async-proxy-pool`
Async Proxy Pool
异步爬虫代理池,以 Python asyncio 为基础,旨在充分利用 Python 的异步性能。
运行环境
项目使用了 sanic,一个异步网络框架。所以建议运行 Python 环境为 Python3.5+,并且 sanic 不支持 Windows 系统,Windows 用户(比如我 smile)可以考虑使用 Ubuntu on Windows。
如何使用
安装 Redis
项目数据库使用了 Redis,Redis 是一个开源(BSD 许可)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。所以请确保运行环境已经正确安装了 Redis。安装方法请参照官网指南。
下载项目源码
1. `$ git clone https:
//github.com/chenjiandongx/async-proxy-pool.git`
安装依赖
使用 requirements.txt
1. `$ pip install -r requirements.txt`
使用 pipenv Pipfile
1. `$ pipenv install`
配置文件
配置文件 config.py,保存了项目所使用到的所有配置项。如下所示,用户可以根据需求自行更改。不然按默认即可。
1. `#!/usr/bin/env python`
2. `# coding=utf-8`
3.
4. `# 请求超时时间(秒)`
5. `REQUEST_TIMEOUT = 15`
6. `# 请求延迟时间(秒)`
7. `REQUEST_DELAY = 0`
8.
9. `# redis 地址`
10. `REDIS_HOST = "localhost"`
11. `# redis 端口`
12. `REDIS_PORT = 6379`
13. `# redis 密码`
14. `REDIS_PASSWORD = None`
15. `# redis set key`
16. `REDIS_KEY = "proxies"`
17. `# redis 连接池最大连接量`
18. `REDIS_MAX_CONNECTION = 20`
19.
20. `# REDIS SCORE 最大分数`
21. `MAX_SCORE = 10`
22. `# REDIS SCORE 最小分数`
23. `MIN_SCORE = 0`
24. `# REDIS SCORE 初始分数`
25. `INIT_SCORE = 9`
26.
27. `# sanic web host`
28. `SANIC_HOST = "localhost"`
29. `# sanic web port`
30. `SANIC_PORT = 3289`
31. `# 是否开启 sanic 日志记录`
32. `SANIC_ACCESS_LOG = True`
33.
34. `# 批量测试数量`
35. `VALIDATOR_BATCH_COUNT = 256`
36. `# 校验器测试网站,可以定向改为自己想爬取的网站,如新浪,知乎等`
37. `VALIDATOR_BASE_URL = "https://httpbin.org/"`
38. `# 校验器循环周期(分钟)`
39. `VALIDATOR_RUN_CYCLE = 15`
40.
41.
42. `# 爬取器循环周期(分钟)`
43. `CRAWLER_RUN_CYCLE = 30`
44. `# 请求 headers`
45. `HEADERS = {`
46. `"X-Requested-With": "XMLHttpRequest",`
47. `"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 "`
48. `"(KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36",`
49. `}`
运行项目 运行客户端,启动收集器和校验器
1. `# 可设置校验网站环境变量 set/export VALIDATOR_BASE_URL="https://example.com"`
2. `$ python client.py`
3. `2018-05-16 23:41:39,234 - Crawler working...`
4. `2018-05-16 23:41:40,509 - Crawler √ http://202.83.123.33:3128`
5. `2018-05-16 23:41:40,509 - Crawler √ http://123.53.118.122:61234`
6. `2018-05-16 23:41:40,510 - Crawler √ http://212.237.63.84:8888`
7. `2018-05-16 23:41:40,510 - Crawler √ http://36.73.102.245:8080`
8. `2018-05-16 23:41:40,511 - Crawler √ http://78.137.90.253:8080`
9. `2018-05-16 23:41:40,512 - Crawler √ http://5.45.70.39:1490`
10. `2018-05-16 23:41:40,512 - Crawler √ http://117.102.97.162:8080`
11. `2018-05-16 23:41:40,513 - Crawler √ http://109.185.149.65:8080`
12. `2018-05-16 23:41:40,513 - Crawler √ http://189.39.143.172:20183`
13. `2018-05-16 23:41:40,514 - Crawler √ http://186.225.112.62:20183`
14. `2018-05-16 23:41:40,514 - Crawler √ http://189.126.66.154:20183`
15. `...`
16. `2018-05-16 23:41:55,866 - Validator working...`
17. `2018-05-16 23:41:56,951 - Validator × https://114.113.126.82:80`
18. `2018-05-16 23:41:56,953 - Validator × https://114.199.125.242:80`
19. `2018-05-16 23:41:56,955 - Validator × https://114.228.75.17:6666`
20. `2018-05-16 23:41:56,957 - Validator × https://115.227.3.86:9000`
21. `2018-05-16 23:41:56,960 - Validator × https://115.229.88.191:9000`
22. `2018-05-16 23:41:56,964 - Validator × https://115.229.89.100:9000`
23. `2018-05-16 23:41:56,966 - Validator × https://103.18.180.194:8080`
24. `2018-05-16 23:41:56,967 - Validator × https://115.229.90.207:9000`
25. `2018-05-16 23:41:56,968 - Validator × https://103.216.144.17:8080`
26. `2018-05-16 23:41:56,969 - Validator × https://117.65.43.29:31588`
27. `2018-05-16 23:41:56,971 - Validator × https://103.248.232.135:8080`
28. `2018-05-16 23:41:56,972 - Validator × https://117.94.69.166:61234`
29. `2018-05-16 23:41:56,975 - Validator × https://103.26.56.109:8080`
30. `...`
运行服务器,启动 web 服务
1. `$ python server.py`
2. `[2018-05-16 23:36:22 +0800] [108] [INFO] Goin' Fast @ http://localhost:3289`
3. `[2018-05-16 23:36:22 +0800] [108] [INFO] Starting worker [108]`
总体架构
项目主要几大模块分别是爬取模块,存储模块,校验模块,调度模块,接口模块。
- 爬取模块 负责爬取代理网站,并将所得到的代理存入到数据库,每个代理的初始化权值为 INIT_SCORE。
- 存储模块 封装了 Redis 操作的一些接口,提供 Redis 连接池。
- 校验模块 验证代理 IP 是否可用,如果代理可用则权值 +1,最大值为 MAX_SCORE。不可用则权值 -1,直至权值为 0 时将代理从数据库中删除。
- 调度模块 负责调度爬取器和校验器的运行。
- 接口模块 使用 sanic 提供 WEB API 。
/
欢迎页面
1. `$ http http://localhost:3289/`
2. `HTTP/1.1 200 OK`
3. `Connection: keep-alive`
4. `Content-Length: 42`
5. `Content-Type: application/json`
6. `Keep-Alive: 5`
7.
8. `{`
9. `"Welcome": "This is a proxy pool system."`
10. `}`
/pop
随机返回一个代理,分三次尝试。
- 尝试返回权值为 MAX_SCORE,也就是最新可用的代理。
- 尝试返回随机权值在 (MAXSCORE -3) - MAXSCORE 之间的代理。
- 尝试返回权值在 0 - MAX_SCORE 之间的代理
1. `$ http http://localhost:3289/pop`
2. `HTTP/1.1 200 OK`
3. `Connection: keep-alive`
4. `Content-Length: 38`
5. `Content-Type: application/json`
6. `Keep-Alive: 5`
7.
8. `{`
9. `"http": "http://46.48.105.235:8080"`
10. `}`
/get/<count:int>
返回指定数量的代理,权值从大到小排序。
1. `$ http http://localhost:3289/get/10`
2. `HTTP/1.1 200 OK`
3. `Connection: keep-alive`
4. `Content-Length: 393`
5. `Content-Type: application/json`
6. `Keep-Alive: 5`
7.
8. `[`
9. `{`
10. `"http": "http://94.177.214.215:3128"`
11. `},`
12. `{`
13. `"http": "http://94.139.242.70:53281"`
14. `},`
15. `{`
16. `"http": "http://94.130.92.40:3128"`
17. `},`
18. `{`
19. `"http": "http://82.78.28.139:8080"`
20. `},`
21. `{`
22. `"http": "http://82.222.153.227:9090"`
23. `},`
24. `{`
25. `"http": "http://80.211.228.238:8888"`
26. `},`
27. `{`
28. `"http": "http://80.211.180.224:3128"`
29. `},`
30. `{`
31. `"http": "http://79.101.98.2:53281"`
32. `},`
33. `{`
34. `"http": "http://66.96.233.182:8080"`
35. `},`
36. `{`
37. `"http": "http://61.228.45.165:8080"`
38. `}`
39. `]`
/count
返回代理池中所有代理总数
1. `$ http http://localhost:3289/count`
2. `HTTP/1.1 200 OK`
3. `Connection: keep-alive`
4. `Content-Length: 15`
5. `Content-Type: application/json`
6. `Keep-Alive: 5`
7.
8. `{`
9. `"count": "698"`
10. `}`
/count/<score:int>
返回指定权值代理总数
1. `$ http http://localhost:3289/count/10`
2. `HTTP/1.1 200 OK`
3. `Connection: keep-alive`
4. `Content-Length: 15`
5. `Content-Type: application/json`
6. `Keep-Alive: 5`
7.
8. `{`
9. `"count": "143"`
10. `}`
/clear/<score:int>
删除权值小于等于 score 的代理
1. `$ http http://localhost:3289/clear/0`
2. `HTTP/1.1 200 OK`
3. `Connection: keep-alive`
4. `Content-Length: 22`
5. `Content-Type: application/json`
6. `Keep-Alive: 5`
7.
8. `{`
9. `"Clear": "Successful"`
10. `}`
扩展爬取网站
在 crawler.py 文件里新增你自己的爬取方法。
1. `class Crawler:`
2.
3. `@staticmethod`
4. `def run():`
5. `...`
6.
7. `# 新增你自己的爬取方法`
8. `@staticmethod`
9. `@collect_funcs # 加入装饰器用于最后运行函数`
10. `def crawl_xxx():`
11. `# 爬取逻辑`
sanic 性能测试
使用 wrk 进行服务器压力测试。基准测试 30 秒, 使用 12 个线程, 并发 400 个 http 连接。
1. `$ wrk -t12 -c400 -d30s http://127.0.0.1:3289/pop`
2. `Running 30s test @ http://127.0.0.1:3289/pop`
3. `12 threads and 400 connections`
4. `Thread Stats Avg Stdev Max +/- Stdev`
5. `Latency 350.37ms 118.99ms 660.41ms 60.94%`
6. `Req/Sec 98.18 35.94 277.00 79.43%`
7. `33694 requests in 30.10s, 4.77MB read`
8. `Socket errors: connect 0, read 340, write 0, timeout 0`
9. `Requests/sec: 1119.44`
10. `Transfer/sec: 162.23KB`
测试 http://127.0.0.1:3289/get/10
1. `Running 30s test @ http://127.0.0.1:3289/get/10`
2. `12 threads and 400 connections`
3. `Thread Stats Avg Stdev Max +/- Stdev`
4. `Latency 254.90ms 95.43ms 615.14ms 63.51%`
5. `Req/Sec 144.84 61.52 320.00 66.58%`
6. `46538 requests in 30.10s, 22.37MB read`
7. `Socket errors: connect 0, read 28, write 0, timeout 0`
8. `Requests/sec: 1546.20`
9. `Transfer/sec: 761.02KB`
性能还算不错,再测试一下没有 Redis 操作的 http://127.0.0.1:3289/
1. `$ wrk -t12 -c400 -d30s http://127.0.0.1:3289/`
2. `Running 30s test @ http://127.0.0.1:3289/`
3. `12 threads and 400 connections`
4. `Thread Stats Avg Stdev Max +/- Stdev`
5. `Latency 127.86ms 41.71ms 260.69ms 55.22%`
6. `Req/Sec 258.56 92.25 520.00 68.90%`
7. `92766 requests in 30.10s, 13.45MB read`
8. `Requests/sec: 3081.87`
9. `Transfer/sec: 457.47KB`
Requests/sec: 3081.87
关闭 sanic 日志记录,测试 http://127.0.0.1:3289/
1. `$ wrk -t12 -c400 -d30s http://127.0.0.1:3289/`
2. `Running 30s test @ http://127.0.0.1:3289/`
3. `12 threads and 400 connections`
4. `Thread Stats Avg Stdev Max +/- Stdev`
5. `Latency 34.63ms 12.66ms 96.28ms 58.07%`
6. `Req/Sec 0.96k 137.29 2.21k 73.29%`
7. `342764 requests in 30.10s, 49.69MB read`
8. `Requests/sec: 11387.89`
9. `Transfer/sec: 1.65MB`
Requests/sec: 11387.89
实际代理性能测试
test_proxy.py 用于测试实际代理性能
运行代码
1. `$ cd test`
2. `$ python test_proxy.py`
3.
4. `# 可设置的环境变量`
5. `TEST_COUNT = os.environ.get("TEST_COUNT") or 1000`
6. `TEST_WEBSITE = os.environ.get("TEST_WEBSITE") or "https://httpbin.org/"`
7. `TEST_PROXIES = os.environ.get("TEST_PROXIES") or "http://localhost:3289/get/20"`
实测效果
https://httpbin.org/
1. `测试代理: http://localhost:3289/get/20`
2. `测试网站: https://httpbin.org/`
3. `测试次数: 1000`
4. `成功次数: 1000`
5. `失败次数: 0`
6. `成功率: 1.0`
https://taobao.com
1. `测试代理: http://localhost:3289/get/20`
2. `测试网站: https://taobao.com/`
3. `测试次数: 1000`
4. `成功次数: 984`
5. `失败次数: 16`
6. `成功率: 0.984`
https://baidu.com
1. `测试代理: http://localhost:3289/get/20`
2. `测试网站: https://baidu.com`
3. `测试次数: 1000`
4. `成功次数: 975`
5. `失败次数: 25`
6. `成功率: 0.975`
https://zhihu.com
1. `测试代理: http://localhost:3289/get/20`
2. `测试网站: https://zhihu.com`
3. `测试次数: 1000`
4. `成功次数: 1000`
5. `失败次数: 0`
6. `成功率: 1.0`
可以看到其实性能是非常棒的,成功率极高。 wink
实际应用示例
1. `import random`
2.
3. `import requests`
4.
5. `# 确保已经启动 sanic 服务`
6. `# 获取多个然后随机选一个`
7.
8. `try:`
9. `proxies = requests.get("http://localhost:3289/get/20").json()`
10. `req = requests.get("https://example.com", proxies=random.choice(proxies))`
11. `except:`
12. `raise`
13.
14. `# 或者单独弹出一个`
15.
16. `try:`
17. `proxy = requests.get("http://localhost:3289/pop").json()`
18. `req = requests.get("https://example.com", proxies=proxy)`
19. `except:`
20. `raise`
aiohttp 的坑
整个项目都是基于 aiohttp 这个异步网络库的,在这个项目的文档中,关于代理的介绍是这样的。
划重点:aiohttp supports HTTP/HTTPS proxies
但是,它根本就不支持 https 代理好吧,在它的代码中是这样写的。
划重点:Only http proxies are supported
我的心情可以说是十分复杂的。astonished 不过只有 http 代理效果也不错没什么太大影响,参见上面的测试数据。
参考借鉴项目
- ProxyPool
- proxy_pool
License
MIT ©chenjiandongx
Python中文社区
全球Python中文开发者的
精神部落
Python中文社区作为一个去中心化的全球技术社区,以成为全球20万Python中文开发者的精神部落为愿景,目前覆盖各大主流媒体和协作平台,与阿里、腾讯、百度、微软、亚马逊、开源中国、极客邦、CSDN等业界知名公司和技术社区建立了广泛的联系,拥有来自十多个国家和地区数万名登记会员,会员来自以公安部、工信部、清华大学、北京大学、北京邮电大学、中国人民银行、中科院、中金、华为、BAT、谷歌、微软等为代表的政府机关、科研单位、金融机构以及海内外知名公司,全平台近20万开发者关注。
最近热门文章
▼ 点击下方 阅读原文 , 免费成为 社区会员