使用多线程爬虫爬取泛见网数据--www.fanjian.com

使用多线程爬虫爬取泛见网数据–www.fanjian.com

分析

两类线程
初定下载线程(3)、解析线程数量(3)
内容队列(线程之间交互):下载线程往队列中put数据,解析线程从线程中get数据
数据
url队列:下载线程从url队列get数据
写数据:上锁

网页分析

目标url有懒加载前端技术,最终需要写入的格式采取json格式,将“标题”和imageurl作为词典转换为
json格式并写入(如果想要下载图,可以在本文代码上进行更改下载),采用到的包:

import threading
import time
from queue import Queue
import requests
from lxml import etree
import json

要注意的点

锁的使用:写文件的时候给写操作加线程锁,但是一定要记住在写操作完成之后要有解锁操作;

# 写到文件中,线程锁锁住,县城完成写操作之后解锁,不然程序将卡住
self.lock.acquire()
self.fp.write(json.dumps(items, ensure_ascii=False) + "\n")
self.lock.release()

json文件写操作

fp = open('jian.json', 'a', encoding='utf8')

完整代码

# coding=utf-8
import threading
import time
from queue import Queue
import requests
from lxml import etree
import json

# 用来存放采集线程
g_crawl_list = []
# 用来存放解析线程
g_parse_list = []


# 采集线程类
class CrawlThread(threading.Thread):
    def __init__(self, name, page_queue, data_queue):
        super(CrawlThread, self).__init__()
        self.name = name
        self.page_queue = page_queue
        self.data_queue = data_queue
        self.url = 'http://www.fanjian.net/jiantu-{}'
        self.headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) '
                          'AppleWebKit/537.36 (KHTML, like Gecko)'
                          ' Chrome/70.0.3538.67 Safari/537.36',
        }

    def run(self):
        print('%s---线程启动' % self.name)
        while 1:
            # 判断何时退出
            if self.page_queue.empty():
                break
            # 从队列中取出页码
            page = self.page_queue.get()
            # 拼接url,发送请求
            url = self.url.format(page)
            r = requests.get(url=url, headers=self.headers)
            # 将相应内容存放到data_queue中
            self.data_queue.put(r.text)
        print('%s---线程退出' % self.name)


# 解析线程类
class ParserThread(threading.Thread):
    def __init__(self, name, data_queue, lock, fp):
        super(ParserThread, self).__init__()
        self.name = name
        self.data_queue = data_queue
        self.lock = lock
        self.fp = fp

    def run(self):
        print('%s---线程启动' % self.name)
        while 1:
            # 判断何时退出
            # 从data_queue中取出一页数据
            try:
                data = self.data_queue.get(True, 10)
                # print(111111)
            except Exception as e:
                break
            # 解析内容即可
            self.parse_content(data)
        print('%s---线程退出' % self.name)

    # 解析内容
    def parse_content(self, data):
        tree = etree.HTML(data)

        li_list = tree.xpath('//ul[@class="cont-list"]/li')

        # print(li_list)
        items = []
        for oli in li_list:
            # 获取图片标题
            title = oli.xpath('./h2/a/text()')[0]
            # 获取图片url
            image_url = oli.xpath('./div/p/img/@data-src')
            item = {
                '标题': title,
                '连接': image_url
            }
            items.append(item)
        # 写到文件中,线程锁锁住,县城完成写操作之后解锁,不然程序将卡住
        self.lock.acquire()
        self.fp.write(json.dumps(items, ensure_ascii=False) + "\n")
        self.lock.release()

# 创建队列
def create_Queue():
    # 创建一个页码队列
    page_queue = Queue()
    for page in range(1, 1874):
        page_queue.put(page)
    # 创建内容队列
    data_queue = Queue()
    return page_queue, data_queue


# 创建采集线程
def create_crawl_thread(page_queue, data_queue):
    crwal_name = ['采集线程1号', '采集线程2号', '采集线程3号', '采集线程4号', '采集线程5号', '采集线程6号']
    # 创建一个采集线程
    for name in crwal_name:
        tcrawl = CrawlThread(name=name, page_queue=page_queue, data_queue=data_queue)
        g_crawl_list.append(tcrawl)


# 创建解析线程
def create_parse_thread(data_queue, fp, lock):
    parse_name = ['解析线程1号', '解析线程2号', '解析线程3号']
    for name in parse_name:
        # 创建一个解析线程
        t_parse = ParserThread(name=name, data_queue=data_queue, fp=fp, lock=lock)
        g_parse_list.append(t_parse)


def main():
    # 创建队列函数
    page_queue, data_queue = create_Queue()
    # 打开文件
    fp = open('jian.json', 'a', encoding='utf8')
    # 创建锁
    lock = threading.Lock()
    # 创建采集线程
    create_crawl_thread(page_queue=page_queue, data_queue=data_queue)
    time.sleep(10)
    # 创建解析线程
    create_parse_thread(data_queue=data_queue, fp=fp, lock=lock)
    # 启动所有采集线程
    for tcrawl in g_crawl_list:
        tcrawl.start()
    # 启动所有解析线程
    for tparse in g_parse_list:
        tparse.start()
    # 主线程等待子线程结束
    for tcrawl in g_crawl_list:
        tcrawl.join()
    for tparse in g_parse_list:
        tparse.join()
    # 关闭json文件
    fp.close()
    print("主线程,子线程全部结束!")


if __name__ == '__main__':
    main()

猜你喜欢

转载自blog.csdn.net/Uridis/article/details/88181243
今日推荐