上一篇多文章,是二级目录,根目录“小说”,二级目录“作品名称”,之后就是小说文件。

本篇改造了部分代码,将目录设置为根目录->作者目录->作品目录->作品章节.txt.

但这并不是本章内容当重点,重点是使用这个爬虫程序抓取当时候,经常会因为网络丢包等原因导致程序中断,

本来想着是循环获取网站状态,然后重新发起请求,结果好像也没什么用。然后在虫师讲selenium的书中看到了多线程,正好就实验下,结果发现,速度很快,cool!

以下代码基本摘自虫师的selenium2

多线程的引用

import threading

方法调用:threading.Thread(target=music, args=('music方法参数1',music方法参数2) )

from time import sleep,ctime
import threading def music(func,loop):
for i in range(loop):
print('music',func,ctime())
sleep(2) def movie(func,loop):
for i in range(loop):
print('movie',func,ctime())
sleep(4) def testOne():
music('简单的歌', 2)
movie('两杆大烟枪', 2)
print('all end', ctime())
def testTwo():
threads = []
t1 = threading.Thread(target=music, args=('喜欢的人',2) )
threads.append(t1) t2 = threading.Thread(target=movie, args=('搏击俱乐部',2) )
threads.append(t2) t3= threading.Thread(target=music, args=('喜欢的人2', 2))
threads.append(t3) for t in threads:
t.start() for t in threads:
t.join() print('all end', ctime())
if __name__ == '__main__':
testOne()
#testTwo()
#testThree()
#threadsRun()
t.join方法用来串联线程,可以保证all end 语句在最后打印出来。

  

创建线程管理类

创建类名时就引入Thread:class MyThread(threading.Thread)

class MyThread(threading.Thread):

    def __init__(self, func, args, name):
threading.Thread.__init__(self)
self.func = func
self.args = args
self.name = name def run(self):
self.func(*self.args)

 self:类实例,默认参数

 func:调用方法名

args:参数

name:方法+".__name__"

完整代码:

 class MyThread(threading.Thread):

     def __init__(self, func, args, name):
threading.Thread.__init__(self)
self.func = func
self.args = args
self.name = name def run(self):
self.func(*self.args) def super_play(file_,time):
for i in range(3):
print('play', file_, ctime())
sleep(time) def time(args):
pass def testThree():
threads = []
lists = {'气球.mp3': 3, '电影.rmvb': 4, 'last.avg' : 2}
for file_, time_ in lists.items():
t = MyThread(super_play, (file_, time_), super_play.__name__)
threads.append(t) files = range(len(lists)) for f in files:
threads[f].start()
for f in files:
threads[f].join() print('all end', ctime())

改造小说爬虫

好了,多线程说完了,怎么调用咱们写的小说类呢,很简单

首先,改造pageOne

    def readPageOneByThread(self,page,time_):
page_url = str(self.two_page_url)
new_page_url = page_url.replace("?", page)
print('第', page, '页---', new_page_url)
path = self.folder_path
self.readPageTwo(new_page_url, path)
sleep(time_)
# end readPageOneByThread ---------------------------------------

 init方法中,self.two_page_url = "http://www.cuiweijuxs.com/jingpinxiaoshuo/5_?.html"

接下来,编写添加线程的方法:

    def threadsRun(self):

        #self.readPageOne(122)

        for i in range(1,123):
page = str(i)
t = MyThread( self.readPageOneByThread, (page,2) , self.readPageOneByThread.__name__)
#t = threading.Thread(target=self.testRun, args=( str(i) ))
self.threads.append(t) for t in self.threads:
t.start()
for t in self.threads:
t.join()
#t.join() print('all end: %s' % ctime()) class MyThread(threading.Thread): def __init__(self, func, args, name):
threading.Thread.__init__(self)
self.func = func
self.args = args
self.name = name def run(self):
self.func(*self.args)

  这里偷了个懒,直接写了总页数,其实也可以使用原来的pageone方法读取last的div获取页数

下面是完整代码:

 # -*- coding: UTF-8 -*-
