python 多线程的爬虫实例

python 多线程的爬虫实例

GetHtml方法
    def GetHtml(self, url):
        '''
        获取源码的封装
        :param url: 传入url链接
        :return: 返回该连接对应源码
        '''
        try:#处理异常
            address = {'user-agent': 'Mozilla/5.0'}#虚拟请求地址,有的网站会检查是否浏览器浏览
            r = requests.get(url)
            r.encoding = r.apparent_encoding
            r.raise_for_status()
            html = r.text#获取到源码
            return html
        except:
            pass
Geturl_1方法
  def Geturl_1(self,):
        '''
        获取到所有的页面链接,
        无返回值,结果直接存在self.url1_list
        '''
        start_time = time.clock()
        print('页面资源加载开始')
        try:
            for i in range(2, 160):
                url = 'https://004647.com/list-14-%s.html' % i
                self.url1_list.append(url)
            print('页面资源加载完毕')
            end_time = time.clock()
            print('页面资源加载耗时:%.2f' % (end_time - start_time))
        except:
            pass
Geturl_2方法
   def Geturl_2(self,size):
        try:
            def func2():
                '''
                1.解析主页面连接,获得组图资源连接
                2.无返回值,结果直接存在self.url2_list
                3.这里封装成函数,是因为数据请求是,I/O操作,
                    通过多线程可以提高效率
                '''
                while self.url1_list:
                    url = self.url1_list.pop()#为了避免重复,采用pop
                    size_new = len(self.url1_list)
                    resu = '数据已加载:%.2f%%' % (((size - size_new) / size) * 100)
                    print('\r%s' % resu, end='', flush=True)#时间较久,加进度条
                    html=self.GetHtml(url)#获取源码,解析,获取相关数据
                    re_url = '<ul class="detail-list">.+?</ul></div></div>'
                    ret = re.findall(re_url, html, re.S)
                    res = re.findall("https://.+?/article.+?.html", ret[0])
                    res = set(res)
                    for ele in res:#将获取到的数据写入到url2_list中
                        self.url2_list.append(ele)

            start_time = time.clock()
            print('数据资源加载开始')

            for i in range(6):
                #根据电脑CPU核数获得最优线程数,这里采用了核数*2+2
                t2 = threading.Thread(target=func2)
                t2.start()
            t2.join()
            print('数据资源加载完毕')
            end_time = time.clock()
            print('数据资源加载耗时:%.2f' % (end_time - start_time))
            #获取下加载时间
        except:
            t2 = threading.Thread(target=func2)
            t2.start()
Download方法
    def Download(self,):
        '''
        下载逻辑代码存放
        :无返回值,直接存放对应位置
        '''
        print('下载图片中')
        try:
            def save():
                try:
                    while self.url2_list:
                        url=self.url2_list.pop()#依次取,避免重复
                        html = self.GetHtml(url)#获取源码
                        ret = re.findall('<h1>(?P<name>.+?)<span> (?P<num>.+?)</span></h1>', html, re.S)
                        res = re.findall('\d+', ret[0][1], re.S)
                        file_name=ret[0][0]#获取组图名
                        N=int(res[1])#获取组图总数量
                        save_path=self.address+'爬虫照片/'#设置储存位置,从传入的盘符
                        if os.path.isdir(save_path):
                            #判断是否有该路径,有的话继续,没有创建
                            pass
                        else:
                            os.mkdir(save_path)
                        file_path = os.path.join(save_path, file_name)
                        #拼接组图文件夹,存放组图图片
                        if os.path.isdir(file_path):
                            # 判断是否有该路径,有的话继续,没有创建
                            print('%s组图已存在'%file_path)
                            pass
                        else:
                            os.mkdir(file_path)
                        for i in range(2, N):
                            #拼接组图中每张图片链接
                            str1 = '%s%s.html' % ('-', str(i))
                            new_url = url.replace('.html', str1)
                            Picture_path=os.path.join(file_path, str(i)+'.gif')
                            #拼接文件储存位置
                            if os.path.isfile(Picture_path):
                                # 判断是否有该图片,有的话跳过,没有下载
                                print('%s图片已存在'% file_name+str(i)+'.gif')
                                continue
                            else:
                                new_html = self.GetHtml(new_url)#获取到图片链接
                                data_url = re.findall('https://img.+?gif', new_html, re.S)
                                data = requests.get(data_url[0])
                                print('正在下载%s' % file_name + str(i) + '.gif')
                                with open(Picture_path, 'wb') as f:#储存图片
                                    f.write(data.content)
                                    print('%s下载完成' % (file_name + str(i) + '.gif'))
                except:
                    t3 = threading.Thread(target=save, )
                    t3.start()
            for i in range(6):
                t3= threading.Thread(target=save,)
                t3.start()
            t3.join()
        except:
            pass
