Python自学笔记——多线程微信文章爬取

# -*- coding: utf-8 -*-

"""

Created on Tue Dec 26 10:34:09 2017

@author: Andrew

"""

#线程1专门获取对应网址并处理为真是网址,然后将网址写入队列urlqueue中,该队列专门用来存放具体文章的网址

#线程2与线程1并行,从线程1提供的网址中依次爬取对应文章信息并处理,处理后将我们需要的结果写入对应的本地文件中

#线程3主要用于判断程序是否完成。因为在此如果没有一个总体控制的线程,即使线程1、2执行完,也不会退出程序

#在正规的项目设计时,尽量并行执行的线程执行的时间相近

#建立合理的延时机制,如:发生异常或让执行较快的线程进行延时。

#建立合理的异常处理机制

导入所需的模块


import threading

import queue

import re

import urllib.request

import time

import urllib.error

#创建一个网址队列


urlqueue=queue.Queue()

#模拟成浏览器


headers=("User-Agent","Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36")

opener=urllib.request.build_opener()

opener.add_handler=[headers]

#将opener安装为全局

urllib.request.install_opener(opener)

#建立空url列表


listurl=[]

#读取网页源代码


def readdata(url):

    try:

        data=urllib.request.urlopen(url).read().decode('utf-8')

        return data

    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)

#线程1,专门获取对应网址并处理为真实网址


class geturl(threading.Thread):

    def __init__(self,key,pagestart,pageend,urlqueue):

        threading.Thread.__init__(self)

        self.pagestart=pagestart

        self.pageend=pageend

        self.urlqueue=urlqueue

    def run(self):

        page=self.pagestart

        #编译关键词key

        keycode=urllib.request.quote(key)

        for page in range(self.pagestart,self.pageend+1):

            url="http://weixin.sogou.com/weixin?query="+keycode+"&_sug_type_=&sut=31049&lkt=0%2C0%2C0&s_from=input&_sug_=y&type=2&sst0=1514192636409&page="+str(page)+"&ie=utf8&w=01019900&dr=1"

            data1=readdata(url)

            #列表页url正则

            listurlpat='

.*?(http://.*?)"'

            listurl.append(re.compile(listurlpat,re.S).findall(data1))

            #便于调试

        print("获取到"+str(len(listurl))+"页")

        for i in range(0,len(listurl)):

            #等一等线程2,合理分配资源

            time.sleep(7)

            for j in range(0,len(listurl[i])):

                try:

                    url=listurl[i][j]

                    #处理成真实url,采集网址比真实网址多了一串"amp;"

                    url=url.replace("amp;","")

                    print("第"+str(i)+","str(j)+"次入队")

                    self.urlqueue.put(url)

                    self.urlqueue.task_done()                    

                except urllib.error.URLError as e:

                    if hasattr(e,"code"):

                        print(e.code)

                    if hasattr(e,"reason"):

                        print(e.reason)

                    #若为URLError异常,延时10秒执行

                    time.sleep(10)

                except Exception as e:

                    print("exception:"+str(e))

                    #若为Exception异常,延时1秒执行

                    time.sleep(1)

 

#线程2,与线程1并行,从线程1提供的网址urlqueue中依次爬去对应文章信息并处理


class getcontent(threading.Thread):

    def __init__(self,urlqueue):

        threading.Thread.__init__(self)

        self.urlqueue=urlqueue

    def run(self):

        html='''

           

           

           

            微信文章页面

           

            '''

        fh=open("C:/Python35/3.html","wb")

        fh.write(html.encode("utf-8"))

        fh.close()

        fh=open("C:/Python35/3.html","ab")

        i=1

        while(True):

            try:

                url=self.urlqueue.get()

                data=readdata(url)

                #文章标题正则表达式

                titlepat="(.*?)"

                #文章内容正则表达式

                contentpat='id="js_content">(.*?)id="js_sg_bar"'

                #通过对应正则表达式找到标题并赋给列表title

                title=re.compile(titlepat).findall(data)

                #通过对应正则表达式找到内容并赋给content

                content=re.compile(contentpat,re.S).findall(data)

                #初始化标题与内容

                thistitle="此次没有获取到"

                thiscontent="此次没有获取到"

                #如果标题列表不为空,说明找到了标题,去列表第0个元素,即次标题赋给thistitle

                if(title!=[]):

                    thistitle=title[0]

                if(thiscontent!=[]):

                    thiscontent=content[0]

                #将标题与内容汇总赋给变量dataall

                dataall="

标题为:"+thistitle+"

内容为:"+thiscontent+"


"

                #将该篇文章的标题与内容的总信息写入对应文件

                fh.write(dataall.encode("utf-8"))

                print("第"+str(i)+"个网页")#便于调试

                i+=1

            except urllib.error.URLError as e:

                    if hasattr(e,"code"):

                        print(e.code)

                    if hasattr(e,"reason"):

                        print(e.reason)

                    #若为URLError异常,延时10秒执行

                    time.sleep(10)

            except Exception as e:

                    print("exception:"+str(e))

                    #若为Exception异常,延时1秒执行

                    time.sleep(1)

        fh.close()

        html4='''

       

        '''

        fh=open("C:/Python35/3.html","ab")

        fh.write(html4.encode("utf-8"))

        fh.close()

#并行控制程序,若60秒未响应,并且url的队列已空,则判断为执行成功


class contrl(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()

#运行


key="考研数学泄题"

pagestart=1#起始页

pageend=2#爬取到哪页

#创建线程1对象,随后启动线程1

t1=geturl(key,pagestart,pageend,urlqueue)

t1.start()

#创建线程2对象,随后启动线程2

t2=getcontent(urlqueue)

t2.start()

#创建线程3对象,随后启动线程3

t3=contrl(urlqueue)

t3.start()

你可能感兴趣的:(Python自学笔记——多线程微信文章爬取)