今天需要写一个功能,需要爬350万个url,并且做解析。
初步探明,被爬网站没有反爬策略,所以剩下的就是如何快速爬取。
选择多进程
通过redis,multiprocessing运行,发现结果有问题,
原因如下:
array = list(conn.smembers("city_key"))
array有350万个
由于是多进程,每一个进程都运行
share = array[int(index * part) : int((index + 1) * part)]
所以,每个进程都拷贝了一份array,300多万个array,直接就是350万* 100(个进程) = 3.5亿个, 我的笔记本直接内存不足。。。
import requests
import redis
from multiprocessing import Process
conn = redis.StrictRedis(host='127.0.0.1')
array = list(conn.smembers("city_key"))
size = len(array)
part = size * 1.0 / 100
def crawl(url):
result = None
result = crawl_sub(url)
if result:
conn.sadd("city_result_key", result)
def get_url(share):
for item in share:
crawl(item)
if __name__ == "__main__":
jobs = []
for one in range(100):
p = Process(target=get_url, args=(array[int(index * part) : int((index + 1) * part)],))
p.start()
jobs.append(p)
for p in jobs:
p.join()
痛定思痛,决定用python的gevent协程。直接轻松加愉快,不再有内存爆炸问题了。
import redis
from gevent import monkey
from gevent.pool import Pool
monkey.patch_all()
pool = Pool(100)
size = len(array)
part = size * 1.0 / 100
conn = redis.StrictRedis(host='127.0.0.1')
array = list(conn.smembers("city_key"))
def crawl(url):
result = crawl_sub(url)
if result:
conn.sadd("city_result_key", result)
def get_url(index):
share = array[int(index * part) : int((index + 1) * part)]
for item in share:
crawl(item)
if __name__ == "__main__":
for one in range(100):
pool.spawn(get_url, one)
pool.join()