笔趣阁爬虫(2020重制版),贴心的操作,谁用谁知道
支持正版,一切只为学习
之前写的笔趣阁爬虫有不少同学说不能爬了,我后来发现是网站改版的缘故,前些日子把书里的爬虫项目都整的差不多了,现在又有些不知道爬什么好了,刚好在这段时间把笔趣阁爬虫代码重写一下。
(PS:我看自己之前写的代码感觉写的好丑哦,官方吐槽,最为致命,以前的链接)
做了以下改进:
- 将爬虫代码写入对象中,把用户选择判断的语句写在外部,使得爬虫本身更加简洁;
- 优化互动的相关代码,操作更舒适;
- 采用多进程爬取小说各章节的内容,速度更快;
- 加入UA代理,尽可能反反爬虫,安全性更高 。
目录
- 一、基本思路
- 二、构建爬虫
- 1、借东风,借用网站搜索书籍的功能
- 2、遇明主,用户确认下载小说
- 3、取荆州,下载小说内容,保存到docx文档中
- 三、运行测试
- 四、总结
- 五、完整代码
前期准备,需要在cmd里下载安装以下第三方库:
pip install requests
pip install python-docx
一、基本思路
以下是爬取笔趣阁小说的主体思路,爬虫代码在这个思路上扩展构建。
二、构建爬虫
笔趣阁的网站众多,这是我爬取的笔趣阁网址:http://www.biquge.tv/
我将爬虫写到 biqugeCrawl 类中。
1、借东风,借用网站搜索书籍的功能
以搜索圣墟为例,网站的搜索是靠这个searchkey这个参数。在biqugeCrawl类中定义一个search_book() 函数专用于查找小说功能。
1.1、 大家看到这个%什么的或许会很陌生,这是因为URL 只允许一部分 ASCII 字符(数字字母和部分符号),其他的字符(如汉字)是不符合 URL 标准的,所以我们这里使用 urllib库 的 parse.quote() 将其转换为URL编码。
转换后还是不符合要求,怀疑是编码格式的问题,去网页的源码中查看,如下显示为GBK编码,所以我们输入的书名还要先转换为GBK格式。
name = input("请输入书名:")
name = parse.quote(name.encode('gbk'))
1.2、 接下来我们拼接搜索的url,并请求它,得到相应的搜索结果的html网页。
__random_ua()是随机返回user-agent的函数,这样在一定程度上可以避免被反爬。代码很简单,自己看一下。
serach_url = "http://www.biquge.tv/modules/article/search.php?searchkey={}"
url = serach_url.format(name)
response = requests.get(url=url, headers=self.__random_ua())
1.3、 如果搜到了书籍,也不直接下载,因为好多小说名字相似趁热度的,所以我这里获取第一个小说名及作者名返回让用户确认是否下载。另外,因为搜索不当,可能没有书籍,也可能是关键字太短了,我用try-except 另行处理,返回None值,并提示没有该书。
# 搜索书籍
root = etree.HTML(response.content)try:book_name = root.xpath('//*[@id="nr"]/td[1]/a/text()')[0]book_author = root.xpath('//*[@id="nr"]/td[3]/text()')[0]book_url = root.xpath('//*[@id="nr"]/td[1]/a/@href')[0]return [book_name, book_author, book_url]except:return None
# 用户确认
book = biquge.search_book()
if book is not None:flag = input("搜索到的书名为《{}》,作者名为{},请确认是否下载【Y/N】".format(book[0], book[1]))while 1:if flag == 'Y' or flag == 'y':biquge.download(book[0], book[2])breakelif flag == 'N' or flag == 'n':breakelse:flag = input("请正确输入【Y/N】!")
else:print("查无此书")
2、遇明主,用户确认下载小说
上一步写得search_book() 函数在搜到小说得情况下返回了三个数据:小说名、作者名、小说得url,经由用户确认,调用biqugeCrawl.download() ,获取小说章节链接,并采用多线程下载内容。
2.1、 请求网页,获取链接,因为它有九个最新章节得在里面,所以我们使用xpath解析出来得列表要略去这九个,直接用切片切掉。
response = requests.get(url=url, headers=self.__random_ua())
root = etree.HTML(response.content)# 拼接完整得章节url
content_urls = list(map(lambda x: "http://www.biquge.tv/" + x, root.xpath('//*[@id="list"]/dl/dd/a/@href')[9:]))
content_names = root.xpath('//*[@id="list"]/dl/dd/a/text()')[9:]# 创建以书名命名的文件夹
path = '《' + book_name + '》'
if not os.path.exists(path):os.mkdir(path)
2.2、 有了相应得链接,这里就要使用多进程了,速度大大的增加。
utls_names = [i for i in zip(content_urls, content_names)]# 同时进行得进程数量
pool = Pool(processes=5)# 将utls_names中得元素分配给parse()函数
pool.map(self.parse, utls_names)
3、取荆州,下载小说内容,保存到docx文档中
上面一步是获取到了小说章节的目录,并采用多进程的方法调用了biqugeCrawl.parse() 函数,这个函数的作用就是下载并保存小说内容。
3.1、 解析出小说的主体内容,观察网页源码,可以发现,小说的内容都在<div id="content"></div>
html标签中,我用正则表达式将其解析出来,并对文本做了一些处理。
response = requests.get(url=url, headers=self.__random_ua())
html = response.content.decode('gbk')
content = "".join(re.findall('<div id="content">(.*?)</div>', html, re.S))
content = re.sub("<.*?>", "", re.sub(" ", " ", content))
3.2、 获取到的小说内容肯定是要保存起来的,我这里保存到了docx文档文件中。这里又用xapth解析出了小说名,作为文本保存路径的一部分。
我后面想想那小说章节名也可以不传进来,在这里解析就是了,算了,无伤大雅
root = etree.HTML(response.content)
book_name = root.xpath('//div[@class="con_top"]/a[2]/text()')[0]# 创建document对象
document = Document()# 将文本写入文档
document.add_paragraph(content)document.save("《{}》/《{}》.docx".format(book_name, name))print('《' + name + '》已下载完成')
爬虫的思路都理清楚了,还有一些旁支末节详见完整代码,有什么不清楚也可以直接来问我。
三、运行测试
做了一些简单的测试,按照提示来操作都是没问题的,就算不按照提示来,整些奇奇怪怪的操作也是没问题的,很舒服,而且速度也快,我爬取《圣墟》一千五百多章大概耗时三分钟,也可以更快,不过我们只是学习爬虫的技术又不是搞破坏,太快的话对服务器的压力也很大的,还有被封IP的可能,可以参考【构建简单IP代理池】,使用代理ip,这样更安全。
IP代理池我自己是改了好几版了,用起来还是很舒服的,不用担心被封ip的事情了,把ip数据存到数据库中,上手简单,建议学习搭建。
四、总结
这爬取笔趣阁本来就是个小爬虫,我感觉很适合让刚入爬虫的同学学习的,虽然相比那种只爬取单个网页的入门学习方式要多些困难,不过克服困难后还是会有很大的进步的,这是我整理的【爬虫实战项目集合】,有兴趣的可以看看,由浅入深的学习爬虫,最简单的和较为复杂的都有。
对于这个爬笔趣阁的项目,我认为有一个很大的槽点,它是多进程爬取出来的,文件按时间排序不行,按名称排序又是下面这样,emm,太难看了,还是之前老版本的非多进程好看,但就是慢些,没有思路解决这个问题,求教。
另外,我想在爬虫里加上暂定下载的功能,以及断网处理的功能(这两个功能是一个原理,搞一个任务队列),这爬取笔趣阁小爬虫是小爬虫,但小事情多做几次,就会越发的精细,好了,也没啥讲的了,祝大家写程序没有bug,天天开心。
啊,对啦对啦,点个赞,点个关注吧,蟹蟹支持。
五、完整代码
import os
from urllib import parse
import requests
from docx import Document
from lxml import etree
import re
import random
from multiprocessing import Poolimport timeclass biqugeCrawl():m_url = "http://www.biquge.tv/"# 查询书籍函数def search_book(self):serach_url = "http://www.biquge.tv/modules/article/search.php?searchkey={}"name = input("请输入书名:")name = parse.quote(name.encode('gbk'))url = serach_url.format(name)response = requests.get(url=url, headers=self.__random_ua())root = etree.HTML(response.content)try:book_name = root.xpath('//*[@id="nr"]/td[1]/a/text()')[0]book_author = root.xpath('//*[@id="nr"]/td[3]/text()')[0]book_url = root.xpath('//*[@id="nr"]/td[1]/a/@href')[0]return [book_name, book_author, book_url]except:return None# 下载函数def download(self, book_name, url):response = requests.get(url=url, headers=self.__random_ua())root = etree.HTML(response.content)content_urls = list(map(lambda x: "http://www.biquge.tv/" + x, root.xpath('//*[@id="list"]/dl/dd/a/@href')[9:]))content_names = root.xpath('//*[@id="list"]/dl/dd/a/text()')[9:]# 创建以书名命名的文件夹path = '《' + book_name + '》'if not os.path.exists(path):os.mkdir(path)utls_names = [i for i in zip(content_urls, content_names)]pool = Pool(processes=5)pool.map(self.parse, utls_names)print("《{}》下载完毕!".format(book_name))# 爬取文章内容函数def parse(self, url_name):url = url_name[0]name = url_name[1]try:response = requests.get(url=url, headers=self.__random_ua())html = response.content.decode('gbk')root = etree.HTML(response.content)book_name = root.xpath('//div[@class="con_top"]/a[2]/text()')[0]content = "".join(re.findall('<div id="content">(.*?)</div>', html, re.S))content = re.sub("<.*?>", "", re.sub(" ", " ", content))# 创建document对象document = Document()# 将文本写入文档document.add_paragraph(content)document.save("《{}》/《{}》.docx".format(book_name, name))print('《' + name + '》已下载完成')except Exception as e:with open("./log.txt", "a+", encoding="utf-8") as file:file.write("*"*30+"\n"+str(e))print("出现异常,下载中断,请查看log文件!")pass# 随机UAdef __random_ua(self):UA = ["Mozilla/5.0 (Windows NT 5.1; rv:7.0.1) Gecko/20100101 Firefox/7.0.1","Mozilla/5.0 (Windows NT 6.1; WOW64; rv:54.0) Gecko/20100101 Firefox/54.0","Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1","Mozilla/5.0 (Windows NT 6.1; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0","Mozilla/5.0 (X11; U; Linux Core i7-4980HQ; de; rv:32.0; compatible; JobboerseBot;Gecko/20100101 Firefox/38.0","Mozilla/5.0 (Windows NT 5.1; rv:36.0) Gecko/20100101 Firefox/36.0","Mozilla/5.0 (Windows NT 5.1; rv:33.0) Gecko/20100101 Firefox/33.0","Mozilla/5.0 (Windows NT 10.0; WOW64; rv:50.0) Gecko/20100101 Firefox/50.0","Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0) Gecko/20100101 Firefox/52.0","Mozilla/5.0 (Windows NT 6.1; WOW64; rv:50.0) Gecko/20100101 Firefox/50.0","Mozilla/5.0 (Windows NT 6.1; WOW64; rv:43.0) Gecko/20100101 Firefox/43.0","Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0","Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.12) Gecko/20050915 Firefox/1.0.7","Mozilla/5.0 (Windows NT 6.1; WOW64; rv:17.0) Gecko/20100101 Firefox/17.0","Mozilla/5.0 (Windows NT 10.0; WOW64; rv:54.0) Gecko/20100101 Firefox/54.0","Mozilla/5.0 (Windows NT 6.0; rv:34.0) Gecko/20100101 Firefox/34.0","Mozilla/5.0 (Windows NT 6.1; WOW64; rv:52.0) Gecko/20100101 Firefox/52.0","Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:57.0) Gecko/20100101 Firefox/57.0","Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:63.0) Gecko/20100101 Firefox/63.0","Mozilla/5.0 (Windows NT 5.1; rv:40.0) Gecko/20100101 Firefox/40.0","Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:57.0) Gecko/20100101 Firefox/57.0","Mozilla/5.0 (Windows NT 6.1; WOW64; rv:42.0) Gecko/20100101 Firefox/42.0","Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041107 Firefox/1.0","Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0","Mozilla/5.0 (Windows NT 6.1; rv:17.0) Gecko/20100101 Firefox/20.6.14","Mozilla/5.0 (Windows NT 5.1; rv:30.0) Gecko/20100101 Firefox/30.0","Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10; rv:33.0) Gecko/20100101 Firefox/33.0","Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:25.0) Gecko/20100101 Firefox/29.0","Mozilla/5.0 (Windows NT 6.1; WOW64; rv:38.0) Gecko/20100101 Firefox/38.0","Mozilla/5.0 (Windows NT 6.1; rv:52.0) Gecko/20100101 Firefox/52.0","Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:59.0) Gecko/20100101 Firefox/59.0","Mozilla/5.0 (Windows NT 6.1; WOW64; rv:47.0) Gecko/20100101 Firefox/47.0","Mozilla/5.0 (Windows NT 6.1; WOW64; rv:41.0) Gecko/20100101 Firefox/41.0","Mozilla/5.0 (X11; U; Linux Core i7-4980HQ; de; rv:32.0; compatible; JobboerseBot; Gecko/20100101 Firefox/38.0","Mozilla/5.0 (Windows NT 6.1; WOW64; rv:45.0) Gecko/20100101 Firefox/45.0"]headers = {"User-Agent": {}}headers["User-Agent"] = random.choice(UA)return headersif __name__ == '__main__':biquge = biqugeCrawl()print("----笔趣阁小说爬虫----")print("1-------------搜索小说")print("2----------------退出")flag = input("请输入指令选择相应功能:")while 1:error_str = ""if flag == "1":book = biquge.search_book()if book is not None:flag = input("搜索到的书名为《{}》,作者名为{},请确认是否下载【Y/N】".format(book[0], book[1]))while 1:if flag == 'Y' or flag == 'y':biquge.download(book[0], book[2])breakelif flag == 'N' or flag == 'n':breakelse:flag = input("请正确输入【Y/N】!")else:print("查无此书")elif flag == "2":exit(1)else:error_str = "指令错误,"flag = input("{}请重新输入指令选择相应功能【1.搜索;2.退出】:".format(error_str))
笔趣阁爬虫(2020重制版),贴心的操作,谁用谁知道相关推荐
- 用python60行代码写一个简单的笔趣阁爬虫!三分一章?
前言 利用python写一个简单的笔趣阁爬虫,根据输入的小说网址爬取整个小说并保存到txt文件.爬虫用到了BeautifulSoup库的select方法 结果如图所示: 本文只用于学习爬虫 一.网页解 ...
- 偷偷溜出来写个笔趣阁爬虫
爬笔趣阁的,或许有点小bug,权当过过手瘾 害,居然打不出代码块,就这样好了 import requests import random from lxml import etree import t ...
- 初学爬虫-笔趣阁爬虫
import requests from lxml import etree base_url=input("请输入小说url:") #如春日宴的url为https://www.x ...
- python3+正则(re)增量爬虫爬取笔趣阁小说( 斗罗大陆IV终极斗罗)
python3+re 爬虫爬取笔趣阁小说 斗罗大陆IV终极斗罗 爬取前准备 导入的模块 分析 正则的贪婪与非贪婪 附完整代码示例 爬取前准备 导入的模块 import redis #redis数据库 ...
- 爬虫练习-爬取笔趣阁小说
练习一下爬虫,将笔趣阁的小说根据需求目标再爬取下来,本文仅仅学习爬虫技术,大家还是要支持一下正版网站的 思路: Created with Raphaël 2.2.0开始输入书名查询小说是否存在跳转页面 ...
- java爬虫爬取笔趣阁小说
java爬虫爬取笔趣阁小说 package novelCrawler;import org.jsoup.Connection; import org.jsoup.HttpStatusException ...
- Python爬虫--笔趣阁小说爬取
Python爬虫–笔趣阁小说爬取 爬虫用到的插件 import requests from lxml import etree 小说目录页 以小说"我有百万技能点"为例,在笔趣阁搜 ...
- 爬虫实战|从笔趣阁爬取书籍并简单保存
最近在看崔庆才那本经典的爬虫开发书籍,之前虽然看过一点视频,但是与书籍相比还是书籍更加成体系,让我对知识有一个宏观的把控.目前已经看了前四章,了解了一些基础知识和如何解析数据的方法,但是对于数据的保存 ...
- python爬虫-笔趣阁
突发奇想去爬笔趣阁的小说,毕竟我是一个老书虫,闲话不多说,代码呈上.主要使用requests BeautifulSoup from urllib.request import quote, unquo ...
最新文章
- 番茄时间有感之关于在疫情期间我与ACM不得不说的故事
- 是什么还让你停留在 iOS 平台?是这些理由吗
- 浅谈java.awt使用过程中遇到的问题
- python cos函数_Python Tensorflow cos()用法及代码示例
- c++ primer练习题 第七章 类 (Class)
- jQuery特效 | 导航底部横线跟随鼠标缓动
- defaultView与currentStyle的区别_获取CSS样式值
- pycharm汉化(搜索不到插件的参考第二中方法)
- php在线拍照代码,PHP+Javascript实现在线拍照功能实例_php技巧
- 【任务二】打卡——by 003-Vamein
- python与金融数据分析论文_python 金融大数据分析 pdf
- 太美医疗科技CTMS临床试验项目管理系统的全新升级
- 使用Python模拟武侠小说中两派人的一场遭遇战。
- euler和鸿蒙,euleros 鸿蒙
- shell脚本中 set -ex
- 为什么我的C语言移位操作达不到效果??
- 专题二:无穷小量阶的比较-一刷
- 苹果手机软件升级密码_密码太多总是忘?不如试试这7个密保工具
- python简单心形代码爱情闪字_HTML5 + CSS3 实现闪光字
- Spring源码深度解析(郝佳)-学习-RMI使用及Spring源码解读