请教一个问题,怎么提高 python 爬虫的爬取效率?

2016-08-25 09:45:33 +08:00
 BBrother

写了个简单的协程爬虫爬取 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. 我知道多进程,但我想问问协程能不能更有效率一点。

7678 次点击
所在节点    Python
30 条回复
lbp0200
2016-08-25 09:59:49 +08:00
多个爬虫+队列( redis )
chy373180
2016-08-25 10:05:30 +08:00
协程与多进程并不冲突
fatpa
2016-08-25 10:19:20 +08:00
消息队列啊少年
abxialiang
2016-08-25 10:21:20 +08:00
使用大量的代理 ip
yangtukun1412
2016-08-25 10:21:55 +08:00
使用 requests.Session 复用连接应该能稍微快一点.
kinghui
2016-08-25 10:29:07 +08:00
使用异步非阻塞 I/O, 如 Tornado, Twisted 等框架
BBrother
2016-08-25 10:35:36 +08:00
@chy373180 我知道不冲突,但是我想知道协程能不能再快点,很直觉得觉得协程的效率没发挥出来。
BBrother
2016-08-25 10:37:31 +08:00
@fatpa 感觉没必要啊, B 站的 uid 是从 1 开始往上加的,直接切片就行了吧?
BBrother
2016-08-25 10:41:36 +08:00
@kinghui 我觉得现在的代码已经异步非阻塞了啊?
razrlele
2016-08-25 10:41:58 +08:00
看一下返回的 response status ,带宽没起来有可能是很多 request 直接被返回 403 了
BBrother
2016-08-25 10:42:31 +08:00
@abxialiang 呃,这个,有什么意义吗?
spider82
2016-08-25 10:42:41 +08:00
可以看看 stackless ,我觉得瓶颈应该不在协程那里,单设备不用代理爬早晚被 BAN 。
knightdf
2016-08-25 10:49:33 +08:00
我每次开 30 台机器爬,想要效率,只有一个途径,花钱
BBrother
2016-08-25 10:52:28 +08:00
@knightdf 残酷的现实
Mark3K
2016-08-25 10:57:54 +08:00
代码使用了 coroutine ,但仍然是单线程在跑,没有利用到多核的优势,如果不考虑对方的反爬而只考虑效率的提高的话 可以再加上多进程试试
erevus
2016-08-25 11:08:38 +08:00
多进程+协程 能用到多核
BBrother
2016-08-25 12:34:42 +08:00
哇啊,大家真热情,谢谢大家!拜谢!
BBrother
2016-08-25 12:35:18 +08:00
@razrlele 看了下, status_code 都是 200
BBrother
2016-08-25 12:45:35 +08:00
@spider82 嗯,看了下 stackless ,因为我要实现的功能比较简单,我觉得 python3.5.X 的 async/await 是够用的。现在只是试着跑跑啦,感觉差不多了就多进程+代理爬数据啦。
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).

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/301628

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX