首页 > 系统相关 >进程+线程+队列爬取斗图网

进程+线程+队列爬取斗图网

时间:2023-01-19 23:13:54浏览次数:47  
标签:src img get url 图网 headers 线程 取斗 data

  • 需求:爬取斗图网数据
  • 首先我们使用线程的方式,爬取前4页数据
    • 准备工作
      • 图片链接存在页面源代码中
      • 但是,界面使用了懒加载技术,真正的url在data-original中
import requests
from lxml import etree
from concurrent.futures import ThreadPoolExecutor
import time

def get_src_url():
    for page in range(1, 5):
        url = f'https://www.pkdoutu.com/photo/list/?page={page}'
        headers = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36"
        }
        resp = requests.get(url =url,headers = headers)
        tree = etree.HTML(resp.text)
        data_original_list = tree.xpath("//li[@class='list-group-item']//a/img/@data-original")
        #下载图片
        with ThreadPoolExecutor(10) as t:
            for src_url in data_original_list:
                print(src_url)
                # download_img(src_url)
                t.submit(download_img,src_url)
                print('一张图片下载完成')

def download_img(url):
    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36"
    }
    img_data = requests.get(url=url,headers=headers).content
    img_name = url.split('/')[-1]
    with open(f'doutu/{img_name}','wb') as f:
        f.write(img_data)

if __name__ == '__main__':
    start = time.time()
    get_src_url()
    end = time.time()
    print(f'总共用时:{end - start}')
  • 使用上述代码,总共花了16s时间

  • 思考:

    • 我们在下载图片的时候,使用了多线程,但是获取图片url还是单线程的
    • 需要等待前一页数据下载完毕才会获取下一页图片的地址
    • 如果,我们使用两个进程,一个专门负责获取图片地址,另外一个专门下载图片,效率是不是会加快呢?
      • 但是,进程只能是不能直接通信的
      • 一般来讲,进程之间想要相互通信,我们有以下几种办法
        • 文件,效率慢,并发不好处理
        • 网络,需要写网络传输,麻烦
        • 队列--本篇使用方法,注意:不是所有队列都支持进程之间通信,python中使用multiprocess(底层就是网络传输)
        • 数据库
import requests
from lxml import etree
from concurrent.futures import ThreadPoolExecutor
import time
from multiprocessing import Queue
from multiprocessing import Process

#专门获取url
def get_src_url(q):
    for page in range(1, 5):
        url = f'https://www.pkdoutu.com/photo/list/?page={page}'
        headers = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36"
        }
        resp = requests.get(url =url,headers = headers)
        tree = etree.HTML(resp.text)
        data_original_list = tree.xpath("//li[@class='list-group-item']//a/img/@data-original")
        for src_url in data_original_list:
            print(src_url)
            # download_img(src_url)
            #把拿到的url 塞入队列
            q.put(src_url)
    q.put("结束")
    #第一个进程跑完后,塞入一个结束的标志,不然第二个进程不知道啥时候结束
    #注意:不能用判断队列为空结束

#第二个进程,负责下载图片
def img_process(q):     #从队列中提取url,下载图片
    with ThreadPoolExecutor(10) as t:
        while 1:       #不确定队列中有多少个,那就一直那,直到取到结束标志
            img_url = q.get()         #get是一个阻塞操作
            if img_url == '结束':
                break
            t.submit(download_img,img_url)


def download_img(url):
    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36"
    }
    img_data = requests.get(url=url,headers=headers).content
    img_name = url.split('/')[-1]
    with open(f'doutu/{img_name}','wb') as f:
        f.write(img_data)

if __name__ == '__main__':
    #准备队列
    start = time.time()
    q = Queue()   #主进程
    p1 = Process(target=get_src_url,args=(q,))    #单独开辟了内存空姐
    p2 = Process(target=img_process,args=(q,))

    p1.start()
    p2.start()

    p1.join()
    p2.join()

    end = time.time()
    print(f'总共用时:{end - start}')

标签:src,img,get,url,图网,headers,线程,取斗,data
From: https://www.cnblogs.com/xwltest/p/17062271.html

相关文章

  • 多线程threading in Python
    SimpleExample1importtimeimportthreadingstart=time.perf_counter()defdo_something(): print('sleeping1second...') time.sleep(1) print('Doneslee......
  • 线程安全单例设计模式
    一、什么是单例设计模式中的线程安全?首先,创建一个单例类:publicsealedclassGuidService{privatestaticintcounter=0;privatestaticGuidService?_gu......
  • 谷歌浏览器启用多线程下载
    谷歌浏览器启用多线程下载功能教程1、双击进入软件,在页面上方地址栏中输入“chrome://flags/#enable-parallel-downloading”并回车访问   2、进入新界......
  • 【并发编程】线程间的通信
    文章目录​​1.wait、notify、notifyAll​​​​2.生产者消费者模型​​​​3.管道流进行线程间的通信​​​​4.Thread.join()方法​​​​5.Condition详解​​1.wait、not......
  • 线程池处理爬虫电影票房排行榜
    需求:爬取1996-2023年电影票房排行榜首先,我们先爬取一年的数据,然后通过循环,逐一爬取每一年的数据。通过测试,话费时间32秒,代码如下:importrequestsfromlxmlimportetr......
  • 【并发编程】线程安全性问题
    文章目录1.什么是线程安全性2.原子性操作3.深入理解synchronized3.4.volatile关键字3.5.happens-before规则3.6.如何避免线程安全性问题1.什么是线程安全性当......
  • 【并发编程】线程的基础知识篇
    文章目录1.进程与线程的区别2.线程的状态相互转换3.创建线程的方式4.线程的挂起和恢复5.线程的中断操作6.线程的优先级7.守护线程1.进程与线程的区别(1)什么是......
  • jmeter添加全局变量,跨线程组传递参数
    在软件测试中,当我们想把某个变量值想设置为全局变量,也就是在任何一个线程组都可以使用该变量时,我们就要用到BeanShell取样器,示例如下:1.拿到某个接口的变量值2.通过BeanSh......
  • 多线程知识总结
    多线程1、线程简介1、关键字:任务、进程、进程、多线程2、普通方法调用和多线程3、核心概念线程是独立的执行路劲在程序运行时,及时没有自己创建线程,后台也会有......
  • 如何使用Java异步编程(多线程CompletableFuture)
    1、创建异步线程任务根据supplier创建CompletableFuture任务//使用内置线程ForkJoinPool.commonPool(),根据supplier构建执行任务publicstatic<U>CompletableFuture......