python3+beautifulSoup4.6抓取某网站小说(四)多线程抓取
上一篇多文章,是二级目录,根目录“小说”,二级目录“作品名称”,之后就是小说文件。
本篇改造了部分代码,将目录设置为根目录->作者目录->作品目录->作品章节.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(' ', ' ')
# content = content.replace('&','').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(' ', ' ') 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抓取某网站小说(四)多线程抓取的更多相关文章
- python3+beautifulSoup4.6抓取某网站小说(三)网页分析,BeautifulSoup解析
本章学习内容:将网站上的小说都爬下来,存储到本地. 目标网站:www.cuiweijuxs.com 分析页面,发现一共4步:从主页进入分版打开分页列表.打开分页下所有链接.打开作品页面.打开单章内容. ...
- python3+beautifulSoup4.6抓取某网站小说(一)爬虫初探
本次学习重点: 1.使用urllib的request进行网页请求,获取当前url整版网页内容 2.对于多级抓取,先想好抓取思路,再动手 3.BeautifulSoup获取html网页中的指定内容 4. ...
- python3+beautifulSoup4.6抓取某网站小说(二)基础功能设计
本章学习内容:1.网页编码还原读取2.功能设计 stuep1:网页编码还原读取 本次抓取对象: http://www.cuiweijuxs.com/jingpinxiaoshuo/ 按照第一篇的代码来 ...
- Python多进程方式抓取基金网站内容的方法分析
因为进程也不是越多越好,我们计划分3个进程执行.意思就是 :把总共要抓取的28页分成三部分. 怎么分呢? # 初始range r = range(1,29) # 步长 step = 10 myList ...
- 网站爬取-案例三:今日头条抓取(ajax抓取JS数据)
今日头条这类的网站制作,从数据形式,CSS样式都是通过数据接口的样式来决定的,所以它的抓取方法和其他网页的抓取方法不太一样,对它的抓取需要抓取后台传来的JSON数据,先来看一下今日头条的源码结构:我们 ...
- 使用BurpSuite抓取HTTPS网站的数据包
昨天面试,技术官问到了我如何使用BurpSuite抓取https网站的数据包,一时间没能回答上来(尴尬!).因为以前https网站的数据包我都是用Fiddler抓取的,Fiddlert自动帮我们配置好 ...
- python3使用requests登录人人影视网站
python3使用requests登录人人影视网站 继续练习使用requests登录网站,人人影视有一项功能是签到功能,需要每天登录签到才能升级. 下面的代码python代码实现了使用requests ...
- 如何用python爬虫从爬取一章小说到爬取全站小说
前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. PS:如有需要Python学习资料的小伙伴可以加点击下方链接自行获取http ...
- webmagic爬取渲染网站
最近突然得知之后的工作有很多数据采集的任务,有朋友推荐webmagic这个项目,就上手玩了下.发现这个爬虫项目还是挺好用,爬取静态网站几乎不用自己写什么代码(当然是小型爬虫了~~|). 好了,废话少说 ...
随机推荐
- java 关于性别的处理
运用数结构的思想(在数据库中把性别的值设置为 男 1 女 0) //数据结构思想应用 public static final Integer EMP_GENDER_OF_MAN = 1; public ...
- js备战春招の四のdevtool中各种错误、调试的使用技巧
try 语句允许我们定义在执行时进行错误测试的代码块. catch 语句允许我们定义当 try 代码块发生错误时,所执行的代码块. JavaScript 语句 try 和 catch 是成对出现的. ...
- 用Node.js写爬虫,撸羞羞的图片
说到爬虫,很多人都认为是很高大上的东西.哇塞,是不是可以爬妹纸图啊,是不是可以爬小片片啊.答案就是对的.爬虫可以完成这些东西的操作.但是,作为一个正直的程序员,我们要在法律允许范围内用爬虫来为我们服务 ...
- BZOJ4825 单旋
分析:一道水题,去年考场发现了特点但是不会splay维护挂了,然后现在我写了个treap. 画一画图就可以解决这道题了,自己试一下. 代码如下: #include<bits/stdc++.h&g ...
- Nagios详解(基础、安装、配置文件解析及监控实例)
一.Nagios基础 1.简介Nagios是一款开源网络监视工具.可监控网络服务(SMTP.POP3.HTTP.NNTP.ICMP.SNMP.FTP.SSH.PING---).监控主机资源.根据需求设 ...
- DBI-1.634之selectrow_array与fetchrow_array的区别
在DBI-1.634使用手册里有一个selectrow_array函数,该函数具体说明如下: This utility method combines "prepare", &qu ...
- 【重点--web前端面试题总结】
前端面试题总结 HTML&CSS: 对Web标准的理解.浏览器内核差异.兼容性.hack.CSS基本功:布局.盒子模型.选择器优先级及使用.HTML5.CSS3.移动端适应. JavaScri ...
- Java路径类问题总结
一.获取路径: 单独的Java类中获得绝对路径根据java.io.File的Doc文挡,可知: 默认情况下new File("/")代表的目录为:System.getPropert ...
- java中StringUtils中isEmpty 和isBlank的区别
StringUtils在commons-lang-2.2.jar包中:org.apache.commons.lang.StringUtils ; StringUtils方法的操作对象是java.lan ...
- 斑马ZPL指令加入如换行、回车等控制符的方法
在程序中可能会被过滤掉,直接在指令中加入ASCII对应的16进制字符即可解决改问题, 语法:_十六进制(ASCII) 栗子:hello_0D_0Aworld 换行 扫描结果: hello world