懒人XX网,有声小说类目数据采集,多线程速采案例,Python爬虫120例之23例

举报
梦想橡皮擦 发表于 2022/01/03 15:15:07 2022/01/03
【摘要】 多线程在 Python 爬虫学习过程中应用落地,提速,提速,再提速。 目标站点分析本次要抓取的目标为懒人畅听网,其中我随机选择了一个分类,有声小说频道,其余频道可使用雷同的办法抓取,增加遍历之后,可以对全站进行抓取。列表页分页规则如下本次依旧只对列表页数据进行提取,只增加多线程模块 threading 的应用,提高采集效率。http://www.lrts.me/book/category/1...

多线程在 Python 爬虫学习过程中应用落地,提速,提速,再提速。

目标站点分析

本次要抓取的目标为懒人畅听网,其中我随机选择了一个分类,有声小说频道,其余频道可使用雷同的办法抓取,增加遍历之后,可以对全站进行抓取。

列表页分页规则如下
本次依旧只对列表页数据进行提取,只增加多线程模块 threading 的应用,提高采集效率。

http://www.lrts.me/book/category/1/recommend/1/20
http://www.lrts.me/book/category/1/recommend/2/20

提取规则模板如下:

http://www.lrts.me/book/category/1/recommend/页码/20

全站页码数,可以直接人眼读取,如果增加动态获取,提取读取一下分页处数据即可。

提取最终的数据源如下图所示,包括书名,作者,主播三部分内容。

编码时间

本次案例中对于多线程部分,除共享全局变量外,增加信号量机制,即限制线程并发数量。

信号量机制的简单 Demo 如下所示:


import threading
import time


def run(n, semaphore):
    # 加锁
    semaphore.acquire()
    time.sleep(2)
    print(f'正在运行线程{n}')
    # 释放锁
    semaphore.release()


if __name__ == '__main__':
    num = 0
    # 最多允许 3 个线程同时运行
    semaphore = threading.BoundedSemaphore(3)
    for i in range(10):
        t = threading.Thread(target=run, args=(f'线程号:{i}', semaphore))
        t.start()
    while threading.active_count() != 1:
        pass
    else:
        print('所有线程运行完毕')

运行代码,会发现先运行 3 个线程,再运行 3 个线程,当然同时运行的线程之间是没有先后顺序的。

信号量,即使用 threading 模块的 BoundedSemaphore 类,该类可以设置允许一定数量的线程更改数据,即最多可同时运行几个线程。

代码完整案例如下所示

import threading
from threading import Lock,Thread
import random,requests
from lxml import etree

def get_headers():
    uas = [
        "Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)",
    ]
    ua = random.choice(uas)
    headers = {
        "user-agent": ua,
        "referer": "https://www.baidu.com/"
    }
    return headers


def run(url,semaphore):
    headers = get_headers()
    semaphore.acquire()   #加锁
    res = requests.get(url,headers=headers,timeout=5)
    if res:
        text = res.text
        element = etree.HTML(text)
        titles = element.xpath('//a[@class="book-item-name"]/text()')
        authors = element.xpath('//a[@class="author"]/text()')
        weakens = element.xpath('//a[@class="g-user-shutdown"]/text()')
        save(url,titles,authors,weakens)


    semaphore.release()    #释放

def save(url,titles,authors,weakens):
    data_list = zip(titles,authors,weakens)
    for item in data_list:
        with open("./data.csv","a+",encoding="utf-8") as f:
            f.write(f"{item[0]},{item[1]},{item[2]}\n")
    print(url,"该URL地址数据写入完毕")
if __name__== '__main__':
    lock = Lock()
    url_format = 'https://www.lrts.me/book/category/1/recommend/{}/20'
    # 拼接URL,全局共享变量
    urls = [url_format.format(i) for i in range(1, 1372)]
    l = []
    semaphore = threading.BoundedSemaphore(5)   # 最多允许5个线程同时运行
    for url in urls:
        t = threading.Thread(target=run,args=(url,semaphore))
        t.start()
    while threading.active_count() !=1:
        pass
    else:
        print('所有线程运行完毕')

代码中 threading.active_count() 部分,用于检测是否存在活跃线程,如无,程序结束。

运行代码,得到如下结果,至此第 23 例已经学习完毕。

【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。