Python 多线程爬虫

1. 并发,并行的理解

# 并发:同一时间段同时运行
# 并行:同一时刻同时运行
# 时间片轮转法:10个视屏不间断播放,是并发运行,但给人的错觉是并行
# 高IO密集(比如在一个刚运行的代码前就有设置的)  阻塞,cup算法密集

2. 用代码实现多线程爬虫

***用多线程爬虫,最重要的就是传参,获取数据,思路********
import threading,requests
# 导入多线程锁机制
from threading import Lock
# 导入线程队列
from queue import Queue
from lxml import etree
import pymongo
# 爬虫类,负责采集数据的
class CrawThread(threading.Thread):
    # 初始化init方法,接收参数
    def __init__(self,name,pageQueue,dataQueue):
        super().__init__()
        self.name = name
        self.pageQueue = pageQueue
        self.headers = {
            'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36'
        }
        self.dataQueue = dataQueue

    # 执行run方法,在def函数调用时执行
    def run(self):
        # 爬取的页数不确定,格式化输出
        base_url = 'https://www.xiaohua.com/duanzi?page=%s'
        while 1:
            try:
                print('开始url')
                # 传参时要抓取几页的数据已准备好直接get获取,block为False用try捕获异常抓取结束,就终止循环
                page = self.pageQueue.get(block=False)
                # 将页码拼接
                url = base_url % page
                res = requests.get(url=url,headers=self.headers)
                self.dataQueue.put(res.text)
                print('URL完成')
            except:
                break

# 数据解析类
class Parse(threading.Thread):
    def __init__(self,name,dataQueue,look):
        super().__init__()
        self.name = name
        self.dataQueue = dataQueue
        self.look = look

    def run(self):
        while 1:
            try:
                html = self.dataQueue.get(block=False)
                print('正在解析')
                # 把获取的HTML的文本放在下一个函数的里进行操作
                self.parserver(html)
                print('解析完毕')
            except:
                break
                
    def parserver(self,html):
        # 解析
        tree = etree.HTML(html)
        div_list = tree.xpath('//div[@class="one-cont"]')
        for div in div_list:
            item = {}
            author = div.xpath('./div/div/a/i/text()')
            item['author'] = author[0]
            # 上锁
            with self.look:
                self.save(item)

    def save(self,item):
        # 连接MongoDB数据库
        conn = pymongo.MongoClient('localhost',27017)
        db = conn.XIAOHUA
        table = db.xh
        table.insert_one(item)

def main():
    # 存放URl----实例化队列对象
    pageQueue = Queue()
    for j in range(1,11):
        # put将所需要的数据存入
        pageQueue.put(j)
    #存放脏数据
    dataQueue = Queue()
    crawlist = ['爬虫1号','爬虫2号','爬虫3号']
    # join等待进程以防有一个进程死掉
    for i in crawlist:
        c = CrawThread(i,pageQueue,dataQueue)
        c.start()
        c.join()
    # 实例化机制锁对象
    look = Lock()
    jiexi = ['解析1号','解析2号','解析3号',]
    for var2 in jiexi:
        cc = Parse(var2,dataQueue,look)
        cc.start()
        # 等待其他线程执行,以防提早结束其他线程死掉
        cc.join()


if __name__ == '__main__':
    main()

原文地址:https://www.cnblogs.com/xinzaiyuan/p/12382253.html