run方法
   def run(self):
        '''
        主程序
        '''
        self.Geturl_1()
        base_url1_size = len(self.url1_list)
        self.Geturl_2(base_url1_size)
        self.Download()
show函数
def show():
    print('''
        请输入对应序号,任意键默认为C盘
        1. C盘
        2. D盘
        3. E盘
        4. F盘
        5. G盘
        6. H盘
        ''')
    dic={'2':'D:/','3':'E:/','4':'F:/','5':'G:/','6':'H:/'}#输入的命令对应关系
    while 1:#选择好盘符后进行爬取
        add=input('请输入储存位置:')
        if dic[add] and os.path.isdir(dic[add]):
            addr=dic[add]
            return addr
        else:
            print('''
            磁盘不存在或者输入有误
            1. 重新输入
            2. 默认存在C盘
            3. 任意键退出程序
            ''')
            N=input('请输入对应序号:')
            if N=='1':
                continue
            elif N=='2':
                addr='C:/'
                return addr
            else:
                addr=None
                return addr
将.py文件封装成.exe文件
  1. 使用pyinstaller模块
  2. 将py文件放到pyinstaller模块安装目录下
  3. dos命令窗口输入pyinstaller xx.py,回车
  4. 在pyinstaller模块安装路径中dist文件夹,找到封装好的.exe
  5. 应用程序无法上传,可直接用源码自己进行封装

源码:

import requests
import re
import threading
import os
import time