from urllib import request
from bs4 import BeautifulSoup
from time import sleep,ctime
import os
import threading
import re
import random '''
使用BeautifulSoup抓取网页
version:0.5 更新为本地缓存链接
author:yaowei
date:2018-03-23
''' class Capture(): def __init__(self):
self.index_page_url = 'http://www.cuiweijuxs.com/'
self.one_page_url = 'http://www.cuiweijuxs.com/jingpinxiaoshuo/'
self.two_page_url = "http://www.cuiweijuxs.com/jingpinxiaoshuo/5_?.html"
self.folder_path = '绯色/'
self.href_list = []
self.head = {}
self.threads = []
# 写入User Agent信息
self.head[
'User-Agent'] = 'Mozilla/5.0 (Linux; Android 4.1.1; Nexus 7 Build/JRO03D) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166 Safari/535.19' # end __init__ --------------------------------------- # 获取BeautifulSoup
def getSoup(self,query_url):
req = request.Request(query_url, headers=self.head)
webpage = request.urlopen(req)
html = webpage.read()
soup = BeautifulSoup(html, 'html.parser')
return soup
# soup = BeautifulSoup(html, 'html5lib') # 读取分版页面,打开分页链接
def readPageOne(self,count,time_): print('count=====',count) # 总页数
if count :
item_size = count
else :
# 读取页面
soup = self.getSoup(self.one_page_url)
last = soup.find("a", 'last')
item_size = int(last.string) print('item_size=====',item_size)
page_url = str(self.two_page_url) # 循环打开分页链接,读取分页页面
for item in range(item_size):
page = str(item + 1)
new_page_url = page_url.replace("?", page)
print('第', page, '页---', new_page_url)
path = self.folder_path
self.readPageTwo(new_page_url, path) sleep(time_)
# end readPageOne --------------------------------------- def readPageOneByThread(self,page,time_):
page_url = str(self.two_page_url)
new_page_url = page_url.replace("?", page)
print('第', page, '页---', new_page_url)
path = self.folder_path
self.readPageTwo(new_page_url, path)
sleep(time_)
# end readPageOneByThread --------------------------------------- # 读取分页页面
def readPageTwo(self, page_url, path):
soup = self.getSoup(page_url)
# first div[id="newscontent"]->div[class="l"]
con_div = soup.find('div', {'id': 'newscontent'}).find('div', {'class': 'l'})
# first div[id="newscontent"]->div[class="l"]->all spann[class="s2"]
span_list = con_div.find_all('span', {'class': 's2'}) # 遍历span
for span in span_list:
# 找到父节点下的span[class="s5"],以作者为文件夹名字
author = span.parent.find('span', {'class': 's5'}).get_text() # span[class="s2"]->a
a_href = span.find('a')
href = a_href.get('href') # 单部作品链接
folder_name = a_href.get_text() # 作品名字
print('a_href', href, '---folder_name', folder_name)
new_path = path + '/' + author + '/' + folder_name
self.createFolder(new_path) # 创建文件夹 self.readPageThree(href, new_path) # 读取单部作品 # t = threading.Thread(target=self.readPageThree, args={href, new_path})
# self.threads.append(t)
# end for # end readPage --------------------------------------- # 打开作品链接,遍历单章
def readPageThree(self, page_url, path):
soup = self.getSoup(page_url) # 作品页面
print('readPageThree--', page_url)
a_list = soup.find('div', {'id': 'list'}).find_all('a')
idx = 0 # 序号
for a_href in a_list:
idx = idx + 1
href = self.index_page_url + a_href.get('href')
file_path = path + '/' + str(idx) + '_' + a_href.get_text() + '.txt'
print('file_a_href', href, '---file_path', file_path) '''
new_path = self.isTxt(file_path)
if new_path:
print(new_path)
file_object = open('网页链接//hrefs.txt', 'w', encoding='utf-8')
file_object.write(href+','+new_path)
file_object.close()
'''
self.readPageFour(href, file_path) #self.href_list.append({'href': href, 'file_path': file_path}) # 多线程
#t = threading.Thread(target=self.readPageFour, args={href, file_path})
#t.start()
#t.join(15) # end readPageThree --------------------------------------- # 读取单章内容并写入
def readPageFour(self, page_url, path):
new_path = self.isTxt(path) # 是否存在,存在则返回'',没创建则返回合法文件名
if new_path:
soup = self.getSoup(page_url)
con_div = soup.find('div', {'id': 'content'}) # 读取文本内容
content = con_div.get_text().replace('<br/>', '\n').replace('&nbsp;', ' ')
# content = content.replace('&amp;','').replace('amp;','').replace('rdquo;','').replace('ldquo;','')
# content = content.rstrip("& amp;rdquo;amp;& amp;ldquo;") self.writeTxt(new_path, content) # 写入文件 # end readPageFour --------------------------------------- def readPageHtml(self, page_url, path):
soup = self.getSoup(page_url)
con_div = soup.find('div', {'id': 'content'})
content = con_div.get_text().replace('<br/>', '\n').replace('&nbsp;', ' ') def createFolder(self, path):
path = path.strip()
# 去除尾部 \ 符号
path = path.rstrip("\\")
rstr = r"[\:\*\?\"\<\>\|]" # '/ \ : * ? " < > |'
new_path = re.sub(rstr, "_", path) # 替换为下划线
is_exists = os.path.exists(new_path)
# 不存在则创建
if not is_exists:
os.makedirs(new_path)
print('目录:', new_path + ' create')
else:
print(new_path + ' 目录已存在') # end createFolder --------------------------------------- def isTxt(self, path):
path = path.strip()
# 去除尾部 \ 符号
path = path.rstrip("\\")
rstr = r"[\:\*\?\"\<\>\|]" # '/ \ : * ? " < > |'
new_path = re.sub(rstr, "_", path) # 替换为下划线
isExists = os.path.exists(new_path)
if isExists:
print(new_path, '已存在')
return ''
else:
return new_path # end createTxt --------------------------------------- def writeTxt(self, file_name, content):
isExists = os.path.exists(file_name)
if isExists:
print(file_name, '已存在')
else:
file_object = open(file_name, 'w', encoding='utf-8')
file_object.write(content)
file_object.close() # end writeTxt ------------------------------------------ def run(self):
try:
self.readPageOne()
except BaseException as error:
print('error--', error) def runTest(self):
try:
page_url = 'http://www.cuiweijuxs.com/4_4508/'
path = '小说/runTest'
self.readPageThree(page_url, path)
except BaseException as error:
print('error--', error) def testRun(self,num,time_):
for i in range(3):
print('num=',num,ctime())
sleep(time_) def threadsRun(self): #self.readPageOne(122) for i in range(1,123):
page = str(i)
t = MyThread( self.readPageOneByThread, (page,2) , self.readPageOneByThread.__name__)
#t = threading.Thread(target=self.testRun, args=( str(i) ))
self.threads.append(t) for t in self.threads:
t.start()
for t in self.threads:
t.join()
#t.join() print('all end: %s' % ctime()) class MyThread(threading.Thread): def __init__(self, func, args, name):
threading.Thread.__init__(self)
self.func = func
self.args = args
self.name = name def run(self):
self.func(*self.args) Capture().threadsRun()

