前言

爬取小说时,以每一个章节为一个线程进行爬取,如果不加以控制的话,保存的时候各个章节之间的顺序会乱掉。

当然,这里说的是一本小说保存为单个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多线程爬虫数据顺序_多线程爬取小说时如何保证章节的顺序相关推荐

  1. Python新手爬虫训练小项目《爬取彼岸图网》(超详细讲解版)

    Python新手爬虫训练小项目<爬取彼岸图网>(超详细讲解版) 这是我的第一篇文章,作为一名新手爬虫,这个算是我这几天来的努力成果,虽然代码寥寥几行但花费了大半天,新手上路还是不能只看视频 ...

  2. python处理json数据——网易云评论爬取

    python处理json数据--网易云评论爬取 准备 代码 准备 1.python 3.7 2.需要安装的库: requests jsonpath pandas time fake_useragent ...

  3. 爬取小说时遇到的问题='gbk' codec can't encode character '\ufffd'、内容为空

    python新手强烈推荐教程:爬虫入门 https://www.bilibili.com/video/av19954075 昨天在B站上看了这个爬虫入门视频,在实践中遇到了2个问题. 下面是我爬取小说 ...

  4. python爬虫影评_Python爬虫(二十)_动态爬取影评信息

    本案例介绍从JavaScript中采集加载的数据.更多内容请参考:Python学习指南 #-*- coding:utf-8 -*- import requests import re import t ...

  5. Python网络爬虫(九):爬取顶点小说网站全部小说,并存入MongoDB

    前言:本篇博客将爬取顶点小说网站全部小说.涉及到的问题有:Scrapy架构.断点续传问题.Mongodb数据库相关操作. 背景: Python版本:Anaconda3 运行平台:Windows IDE ...

  6. Python网络爬虫3 - 生产者消费者模型爬取某金融网站数据

    博客首发于www.litreily.top 应一位金融圈的朋友所托,帮忙写个爬虫,帮他爬取中国期货行业协议网站中所有金融机构的从业人员信息.网站数据的获取本身比较简单,但是为了学习一些新的爬虫方法和技 ...

  7. 爬虫python爬取页面请求_03 Python网络爬虫第三弹《爬取get请求的页面数据》,urllib...

    一.urllib库 urllib是Python自带的一个用于爬虫的库,其主要作用就是可以通过代码模拟浏览器发送请求.其常被用到的子模块在Python3中的为urllib.request和urllib. ...

  8. Python网络爬虫,Appuim+夜神模拟器爬取得到APP课程数据

    一.背景介绍 随着生产力和经济社会的发展,温饱问题基本解决,人们开始追求更高层次的精神文明,开始愿意为知识和内容付费.从2016年开始,内容付费渐渐成为时尚. 罗辑思维创始人罗振宇全力打造" ...

  9. Python3爬虫数据入数据库---把爬取到的数据存到数据库,带数据库去重功能

    这是python3实战入门系列的第三篇文章,要学习这一篇需要了解前两篇,要不学起来比较费劲 python3实战入门python爬虫篇001---网页爬虫,图片爬虫,文章爬虫,Python爬虫爬取新闻网 ...

最新文章

  1. 读书人:人机融合中的深度态势感知
  2. JSP的HTML基础实验原理,实验四 JSP基础语法
  3. 用指针编写程序将输入的字符串倒序输出
  4. 第55课 分解质因数 《小学生C++编程入门》
  5. window安全模式的用途
  6. ios侧滑返回:完美解决 interactivePopGestureRecognizer 卡住的问题
  7. 教大家一种迅雷下载百度云文件方法
  8. landsat 8 卫星 波段介绍 及组合
  9. 让ffmpeg支持输出h264格式
  10. redis中内存碎片处理
  11. 《控制论导论》读书:机构-黑箱
  12. python监控网站更新_Python 通过网站search功能监控网站内容更新
  13. 微信公众号首次关注自动回复图文信息
  14. MBA——mba的9堂课
  15. Educational Codeforces Round 97 (Rated for Div. 2)
  16. 光控可控硅有过零检测和无过零检测区别
  17. 阿里云RPA(机器人流程自动化)干货系列之五:业务流程梳理方法...
  18. QT网格线的颜色设置
  19. 校园网的实现 java_北科校园网开机自动登录的JAVA实现(已修正)
  20. 使用A*算法解迷宫最短路径问题

热门文章

  1. ajax c 提交form,使用ajax提交form表单,包括ajax文件上传
  2. centos rsyslog mysql_centos7+rsyslog+loganalyzer+mysql 搭建rsyslog日志服务器
  3. hp designiet 500_2020年HP学院壁纸
  4. mysql 一分钟内_MySQL语句需要超过一分钟才能执行
  5. [javaweb] servlet-session 会话跟踪技术 与 session保存作用域 (三)
  6. Misc-----[2021祥云杯初赛]鸣雏恋 提取压缩包文件图片名8个为一组 转ASC码base64转图片
  7. 使用Python和Pandas的最简单的数据清理方法
  8. Python基础教程:菱形继承问题
  9. java在线作业系统_在线作业系统论文
  10. 计算机高级语言程序Access,[计算机软件及应用]Access的编程语言VBA.ppt