7-多线程爬虫糗事百科

7-多线程爬虫糗事百科

简介

多线程 thread 在 Python 里面被称作鸡肋的存在!不建议使用,多是使用多进程,虽然不建议使用,还是做个笔记吧。

实现线程的两种方式

直接利用函数创建多线程
import _thread
import time


# 为线程定义函数
def print_time(thread_name, delay):
    count = 0
    while count < 5:
        time.sleep(delay)
        count += 1
        print("%s : %s" % (thread_name, time.ctime(time.time())))


# 创建两个线程
try:
    _thread.start_new_thread(print_time, ("thread-1", 2))
    _thread.start_new_thread(print_time, ("thread-2", 3))
except:
    print("Error: unalbe to start thread")


# 这是让主线程一直在等待
# 如果去掉,线程中数据不会打印
while 1:
    pass
利用threading创建多线程

使用Threading模块创建线程,直接从threading.Thread继承,然后重写init方法和run方法:

利用threading多线程糗事百科

from threading import Thread
from queue import Queue
from fake_useragent import UserAgent
import requests
from lxml import etree
import time


# 爬虫类
class CrawlInfo(Thread):
    def __init__(self, url_queue, html_queue):
        Thread.__init__(self)
        self.url_queue = url_queue
        self.html_queue = html_queue

    def run(self):
        headers = {
            'User-Agent': UserAgent().random
        }
        while not self.url_queue.empty():
            response = requests.get(self.url_queue.get(), headers=headers)
            if response.status_code == 200:
                self.html_queue.put(response.text)


class ParseInfo(Thread):
    def __init__(self, html_queue):
        Thread.__init__(self)
        self.html_queue = html_queue

    def run(self) -> None:
        while not self.html_queue.empty():
            e = etree.HTML(self.html_queue.get())
            contents = e.xpath('//div[@class="content"]/span[1]')
            with open("duanzi.txt", "a", encoding="utf-8") as f:
                for content in contents:
                    info = content.xpath('string(.)')
                    f.write(info + "\n")


if __name__ == '__main__':
    time.time()
    # 存储url的容器
    # FIFO(first-in-first-out先入先出)队列
    url_queue = Queue()
    # 存储内容容器
    html_queue = Queue()
    base_url = 'https://www.qiushibaike.com/text/page/{}/'
    for i in range(1, 13):
        new_url = base_url.format(i)
        url_queue.put(new_url)

    # 创建一个爬虫
    crawl_list = []
    for i in range(0, 3):
        crawl1 = CrawlInfo(url_queue, html_queue)
        crawl_list.append(crawl1)
        crawl1.start()

    for crawl_detail in crawl_list:
        crawl_detail.join()

    # 处理数据
    crawl2 = ParseInfo(html_queue)
    crawl2.start()

线程同步

如果多个线程共同对某个数据修改,则可能出现不可预料的结果,为了保证数据的正确性,需要对多个线程进行同步。

使用Thread对象的Lock和Rlock可以实现简单的线程同步,这两个对象都有acquire方法和release方法,对于那些需要每次只允许一个线程操作的数据,可以将其操作放到acquire和release方法之间。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值