python 爬虫,多进程,多线程

想要更多爬虫示例吗,还等什么呢,关注微信公众号“木下学Python”获取把~ 

 

从 360图片网站 下载 1000 张图片,一下是没用多进程,多线程下载所使用的时间

 

使用多进程,多线程后,所使用的时间, 在加了多进程,多线程的代码后面都加了一个 # 标注

 

代码:

spiderMan.py 为主逻辑运行接口

spiderMan.py:

from urlManager import urlManager
from htmlDownload import htmlDownload
from parseHtml import parseHtml
from dataOutput import dataOutput
from multiprocessing import Pool #
import json
import time


class spipderMan():
    """
    主逻辑
    """
    def __init__(self):
        """
        初始化各个模块
        """
        self.manager = urlManager()
        self.download = htmlDownload()
        self.parse = parseHtml()
        self.output = dataOutput()

    def get_url(self):
        """
        获取每一页的 url, 在这里添加多进程进行请求 url
        :return:
        """
        page_urls = self.manager.create_url()

        p = Pool() # # 创建进程池
        for page_url in page_urls:
            p.apply_async(self.request_url,args=(page_url,)) # #添加进程任务,page_url 为传进去的进程任务的参数

        p.close()  # # 不再添加新进程
        p.join()  # # 等待所有子进程执行完毕,调用之前必须先调用 close(),针对 Pool 对象

    def request_url(self,page_url):
        """
        请求每一页的 url
        :return:
        """
        # 此处的循环放到上一个函数了

        response = self.download.request_url(page_url)
        # 判断是否请求成功
        if response == None:
            print('访问网页失败,可能被反爬或网络出问题了噢~')
        # 判断是否是最后一页
        html = json.loads(response.text)
        if html['end'] != False:
            print('没有更多图片了,下载完毕!')
        else:
            self.get_img_url(html)

    def get_img_url(self,html):
        """
        解析获取每一页所有图片的 url
        :return:
        """
        img_urls = self.parse.get_this_page_img_urls(html)
        self.get_img(img_urls)

    def get_img(self,img_urls):
        """
        下载图片
        :return:
        """
        self.output.download_img(img_urls)


if __name__ == '__main__':
    # 运行主接口
    start_time = time.time()
    spider = spipderMan()
    spider.get_url()
    end_time = time.time()
    print(end_time - start_time)

 

urlManager.py:

class urlManager():
    """
    管理 url
    """
    def __init__(self):
        """
        初始化需要拼接的 url
        """
        self.base_url = 'http://image.so.com/zj?ch=beauty&sn={}&listtype=new&temp=1'

    def create_url(self):
        """
        构造每一页的 url
        :return:
        """
        urls = [self.base_url.format(str(i)) for i in range(0,1020,30)]
        return urls

 

htmlDownload.py:

import requests
import random


class htmlDownload():
    """
    网页下载
    """
    def __init__(self):
        """
        初始化请求头
        """
        USER_AGENTS = [
        
            "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:16.0) Gecko/20100101 Firefox/16.0",
            "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11",
            "Mozilla/5.0 (X11; U; Linux x86_64; zh-CN; rv:1.9.2.10) Gecko/20100922 Ubuntu/10.10 (maverick) Firefox/3.6.10"
        ]
        self.headers = {'User-Agent' : random.choice(USER_AGENTS)}


    def request_url(self,url):
        """
        请求
        :param url:
        :return:
        """
        response = requests.get(url,self.headers)
        if response.status_code == 200:
            return response
        else:
            return None

 

parseHtml.py:

class parseHtml():
    """
    解析网页,提取数据
    """
    def __init__(self):
        self.img_urls = [] # 存储图片标题和 url 的列表

    def get_this_page_img_urls(self,html):
        """
        获取此页图片的 url
        :param html:
        :return: 存储图片 url 的列表
        """
        # 打印当前下载了多少图片,先判断是否访问成功,成功就打印
        if html['list']:
            img_count = html['lastid'] - 30
            print('当前已下载 {} 张,有误差,同名的会过滤~'.format(img_count))

        for item in html['list']:
            img_title = item['group_title']
            img_url = item['qhimg_url']
            self.img_urls.append((img_title,img_url))
        return self.img_urls

 

dataOutput.py:

import os
import threading #
from htmlDownload import htmlDownload


class dataOutput():
    """
    数据输出处理
    """
    def __init__(self):
        """
        创建图片保存路径
        """
        self.root_path = r'C:\Users\13479\Desktop\python项目\我的爬虫\有无多进程,线程图片,视频下载对比\图片\多进程、线程爬取\images\\'
        # 如果没有文件路径就创建
        if not os.path.exists(self.root_path):
            os.mkdir(self.root_path)

        self.download = htmlDownload()

    def download_img(self,img_urls):
        """
        下载图片的函数, 运用多线程下载
        :param img_urls: 图片名称,url 对应的列表
        :return:
        """
        # 设置 3 个线程,每个线程下载 10 张图片, 去掉了循环
        t1 = threading.Thread(target=self.thread_run, name='Thread_1', args=(img_urls[0:15],)) #
        t2 = threading.Thread(target=self.thread_run, name='Thread_2', args=(img_urls[15:],)) #

        t1.start() # # 开启线程
        t2.start()
        t1.join() # # 等待其他线程
        t2.join()

    def thread_run(self,urls): #
        """
        线程执行的下载任务
        :param urls: 传进来的图片 url 列表
        :return:
        """
        for url in urls: #
            # 构造图片的完整下载路线
            download_path = '{}{}.jpg'.format(self.root_path,url[0])
            if not os.path.exists(download_path):
                response = self.download.request_url(url[1])
                try:
                    with open(download_path, 'wb') as f:
                        f.write(response.content)
                except:
                    pass
            else:
                pass




 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值