小爬虫,线程,进程?

本文探讨了在大规模URL爬取任务中遇到的内存爆炸问题,并通过使用gevent协程成功解决了该问题。详细介绍了问题的根源、采用多进程与Redis的尝试及其失败,最终引入gevent协程的解决方案,以及如何合理分配任务以避免内存泄露。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天需要写一个功能,需要爬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()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值