class MyBaby(object):
    def __init__(self,address):#address为了简洁只支持盘符
        self.address=address
        self.url1_list=[]#存放主页面url连接
        self.url2_list=[]#存放组图资源url连接

    def Geturl_1(self,):
        '''
        获取到所有的页面链接,
        无返回值,结果直接存在self.url1_list
        '''
        start_time = time.clock()
        print('页面资源加载开始')
        try:
            for i in range(2, 160):
                url = 'https://004647.com/list-14-%s.html' % i
                self.url1_list.append(url)
            print('页面资源加载完毕')
            end_time = time.clock()
            print('页面资源加载耗时:%.2f' % (end_time - start_time))
        except:
            pass

    def Geturl_2(self,size):
        try:
            def func2():
                '''
                1.解析主页面连接,获得组图资源连接
                2.无返回值,结果直接存在self.url2_list
                3.这里封装成函数,是因为数据请求是,I/O操作,
                    通过多线程可以提高效率
                '''
                while self.url1_list:
                    url = self.url1_list.pop()#为了避免重复,采用pop
                    size_new = len(self.url1_list)
                    resu = '数据已加载:%.2f%%' % (((size - size_new) / size) * 100)
                    print('\r%s' % resu, end='', flush=True)#时间较久,加进度条
                    html=self.GetHtml(url)#获取源码,解析,获取相关数据
                    re_url = '<ul class="detail-list">.+?</ul></div></div>'
                    ret = re.findall(re_url, html, re.S)
                    res = re.findall("https://.+?/article.+?.html", ret[0])
                    res = set(res)
                    for ele in res:#将获取到的数据写入到url2_list中
                        self.url2_list.append(ele)

            start_time = time.clock()
            print('数据资源加载开始')

            for i in range(6):
                #根据电脑CPU核数获得最优线程数,这里采用了核数*2+2
                t2 = threading.Thread(target=func2)
                t2.start()
            t2.join()
            print('数据资源加载完毕')
            end_time = time.clock()
            print('数据资源加载耗时:%.2f' % (end_time - start_time))
            #获取下加载时间
        except:
            t2 = threading.Thread(target=func2)
            t2.start()

    def GetHtml(self, url):
        '''
        获取源码的封装
        :param url: 传入url链接
        :return: 返回该连接对应源码
        '''
        try:#处理异常
            address = {'user-agent': 'Mozilla/5.0'}#虚拟请求地址,有的网站会检查是否浏览器浏览
            r = requests.get(url)
            r.encoding = r.apparent_encoding
            r.raise_for_status()
            html = r.text#获取到源码
            return html
        except:
            pass

    def Download(self,):
        '''
        下载逻辑代码存放
        :无返回值,直接存放对应位置
        '''
        print('下载图片中')
        try:
            def save():
                try:
                    while self.url2_list:
                        url=self.url2_list.pop()#依次取,避免重复
                        html = self.GetHtml(url)#获取源码
                        ret = re.findall('<h1>(?P<name>.+?)<span> (?P<num>.+?)</span></h1>', html, re.S)
                        res = re.findall('\d+', ret[0][1], re.S)
                        file_name=ret[0][0]#获取组图名
                        N=int(res[1])#获取组图总数量
                        save_path=self.address+'爬虫照片/'#设置储存位置,从传入的盘符
                        if os.path.isdir(save_path):
                            #判断是否有该路径,有的话继续,没有创建
                            pass
                        else:
                            os.mkdir(save_path)
                        file_path = os.path.join(save_path, file_name)
                        #拼接组图文件夹,存放组图图片
                        if os.path.isdir(file_path):
                            # 判断是否有该路径,有的话继续,没有创建
                            print('%s组图已存在'%file_path)
                            pass
                        else:
                            os.mkdir(file_path)
                        for i in range(2, N):
                            #拼接组图中每张图片链接
                            str1 = '%s%s.html' % ('-', str(i))
                            new_url = url.replace('.html', str1)
                            Picture_path=os.path.join(file_path, str(i)+'.gif')
                            #拼接文件储存位置
                            if os.path.isfile(Picture_path):
                                # 判断是否有该图片,有的话跳过,没有下载
                                print('%s图片已存在'% file_name+str(i)+'.gif')
                                continue
                            else:
                                new_html = self.GetHtml(new_url)#获取到图片链接
                                data_url = re.findall('https://img.+?gif', new_html, re.S)
                                data = requests.get(data_url[0])
                                print('正在下载%s' % file_name + str(i) + '.gif')
                                with open(Picture_path, 'wb') as f:#储存图片
                                    f.write(data.content)
                                    print('%s下载完成' % (file_name + str(i) + '.gif'))
                except:
                    t3 = threading.Thread(target=save, )
                    t3.start()
            for i in range(6):
                t3= threading.Thread(target=save,)
                t3.start()
            t3.join()
        except:
            pass
    def run(self):
        '''
        主程序
        '''
        self.Geturl_1()
        base_url1_size = len(self.url1_list)
        self.Geturl_2(base_url1_size)
        self.Download()
def show():
    print('''
        请输入对应序号,任意键默认为C盘
        1. C盘
        2. D盘
        3. E盘
        4. F盘
        5. G盘
        6. H盘
        ''')
    dic={'2':'D:/','3':'E:/','4':'F:/','5':'G:/','6':'H:/'}#输入的命令对应关系
    while 1:#选择好盘符后进行爬取
        add=input('请输入储存位置:')
        if dic[add] and os.path.isdir(dic[add]):
            addr=dic[add]
            return addr
        else:
            print('''
            磁盘不存在或者输入有误
            1. 重新输入
            2. 默认存在C盘
            3. 任意键退出程序
            ''')
            N=input('请输入对应序号:')
            if N=='1':
                continue
            elif N=='2':
                addr='C:/'
                return addr
            else:
                addr=None
                return addr
cond=show()
if cond==None:
    print('感谢使用')
else:
    baby = MyBaby(cond)
    baby.run()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值