写了个简单的协程爬虫爬取 B 站用户信息,代码如下:
import requests
import re
import json
import datetime
import asyncio
def get_info(uid):
url_info = "http://space.bilibili.com/ajax/member/GetInfo?mid=" #基本信息
uid = str(uid)
return loop.run_in_executor(None, requests.get, url_info+uid)
async def user_info(num):
for uid in range(num, num+10):
info = await get_info(uid)
info = json.loads(info.text)["data"]
try:
# print(datetime.datetime.fromtimestamp(info['regtime']))
print("ok", uid)
print(info)
except UnicodeEncodeError as e:
print("UnicodeEncodeError:", e)
except TypeError:
print(info)
loop = asyncio.get_event_loop()
try:
loop.run_until_complete(asyncio.wait([user_info(x) for x in range(1, 1000, 10)]))
except Exception as e:
print("Error:", e)
爬取 1000 条需要 50 秒左右,而且带宽占用也只有 220Kbps 左右的样子,有没有什么办法提高爬取的速度? B 站用户有 3800 万左右。
谢谢指教。
ps:1. 没机器做分布式 2. 我知道多进程,但我想问问协程能不能更有效率一点。
1
lbp0200 2016-08-25 09:59:49 +08:00
多个爬虫+队列( redis )
|
2
chy373180 2016-08-25 10:05:30 +08:00 via iPhone
协程与多进程并不冲突
|
3
fatpa 2016-08-25 10:19:20 +08:00
消息队列啊少年
|
4
abxialiang 2016-08-25 10:21:20 +08:00
使用大量的代理 ip
|
5
yangtukun1412 2016-08-25 10:21:55 +08:00
使用 requests.Session 复用连接应该能稍微快一点.
|
6
kinghui 2016-08-25 10:29:07 +08:00
使用异步非阻塞 I/O, 如 Tornado, Twisted 等框架
|
10
razrlele 2016-08-25 10:41:58 +08:00 via iPhone
看一下返回的 response status ,带宽没起来有可能是很多 request 直接被返回 403 了
|
11
BBrother OP @abxialiang 呃,这个,有什么意义吗?
|
12
spider82 2016-08-25 10:42:41 +08:00
可以看看 stackless ,我觉得瓶颈应该不在协程那里,单设备不用代理爬早晚被 BAN 。
|
13
knightdf 2016-08-25 10:49:33 +08:00
我每次开 30 台机器爬,想要效率,只有一个途径,花钱
|
15
Mark3K 2016-08-25 10:57:54 +08:00
代码使用了 coroutine ,但仍然是单线程在跑,没有利用到多核的优势,如果不考虑对方的反爬而只考虑效率的提高的话 可以再加上多进程试试
|
16
erevus 2016-08-25 11:08:38 +08:00
多进程+协程 能用到多核
|
17
BBrother OP 哇啊,大家真热情,谢谢大家!拜谢!
|
19
BBrother OP @spider82 嗯,看了下 stackless ,因为我要实现的功能比较简单,我觉得 python3.5.X 的 async/await 是够用的。现在只是试着跑跑啦,感觉差不多了就多进程+代理爬数据啦。
|
20
kinghui 2016-08-25 15:11:07 +08:00
@BBrother https://docs.python.org/3/library/asyncio-eventloop.html#executor
> Call a function in an Executor (pool of threads or pool of processes). By default, an event loop uses a thread pool executor (ThreadPoolExecutor). |
21
JhZ7z587cYROBgVQ 2016-08-25 15:33:16 +08:00
为啥不用 aiohttp 要用 requests 呢?不会被阻塞住么?
|
22
wmjie 2016-08-25 17:48:26 +08:00 1
requests 会被阻塞,换成 aiohttp 试试;
https://github.com/aosabook/500lines/tree/master/crawler |
23
soulmine 2016-08-25 18:18:48 +08:00
不挂代理池+搞分布式然后多线程 你跑到下个月也跑不完
|
24
pncltp 2016-08-25 18:27:59 +08:00 via iPhone
为什么要重新造轮子,用 scrapy 库呗。
|
25
mutalisk 2016-08-26 08:03:22 +08:00 via iPhone 1
requests+gevent
|
26
hard2reg 2016-08-26 14:44:04 +08:00
你好,我是 B 站的运维。我打算在后端加入反爬虫代码了!
|
28
Shliesce 2016-08-26 18:01:53 +08:00
我是 B 站的研发,我要取消这个接口了。
|