爬虫入门实践之多线程爬虫

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/carson0408/article/details/89930408

        有的爬重只需要单线程就可以完成,而有的爬虫可以拆分成多线程实现,能够提高爬虫效率。比如爬虫入门实践之爬取虎扑论坛帖子一文中,介绍使用的是用单线程实现的,首先在首页找出所有的url,然后遍历url,找出相关信息。其实,仔细分析,可以发现,该例子可以使用多线程来实现,比如一个线程用于获取url,一个线程根据已有的url来爬取相关信息,这样一来,总的等待时间更短了。因此,本文针对改写该例子进行讲解。

1.python中多线程基础

        所谓的多线程爬虫,指的是爬虫中的某部分程序可以并行执行,即在多条线上执行。python3中用于多线程的库是threading,我们可以通过导入threading模块使用多线程功能,定义一个类并继承threading.Thread类,将该类定义为一个线程。在该类中,可以使用__init__(self)方法对线程进行初始化,在run(self)方法中编写该线程需要执行的程序,然后构造线程,并调用线程对象的start()方法启动对应的线程。

例子:

import threading

class thread(threading.Thread):#继承threading.Thread
    def __init__(self,x):
        #初始化该线程
        threading.Thread.__init__(self)
        self.x=x
    def run(self):
        #编写该线程需要执行的程序
        print(1)
x=""
t1=thread(x)
t1.start()

        本文后续讲到多线程会使用到一个数据结构--队列,队列具有先进先出,是有序的,因此,在这里可以起到较好的作用,将遍历得到的线程放进队列,另一线程只需要从队列中取出url,并进行爬取信息即可。两者可以并行执行。

Python3中,导入queue模块可以使用队列,q=queue.Queue()声明队列,q.put(元素)则表示入队,q.get()方法则表示出队,q.empty()可以判断队列是否为空。

2.爬虫分析

        本文是基于爬虫入门实践之爬取虎扑论坛帖子一文的例子的,并使用了三个线程。

1.线程1用于爬取首页的各个帖子的url以及帖子的来源,并将url和来源分别放入urlqueue和sourcequeue两个队列

2.线程2则是将urlqueue中的url逐个出队,并根据出队的url,找到对应帖子的作者,标题以及发表时间,然后结合帖子相应的url和source,将这些信息归类,追加写入到本地的一个html文件中,

3.控制线程则用于控制线程的开始和结束,这里的结束标志是urlqueue为空。

        以上三个线程可以使爬取首页帖子的url和获取url的相关信息可以并行执行,而不是等到所有url都获取之后才逐个去爬取相关信息,这样一定程度上提升了爬虫效率。在编写线程程序过程中,要注意捕获异常,提升程序的健壮性。

代码如下:

import urllib.request
import time
import urllib.error
import threading
import queue
import re
urlqueue = queue.Queue()
sourcequeue=queue.Queue()
def getdata(url):
    req = urllib.request.Request(url)
    req.add_header('User-Agent', 'Mozilla/5.0(Windows NT 10.0;Win64;x64;rv:66.0)Gecko/20100101 Firefox/66.0')
    data = urllib.request.urlopen(req).read().decode('utf-8')
    return data
#获取当前页面符合要求的url和帖子来源
class geturlandsource(threading.Thread):
    def __init__(self,url,urlqueue,sourcequeue):
        threading.Thread.__init__(self)
        self.url=url
        self.urlqueue=urlqueue
        self.sourcequeue=sourcequeue
    def run(self):
        data=getdata(self.url)
        urlpattern='<a href="/(.*?)" target="_blank" title=".*?">'
        sourcepattern='<a href="/.+?" target="_blank">(.*?)</a>'
        urlList = re.compile(urlpattern).findall(data)
        length = len(urlList)
        sourceList=re.compile(sourcepattern).findall(data)
        print(length)
        for i in range(length):
            try:
                url = "https://bbs.hupu.com/" + urlList[i]
                self.urlqueue.put(url)
                self.sourcequeue.put(sourceList[i])
                self.urlqueue.task_done()
                self.sourcequeue.task_done()
            except urllib.error.URLError as e:
                if hasattr(e, "code"):
                    print(e.code)
                if hasattr(e, "reason"):
                    print(e.reason)
                time.sleep(10)
            except Exception as e:
                print("exception:" + str(e))
                time.sleep(1)