python3+beautifulSoup4.6抓取某网站小说(四)多线程抓取的更多相关文章

  1. python3+beautifulSoup4.6抓取某网站小说(三)网页分析,BeautifulSoup解析

    本章学习内容:将网站上的小说都爬下来,存储到本地. 目标网站:www.cuiweijuxs.com 分析页面,发现一共4步:从主页进入分版打开分页列表.打开分页下所有链接.打开作品页面.打开单章内容. ...

  2. python3+beautifulSoup4.6抓取某网站小说(一)爬虫初探

    本次学习重点: 1.使用urllib的request进行网页请求,获取当前url整版网页内容 2.对于多级抓取,先想好抓取思路,再动手 3.BeautifulSoup获取html网页中的指定内容 4. ...

  3. python3+beautifulSoup4.6抓取某网站小说(二)基础功能设计

    本章学习内容:1.网页编码还原读取2.功能设计 stuep1:网页编码还原读取 本次抓取对象: http://www.cuiweijuxs.com/jingpinxiaoshuo/ 按照第一篇的代码来 ...

  4. Python多进程方式抓取基金网站内容的方法分析

    因为进程也不是越多越好,我们计划分3个进程执行.意思就是 :把总共要抓取的28页分成三部分. 怎么分呢? # 初始range r = range(1,29) # 步长 step = 10 myList ...

  5. 网站爬取-案例三:今日头条抓取(ajax抓取JS数据)

    今日头条这类的网站制作,从数据形式,CSS样式都是通过数据接口的样式来决定的,所以它的抓取方法和其他网页的抓取方法不太一样,对它的抓取需要抓取后台传来的JSON数据,先来看一下今日头条的源码结构:我们 ...

  6. 使用BurpSuite抓取HTTPS网站的数据包

    昨天面试,技术官问到了我如何使用BurpSuite抓取https网站的数据包,一时间没能回答上来(尴尬!).因为以前https网站的数据包我都是用Fiddler抓取的,Fiddlert自动帮我们配置好 ...

  7. python3使用requests登录人人影视网站

    python3使用requests登录人人影视网站 继续练习使用requests登录网站,人人影视有一项功能是签到功能,需要每天登录签到才能升级. 下面的代码python代码实现了使用requests ...

  8. 如何用python爬虫从爬取一章小说到爬取全站小说

    前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. PS:如有需要Python学习资料的小伙伴可以加点击下方链接自行获取http ...

  9. webmagic爬取渲染网站

    最近突然得知之后的工作有很多数据采集的任务,有朋友推荐webmagic这个项目,就上手玩了下.发现这个爬虫项目还是挺好用,爬取静态网站几乎不用自己写什么代码(当然是小型爬虫了~~|). 好了,废话少说 ...

