一个将多线程多进程结合爬取图片网站的示例

本文介绍了如何结合多线程和多进程技术来提高图片爬取效率。通过实例展示了在爬取大量图片时,多线程用于图片下载,多进程用于爬取多个页面,从而有效利用系统资源,提升爬取速度。

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

在图片网站爬取图片时候,我们需要取得具体每张图片的url地址,然后下载到电脑保存下来。这其中,对时间消耗最多的步骤是保存图片到本地硬盘,机械硬盘的读写性能速度较慢。如果采取单线程单进程的话,在读写的同时没法进行其他的操作,只能等待,浪费了性能。
对单个存有图片的页面而言,如果可以采取多线程的话,在写入图片的同时还能去请求新的图片地址保存到列表将会更合理的利用时间。因为图片网站,图片存放在很多页面里,所以对多个存有图片的页面而言采取 多进程,同时对多个有图片的页面进行爬取任务。
至于你要爬取什么样的图片网站, 我不得而知,不同网站展示图片界面不同或许与我的有差异但主体思路就这样。

接下来上代码:

import requests ,time,threading
from  lxml.html import etree
from  fake_useragent import UserAgent
from multiprocessing import Pool


#得到自己爬取页网址
def get_Url(P):

    Url='保密'.format(P)
    return Url
#得到10个尤物的名字
def get_names(Url):
    all_names=[]
    header = {'User-Agent': UserAgent().chrome}
    response = requests.get(url=Url, headers=header)
    response.encoding = 'GB18030'
    e = etree.HTML(response.text)
    picture_name = e.xpath('//h2/a')
    for k in range(10):
        all_names.append(picture_name[k].text)
    return all_names
#得到第i个尤物的名字 i 0 9
def get_i_name(all_names,i):
    i_name=all_names[i]
    return i_name

#得到10个尤物的首网址
def get_url(Url):
    all_urls=[]
    header = {'User-Agent' : UserAgent().chrome}
    response=requests.get(url=Url,headers=header)
    response.encoding='GB18030'
    e=etree.HTML(response.text)
    url=e.xpath('//h2//@href')
    for k in range(10):
        new_url = 'https://qqr57.com' + url[k]
        all_urls.append(new_url)
    return all_urls
#得到第i个尤物的首地址
def get_i_url(all_urls,i):
    i_url=all_urls[i]
    return i_url
#得到第i个尤物存在图片的地址
def i_girl_pictures_urls(i_url):
    mod_page_urls=[]
    header = {'User-Agent': UserAgent().chrome}
    response = requests.get(url=i_url, headers=header)
    response.encoding = 'GB18030'
    e = etree.HTML(response.text)
    next_page = (e.xpath('//li[@class="next-page"]/a'))[0].text
    j = 1
    #空列表=false
    while next_page  :
        j = j + 1
        last_page = i_url.replace('.html', '_' + str(j) + '.html')
        new_new_url = last_page
        header = {'User-Agent': UserAgent().chrome}
        response = requests.get(url=new_new_url, headers=header)
        response.encoding = 'GB18030'
        e = etree.HTML(response.text)
    #     # time.sleep(0.05)
        next_page = (e.xpath('//li[@class="next-page"]/a'))
        # print(next_page)
        mod_page_urls.append(new_new_url)
    mod_page_urls.append(i_url)
    return mod_page_urls

#得到第i尤物所有图片地址
def girl_jpg_urls(mod_page_urls):
    girl_pictures_urls=[]
    for a in range(len(mod_page_urls)):
        # 一只尤物某一个网页的图片链接地址
        time.sleep(0.1)
        girl_urls = mod_page_urls[a]
        # 一只尤物的所有图片地址
        header = {'User-Agent': UserAgent().chrome}
        response = requests.get(url=girl_urls, headers=header)
        response.encoding = 'GB18030'
        e = etree.HTML(response.text)
        girl_pictures_url = (e.xpath('//article[@class="article-content"]/p/img/@src'))
        girl_pictures_urls+=(girl_pictures_url)
    print(girl_pictures_urls)
    return girl_pictures_urls

#根据所有图片地址 下载第i个尤物的图片
def save_imgs(girl_pictures_urls,i_name):
    x = len(girl_pictures_urls)
    for b in range(x):
        r = requests.get(url=girl_pictures_urls[b])
        time.sleep(0.2)
        print("正在爬取尤物" + i_name + str(b) + '进度:' + str(100 * (b + 1) / x) + '%')
        with open('保密/{}.jpg'.format(i_name + str(b)), 'wb') as f:
            f.write(r.content)

#多线程下载单页的所有图片
def thread(P):
    threads = []
    Url=get_Url(P)
    all_names=get_names(Url)
    all_urls=get_url(Url)
    for i in range(10):
        i_name = get_i_name(all_names, i)
        i_url = get_i_url(all_urls, i)
        mod_page_urls = i_girl_pictures_urls(i_url)
        girl_pictures_urls = girl_jpg_urls(mod_page_urls)

        # save_imgs(girl_pictures_urls,i_name)
        t = threading.Thread(target=save_imgs,args=(girl_pictures_urls,i_name))
        threads.append(t)
    for i in threads:
        i.start()
    for i in threads:
        i.join()
#多进程请求不同的页面
def process(P):
    pool = Pool(processes=4) #定义一个进程池,最大进程数为4,默认大小为CPU核数
    for i in range(P):
        pool.apply_async(func=thread, args=(i,))
    pool.close()
    pool.join()


# 主程序
if __name__ == '__main__':
    P=int(input('输入爬取的页面数量:'))
    start=time.time()
    process(P)
    end=time.time()
    print(str(end-start))

上效果图:
在这里插入图片描述
共有634张图片,
在这里插入图片描述
用时701秒,
在这里插入图片描述
单张图片用时约1.1秒
速度比较慢。这是因为,我只爬取得一个页面做了个示范,只体现出了多线程优势,多进程的优势没有体现出来。

再来一个示范:
在这里插入图片描述
这次我爬取了2694张图片 ,用时895秒,单张图片用时约0.3秒。因为我这次爬取的页数为4,CPU核数也为4,多进程的优势正好可以利用起来。
当页面数越多,图片数越多,节省的时间也越多。看着数据不断爬取下来的过程,很舒服啊
在这里插入图片描述
最终我一共爬取了4万多张图片。用时没统计,感觉不到 半小时。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值