#逐个根据urlqueue中的url获取帖子的标题、时间和作者
class getcontent(threading.Thread):
    def __init__(self,urlqueue,sourcequeue):
        threading.Thread.__init__(self)
        self.urlqueue=urlqueue
        self.sourcequeue=sourcequeue

    def run(self):
        #定义html
        html1 = '''<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
                "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
                <html xmlns="http://www.w3.org/1999/xhtml">
                <head>
                <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
            <title>虎扑专栏</title>
                </head>
                <body><p align="center" style="font-size:20px">虎扑帖子汇总</p>'''
        fh = open("hupu_thread.html", "wb")
        fh.write(html1.encode('utf-8'))
        fh.close()
        #fh = open("C:/Users/carson0408/Desktop/webcrawler/hupu_thread.html", "ab")
        i = 1
        while(True):
            try:

                url = self.urlqueue.get()
                source=self.sourcequeue.get()
                data=getdata(url)
                titlepattern='data-title="(.*?)"'
                titlelist=re.compile(titlepattern).findall(data)
                authorpattern='<a class="u" target="_blank" href=".*?">(.*?)</a>'
                authorlist=re.compile(authorpattern).findall(data)
                timepattern='<span class="stime">(.*?)</span>'
                timelist=re.compile(timepattern).findall(data)
                title=""
                author=""
                time=""
                if(titlelist!=[]):
                    title=titlelist[0]
                if(authorlist!=[]):
                    author=authorlist[0]
                if(timelist!=[]):
                    time=timelist[0]

                content='<p align="center">标题:<font color="red">'+title+" "+'</font></p><p align="center">作者:'+author+" "+'</p><p align="center" >URL:<font color="blue">'+url+" "+'</font></p><p align="center">发布时间:'+time+" "+'</p><p align="center">帖子来源:'+source+"</p><br>"
                print(content)
                fh = open("hupu_thread.html", "ab")
                fh.write(content.encode('utf-8'))
                fh.close()
            except urllib.error.URLError as e:
                if hasattr(e,"code"):
                    print(e.code)
                if hasattr(e,"reason"):
                    print(e.reason)
                time.sleep(10)
            except Exception as e:
                print("exception:"+str(e))
                time.sleep(1)
        fh.close()
        html2 = '''</body>
                    </html>
                    '''
        fh = open("hupu_thread.html", "ab")
        fh.write(html2.encode('utf-8'))
        fh.close()
#并行控制程序
class controll(threading.Thread):
    def __init__(self,urlqueue):
        threading.Thread.__init__(self)
        self.urlqueue=urlqueue
    def run(self):
        while(True):
            print("程序执行中")
            time.sleep(60)
            if(self.urlqueue.empty()):
                print("程序执行完毕")
                exit()

url1="https://bbs.hupu.com/all-nba"
t1=geturlandsource(url1,urlqueue,sourcequeue)
t1.start()

t2=getcontent(urlqueue,sourcequeue)
t2.start()


t3=controll(urlqueue)
t3.start()

  运行程序,运行结果:

程序执行中
30
<p align="center">标题:<font color="red">NBA赛场上有哪些令人窒息的尴尬时刻? </font></p><p align="center">作者:leo1824 </p><p align="center" >URL:<font color="blue">https://bbs.hupu.com/27275178.html </font></p><p align="center">发布时间:2019-05-07 16:43 </p><p align="center">帖子来源:湿乎乎的话题</p><br>
<p align="center">标题:<font color="red">詹姆斯是不是有三年,把不是总决赛级别实力的队伍强行拖进了总决赛? </font></p><p align="center">作者:站在你背后 </p><p align="center" >URL:<font color="blue">https://bbs.hupu.com/27275324.html </font></p><p align="center">发布时间:2019-05-07 16:54 </p><p align="center">帖子来源:湿乎乎的话题</p><br>
<p align="center">标题:<font color="red">刚想起来,火勇大战的观看人数太残暴了 </font></p><p align="center">作者:虎扑街头顶点击 </p><p align="center" >URL:<font color="blue">https://bbs.hupu.com/27276935.html </font></p><p align="center">发布时间:2019-05-07 18:57 </p><p align="center">帖子来源:湿乎乎的话题</p><br>
<p align="center">标题:<font color="red">格林:我说过哈登投三分对我犯规,你们都说我说谎!zt </font></p><p align="center">作者:灵儿丶莫失莫忘 </p><p align="center" >URL:<font color="blue">https://bbs.hupu.com/27276464.html </font></p><p align="center">发布时间:2019-05-07 18:27 </p><p align="center">帖子来源:湿乎乎的话题</p><br>
<p align="center">标题:<font color="red">格林:“G5 将加强身体对抗,我们知道问题的答案 </font></p><p align="center">作者:NLF724 </p><p align="center" >URL:<font color="blue">https://bbs.hupu.com/27272736.html </font></p><p align="center">发布时间:2019-05-07 14:06 </p><p align="center">帖子来源:湿乎乎的话题</p><br>
<p align="center">标题:<font color="red">这个球怎么看,克莱为啥不把球传给杜兰特 </font></p><p align="center">作者:虎扑用户644001 </p><p align="center" >URL:<font color="blue">https://bbs.hupu.com/27275703.html </font></p><p align="center">发布时间:2019-05-07 17:24 </p><p align="center">帖子来源:湿乎乎的话题</p><br>
<p align="center">标题:<font color="red">ESPN专家:克莱正在伤害球队 </font></p><p align="center">作者:不吹不黑路人王 </p><p align="center" >URL:<font color="blue">https://bbs.hupu.com/27276359.html </font></p><p align="center">发布时间:2019-05-07 18:18 </p><p align="center">帖子来源:湿乎乎的话题</p><br>
<p align="center">标题:<font color="red">[话题团]篮板球成风向标?勇火系列赛至今赢下篮板的一方即赢得比赛 </font></p><p align="center">作者:孟克_巴特尔 </p><p align="center" >URL:<font color="blue">https://bbs.hupu.com/27273875.html </font></p><p align="center">发布时间:2019-05-07 15:11 </p><p align="center">帖子来源:湿乎乎的话题</p><br>
<p align="center">标题:<font color="red">火勇大战,双方都不敢多用一个人的原因是什么? </font></p><p align="center">作者:休斯顿丶Rocket </p><p align="center" >URL:<font color="blue">https://bbs.hupu.com/27274200.html </font></p><p align="center">发布时间:2019-05-07 15:35 </p><p align="center">帖子来源:湿乎乎的话题</p><br>
<p align="center">标题:<font color="red">[虎扑评选]字母哥39+16,哈登38+10,今日最佳数据你选谁? </font></p><p align="center">作者:虎扑每日最佳数据评选 </p><p align="center" >URL:<font color="blue">https://bbs.hupu.com/27269726.html </font></p><p align="center">发布时间:2019-05-07 12:30 </p><p align="center">帖子来源:湿乎乎的话题</p><br>
<p align="center">标题:<font color="red">ZT:烤肉姐:输掉G4 杜兰特气冲冲离开球场 勇士整个管理层在开会 </font></p><p align="center">作者:灵儿丶莫失莫忘 </p><p align="center" >URL:<font color="blue">https://bbs.hupu.com/27276644.html </font></p><p align="center">发布时间:2019-05-07 18:38 </p><p align="center">帖子来源:湿乎乎的话题</p><br>
<p align="center">标题:<font color="red">[话题团]哈登重拾必杀技止血中投,你还知道哪些杀死比赛的中投 </font></p><p align="center">作者:哈灯的登 </p><p align="center" >URL:<font color="blue">https://bbs.hupu.com/27274404.html </font></p><p align="center">发布时间:2019-05-07 15:49 </p><p align="center">帖子来源:湿乎乎的话题</p><br>
<p align="center">标题:<font color="red">欧文在16年总决赛打得多好啊!现在他到底怎么了? </font></p><p align="center">作者:miqiaoedr </p><p align="center" >URL:<font color="blue">https://bbs.hupu.com/27275535.html </font></p><p align="center">发布时间:2019-05-07 17:11 </p><p align="center">帖子来源:湿乎乎的话题</p><br>
<p align="center">标题:<font color="red">不懂就问,欧文不是杜库登字卡这种咖位,为什么开会程度却比他们更激烈? </font></p><p align="center">作者:无处寄托的心 </p><p align="center" >URL:<font color="blue">https://bbs.hupu.com/27278067.html </font></p><p align="center">发布时间:2019-05-07 20:14 </p><p align="center">帖子来源:湿乎乎的话题</p><br>
<p align="center">标题:<font color="red">[话题团]库里半决赛单防的回合,火箭球员合计41投16中,并有10次失误 </font></p><p align="center">作者:孟克_巴特尔 </p><p align="center" >URL:<font color="blue">https://bbs.hupu.com/27272529.html </font></p><p align="center">发布时间:2019-05-07 13:56 </p><p align="center">帖子来源:湿乎乎的话题</p><br>
<p align="center">标题:<font color="red">刚刚看到这图,是真的吗?哪场比赛啊 </font></p><p align="center">作者:虎扑用户264049 </p><p align="center" >URL:<font color="blue">https://bbs.hupu.com/27276584.html </font></p><p align="center">发布时间:2019-05-07 18:35 </p><p align="center">帖子来源:湖人专区</p><br>
<p align="center">标题:<font color="red">别样的老李 </font></p><p align="center">作者:虎扑用户630413 </p><p align="center" >URL:<font color="blue">https://bbs.hupu.com/27277081.html </font></p><p align="center">发布时间:2019-05-07 19:08 </p><p align="center">帖子来源:火箭专区</p><br>
<p align="center">标题:<font color="red">马健:火勇大战才刚刚开始,保罗会是G5的关键 </font></p><p align="center">作者:我就是你马大爷 </p><p align="center" >URL:<font color="blue">https://bbs.hupu.com/27276394.html </font></p><p align="center">发布时间:2019-05-07 18:21 </p><p align="center">帖子来源:火箭专区</p><br>
<p align="center">标题:<font color="red">原来杜兰特在场边交流的观众是她 </font></p><p align="center">作者:虎扑用户791927 </p><p align="center" >URL:<font color="blue">https://bbs.hupu.com/27276538.html </font></p><p align="center">发布时间:2019-05-07 18:32 </p><p align="center">帖子来源:火箭专区</p><br>
<p align="center">标题:<font color="red">别再争了,这才是勇士真正的问题 </font></p><p align="center">作者:你要skr我死磕 </p><p align="center" >URL:<font color="blue">https://bbs.hupu.com/27276650.html </font></p><p align="center">发布时间:2019-05-07 18:39 </p><p align="center">帖子来源:勇士专区</p><br>
<p align="center">标题:<font color="red">ZT:烤肉姐:输掉G4 杜兰特气冲冲离开球场 勇士整个管理层在开会 </font></p><p align="center">作者:火箭VIP </p><p align="center" >URL:<font color="blue">https://bbs.hupu.com/27277075.html </font></p><p align="center">发布时间:2019-05-07 19:07 </p><p align="center">帖子来源:火箭专区</p><br>
<p align="center">标题:<font color="red">费尔蒂塔赛后激动相拥三巨头 </font></p><p align="center">作者:a5565579 </p><p align="center" >URL:<font color="blue">https://bbs.hupu.com/27275317.html </font></p><p align="center">发布时间:2019-05-07 16:54 </p><p align="center">帖子来源:火箭专区</p><br>
<p align="center">标题:<font color="red">飞行20个小时就只为了亲眼见证G3,所有的辛苦都值得! </font></p><p align="center">作者:虎扑用户818374 </p><p align="center" >URL:<font color="blue">https://bbs.hupu.com/27275733.html </font></p><p align="center">发布时间:2019-05-07 17:26 </p><p align="center">帖子来源:火箭专区</p><br>
<p align="center">标题:<font color="red">ZT  关于这个帖子,科比会拿枪顶着我的脑门让我删掉[拜拜] ​ </font></p><p align="center">作者:虎扑用户989576 </p><p align="center" >URL:<font color="blue">https://bbs.hupu.com/27277867.html </font></p><p align="center">发布时间:2019-05-07 20:02 </p><p align="center">帖子来源:湖人专区</p><br>
<p align="center">标题:<font color="red">哈登第四节3:22这个中投什么水平? </font></p><p align="center">作者:虎扑用户717546 </p><p align="center" >URL:<font color="blue">https://bbs.hupu.com/27272571.html </font></p><p align="center">发布时间:2019-05-07 13:58 </p><p align="center">帖子来源:火箭专区</p><br>
<p align="center">标题:<font color="red">林有希望出厂天王山吗 </font></p><p align="center">作者:虎扑用户583659 </p><p align="center" >URL:<font color="blue">https://bbs.hupu.com/27273205.html </font></p><p align="center">发布时间:2019-05-07 14:28 </p><p align="center">帖子来源:林书豪专区</p><br>
<p align="center">标题:<font color="red">有哪些球员大家觉得是下赛季必涨的? </font></p><p align="center">作者:虎扑用户071625 </p><p align="center" >URL:<font color="blue">https://bbs.hupu.com/27276613.html </font></p><p align="center">发布时间:2019-05-07 18:37 </p><p align="center">帖子来源:NBA2KOL2</p><br>
<p align="center">标题:<font color="red">常规赛末2k球员数据更新!部分球员投射数据变化! </font></p><p align="center">作者:虎扑用户314880 </p><p align="center" >URL:<font color="blue">https://bbs.hupu.com/27273949.html </font></p><p align="center">发布时间:2019-05-07 15:16 </p><p align="center">帖子来源:NBA2KOL2</p><br>
<p align="center">标题:<font color="red">现在球哥鲍尔,都没人出售了吗? </font></p><p align="center">作者:虎扑用户019900 </p><p align="center" >URL:<font color="blue">https://bbs.hupu.com/27269990.html </font></p><p align="center">发布时间:2019-05-07 12:36 </p><p align="center">帖子来源:NBA2KOL2</p><br>
<p align="center">标题:<font color="red">找个锋线打pg </font></p><p align="center">作者:虎扑用户051324 </p><p align="center" >URL:<font color="blue">https://bbs.hupu.com/27269853.html </font></p><p align="center">发布时间:2019-05-07 12:32 </p><p align="center">帖子来源:NBA2KOL2</p><br>

        打开本地保存的网页,部分截图如下:

        以上是多线程爬虫的具体分析,其实只需要将单线程爬虫部分可以拆分的步骤进行拆分,实现并行执行即可。 

猜你喜欢

转载自blog.csdn.net/carson0408/article/details/89930408