python多线程爬虫数据顺序_多线程爬取小说时如何保证章节的顺序
前言
爬取小说时,以每一个章节为一个线程进行爬取,如果不加以控制的话,保存的时候各个章节之间的顺序会乱掉。
当然,这里说的是一本小说保存为单个txt文件,如果以每个章节为一个txt文件,自然不会存在这种情况。
不仅仅是小说,一些其他的数据在多线程爬取时也有类似情况,比如:
漫画:漫画其实是由大量图片组成,一般一本漫画会保存为一个pdf文件,在此过程要保证图片的顺序。
视频:现在网络上的视频大部分是由多个ts文件拼合,最后保存为一个mp4文件,要保证ts文件的顺序。
它们都有一个共同的特点,那就是:爬取目标时有多个链接,但保存后却只有一个文件,且无法在保存完毕后进行二次排序。
单线程时,这一类文件的爬取不会出现任何问题;
多线程时,因为爬取顺序的不确定性,导致保存的顺序紊乱。
解决方案
问题的根本原因在于:因为爬取和保存的一致性,混乱的爬取顺序使得保存顺序也变得混乱。
解决方案:将爬取过程和保存过程分离,多线程爬取数据,但按顺序保存数据。
比如一本小说,在爬取章节的过程中可以使用多线程,但不要在爬取之后立即保存,等待时机,精准写入。
那这个时机是什么呢?
可以在爬取章节的过程中,给每个章节一个带序号的标记,这个序号即小说章节的序号;保存时,从序号0开始保存,记录这一个序号,再检测当前爬取的章节中有没有比记录的序号刚好大于1的(大于1相当于下一个章节),有就写入,没有就等待。
具体过程:
爬取目录页,抽取出所有的章节链接。
将所有待爬取的链接扔到一个队列里面去,同时给每个链接一个标记。
开5个线程,不断地从队列里面拿链接进行爬取。
单个章节爬取之后,让爬取这个链接的线程阻塞。
申明一个成员变量,表示保存的章节序号,从-1开始
当前线程的链接标记是否刚好比章节序号大于1,是就保存,不是就继续阻塞
因为是从队列中取数据,就能够保证这5个章节是还没有被爬取的前5个章节
具体实现
爬虫代码用的python实现,自定义的线程类,这里以http://www.booktxt.net/8_8455/爬取为例。
代码如下:
importrequestsfrom lxml importetreefrom threading importThreadfrom queue importQueueclassMyThread(Thread):def __init__(self, q):
Thread.__init__(self)
self.q=qdefrun(self):globalindexwhile notself.q.empty():
data=self.q.get()
url= root + ''.join(data[1])
response= requests.get(url, headers=headers)
page=etree.HTML(response.content)
chapter= page.xpath("//h1/text()")
chapter= ''.join(chapter)print("爬取 -> %s" %chapter,index)
content= page.xpath("//div[@id='content']/text()")
content= '\n'.join(content)
content= content.replace("\xa0\xa0\xa0\xa0", "\t")#如果当前标记比保存的小说章节序号大于1,阻塞
while data[0] > index + 1:pass
#刚好大于1时,通过,保存章节
if data[0] == index + 1:print("保存 -> %s" %chapter,index)
f.write('\n' + chapter + '\n')
f.write(content)
index+= 1
if __name__ == '__main__':
root= "http://www.booktxt.net/8_8455/"headers={'user-agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36'}
index= -1 #章节标记,表示保存的章数
response= requests.get(root, headers=headers)
page=etree.HTML(response.content)
title= ''.join(page.xpath("//h1/text()")) #小说名
print(title)
with open("%s.txt" % title, 'w', encoding='utf8') as f:
f.write(title)#先写入小说名
hrefs = page.xpath("//div[@id='list']/dl/dt[2]/following-sibling::dd/a/@href")
q=Queue()for i,href inenumerate(hrefs):
q.put((i,href))
ts=[]for i in range(5):
t=MyThread(q)
t.start()
ts.append(t)for t ints:
t.join()
代码整体上并不复杂,用的也是requests+lxml的经典组合,主要是队列数据写入和线程阻塞那里,能够理解整个也就不难了。
总结
该说的也都说了,最后说一句:
如果是锻炼技术的话可以多线程爬这玩玩,但如果要写全网爬虫,还是写个单线程吧,尤其是在自己时间足够充裕的情况下,毕竟人家租个服务器也不容易。
python多线程爬虫数据顺序_多线程爬取小说时如何保证章节的顺序相关推荐
- Python新手爬虫训练小项目《爬取彼岸图网》(超详细讲解版)
Python新手爬虫训练小项目<爬取彼岸图网>(超详细讲解版) 这是我的第一篇文章,作为一名新手爬虫,这个算是我这几天来的努力成果,虽然代码寥寥几行但花费了大半天,新手上路还是不能只看视频 ...
- python处理json数据——网易云评论爬取
python处理json数据--网易云评论爬取 准备 代码 准备 1.python 3.7 2.需要安装的库: requests jsonpath pandas time fake_useragent ...
- 爬取小说时遇到的问题='gbk' codec can't encode character '\ufffd'、内容为空
python新手强烈推荐教程:爬虫入门 https://www.bilibili.com/video/av19954075 昨天在B站上看了这个爬虫入门视频,在实践中遇到了2个问题. 下面是我爬取小说 ...
- python爬虫影评_Python爬虫(二十)_动态爬取影评信息
本案例介绍从JavaScript中采集加载的数据.更多内容请参考:Python学习指南 #-*- coding:utf-8 -*- import requests import re import t ...
- Python网络爬虫(九):爬取顶点小说网站全部小说,并存入MongoDB
前言:本篇博客将爬取顶点小说网站全部小说.涉及到的问题有:Scrapy架构.断点续传问题.Mongodb数据库相关操作. 背景: Python版本:Anaconda3 运行平台:Windows IDE ...
- Python网络爬虫3 - 生产者消费者模型爬取某金融网站数据
博客首发于www.litreily.top 应一位金融圈的朋友所托,帮忙写个爬虫,帮他爬取中国期货行业协议网站中所有金融机构的从业人员信息.网站数据的获取本身比较简单,但是为了学习一些新的爬虫方法和技 ...
- 爬虫python爬取页面请求_03 Python网络爬虫第三弹《爬取get请求的页面数据》,urllib...
一.urllib库 urllib是Python自带的一个用于爬虫的库,其主要作用就是可以通过代码模拟浏览器发送请求.其常被用到的子模块在Python3中的为urllib.request和urllib. ...
- Python网络爬虫,Appuim+夜神模拟器爬取得到APP课程数据
一.背景介绍 随着生产力和经济社会的发展,温饱问题基本解决,人们开始追求更高层次的精神文明,开始愿意为知识和内容付费.从2016年开始,内容付费渐渐成为时尚. 罗辑思维创始人罗振宇全力打造" ...
- Python3爬虫数据入数据库---把爬取到的数据存到数据库,带数据库去重功能
这是python3实战入门系列的第三篇文章,要学习这一篇需要了解前两篇,要不学起来比较费劲 python3实战入门python爬虫篇001---网页爬虫,图片爬虫,文章爬虫,Python爬虫爬取新闻网 ...
最新文章
- 读书人:人机融合中的深度态势感知
- JSP的HTML基础实验原理,实验四 JSP基础语法
- 用指针编写程序将输入的字符串倒序输出
- 第55课 分解质因数 《小学生C++编程入门》
- window安全模式的用途
- ios侧滑返回:完美解决 interactivePopGestureRecognizer 卡住的问题
- 教大家一种迅雷下载百度云文件方法
- landsat 8 卫星 波段介绍 及组合
- 让ffmpeg支持输出h264格式
- redis中内存碎片处理
- 《控制论导论》读书:机构-黑箱
- python监控网站更新_Python 通过网站search功能监控网站内容更新
- 微信公众号首次关注自动回复图文信息
- MBA——mba的9堂课
- Educational Codeforces Round 97 (Rated for Div. 2)
- 光控可控硅有过零检测和无过零检测区别
- 阿里云RPA(机器人流程自动化)干货系列之五:业务流程梳理方法...
- QT网格线的颜色设置
- 校园网的实现 java_北科校园网开机自动登录的JAVA实现(已修正)
- 使用A*算法解迷宫最短路径问题
热门文章
- ajax c 提交form,使用ajax提交form表单,包括ajax文件上传
- centos rsyslog mysql_centos7+rsyslog+loganalyzer+mysql 搭建rsyslog日志服务器
- hp designiet 500_2020年HP学院壁纸
- mysql 一分钟内_MySQL语句需要超过一分钟才能执行
- [javaweb] servlet-session 会话跟踪技术 与 session保存作用域 (三)
- Misc-----[2021祥云杯初赛]鸣雏恋 提取压缩包文件图片名8个为一组 转ASC码base64转图片
- 使用Python和Pandas的最简单的数据清理方法
- Python基础教程:菱形继承问题
- java在线作业系统_在线作业系统论文
- 计算机高级语言程序Access,[计算机软件及应用]Access的编程语言VBA.ppt