随机推荐

  1. 31.Django缓存和信号

    缓存 由于Django是动态网站,所有每次请求均会去数据进行相应的操作,当程序访问量大时,耗时必然会更加明显,最简单解决方式是使用:缓存,缓存将某个views的返回值保存至内存或者memcache中, ...

  2. CSS( Cascading Style Sheets )简书

    (注:带*号的属性是CSS3新增属性)一.基本规则1.css通常存储在样式表(style)中,用于定义如何显示HTML元素:2.css主要由两个部分构成:选择器和一条或多条声明. 选择器通常是需要改变 ...

  3. 基于Three.js的360度全景--photo-sphere-viewer--简介

    这个是基于three.js的全景插件  photo-sphere-viewer.js  ---------------------------------------- 1.能添加热点: 2.能调用陀 ...

  4. [SCOI2010] 连续攻击问题

    题目 Description lxhgww最近迷上了一款游戏,在游戏里,他拥有很多的装备,每种装备都有2个属性,这些属性的值用[1,10000]之间的数表示.当他使用某种装备时,他只能使用该装备的某一 ...

  5. 使用了旧版nuget的.net项目在git中的问题

    曾几何时,使用nuget包管理项目依赖还需要将nuget执行程序及其配置文件包含在项目中. 如上图所示,在解决方案文件夹中,有专门为nuget程序设置的 .nuget 子目录. 当将项目纳入git管理 ...

  6. POJ 1979 DFS

    题目链接:http://poj.org/problem?id=1979 #include<cstring> #include<iostream> using namespace ...

  7. 部署腾讯云(CentOS6.6版本,jdk1.7+tomcat8+mysql)

    这是从一个大神哪里学到的,用来留下来用以记录 http://blog.csdn.net/qingluoII/article/details/76053736 只是其中有一个地方,我在学习的时候觉得可以 ...

  8. 【最全】经典排序算法(C语言)

    算法复杂度比较: 算法分类 一.直接插入排序 一个插入排序是另一种简单排序,它的思路是:每次从未排好的序列中选出第一个元素插入到已排好的序列中. 它的算法步骤可以大致归纳如下: 从未排好的序列中拿出首 ...

  9. Android开发心得-使用File ExPlorer无法访问系统内部文件

    问题:本机在获得ROOT权限后,使用Eclipse自带的File Explorer访问/data/data下各APP的存储文件,均无法打开.更换另外一个设备后,情况正常.Sumsung的有些机型在获得 ...

  10. 涉及模式之 装饰器模式详解(与IO不解的情缘)

    作者:zuoxiaolong8810(左潇龙),转载请注明出处,特别说明:本博文来自博主原博客,为保证新博客中博文的完整性,特复制到此留存,如需转载请注明新博客地址即可. LZ到目前已经写了九个设计模 ...