从零开始写Python爬虫 --- 1.7 爬虫实践: 排行榜小说批量下载Ehco

5 个月前

本来只是准备做一个爬起点小说名字的爬虫,后来想了一下,为啥不顺便把小说的内容也爬下来呢?于是我就写了这个爬虫,他爬下了各类小说排行榜上的所有章节内容,并保存到本地。仔细想了一下,各种盗版小说阅读器,是不是就是这样做的呢?

目标分析:首先来看看我们排行榜的地址:

http://www.qu.la/paihangbang/

我们的目的很明确:

找到各类排行旁的的每一部小说的名字,和在该网站的链接:

观察一下网页的结构:

我们很容易就能发现,每一个分类都是包裹在:

之中

这种调理清晰的网站,大大方便了我们爬虫的编写

小说标题和链接:我们在刚才那个div里自己寻找:

玄幻奇幻排行

05-061.择天记05-062.大主宰05-063.太古神王05-064.雪鹰领主05-0115.武动乾坤

发现所有的小说都是在一个个列表里,并且里面清晰的定义了:

标题:title = div.a['title']

链接:link = 'http://www.qu.la/'

+ div.a['href']

这样一来,我们只需要在当前页面找到所有小说的连接,并保存在列表就行了。

列表去重的小技巧:信息的同学会发现,就算是不同类别的小说,也是会重复出现在排行榜的。

这样无形之间就会浪费我们很多资源,尤其是在面对爬大量网页的时候。

那么我们如何从抓取的url列表里去重呢?

刚学Python的小伙伴可能会去实现一个循环算法,来去重,

但是Python的强大之处就在于他可以通过及其优美的方式来解决很多问题,这里其实只要一行代码就能解决:

url_list = list(set(url_list))

这里我们调用了一个list的构造函数set:这样就能保证列表里没有重复的元素了。是不是很简单?

单个小说所有章节链接:首先我们从前面获取到的小说url连接选取一个做实验:

比如我最爱的择天记:

http://www.qu.la/book/168/

依然是无比清晰的网页结构,点个赞:

《择天记》正文

序 下山第一章 我改主意了第二章 为什么第九章 我有做错什么吗?

我们可以很容易的找到对应章节的连接:

这个代码是节选,不能直接用!后面会有说明

link='http://www.qu.la/' + url.a['href']

好的,这样我们就能把一篇小说的所有章节的链接爬下来了。

剩下最后一步:爬取文章内容:

文章内容的爬取:首先我们打开一章,并查看他的源代码:

我们能发现所有的正文内容,都保存在:

所有的章节名就更简单了:

第一章 我改主意了

那我们通过bs4库的各种标签的查找方法,就能很简单的找到啦

好了,让我们看看具体代码的实现:

代码的实现:模块化,函数式编程是一个非常好的习惯,我们坚持把每一个独立的功能都写成函数,这样会使你的代码简单又可复用。

网页抓取头:def get_html(url):

try:

r = requests.get(url, timeout=30)

r.raise_for_status

# 我手动测试了编码。并设置好,这样有助于效率的提升

r.encoding = ('utr-8')

return r.text

except:

return "Someting Wrong!"

获取排行榜小说及其链接:def get_content(url):

'''

爬取每一类型小说排行榜,

按顺序写入文件,

文件内容为 小说名字+小说链接

将内容保存到列表

并且返回一个装满url链接的列表

'''

url_list = []

html = get_html(url)

soup = bs4.BeautifulSoup(html, 'lxml')

# 由于小说排版的原因,历史类和完本类小说不在一个div里

category_list = soup.find_all('div', class_='index_toplist mright mbottom')

history_finished_list = soup.find_all(

'div', class_='index_toplist mbottom')

for cate in category_list:

name = cate.find('div', class_='toptab').span.string

with open('novel_list.csv', 'a+') as f:

f.write("\n小说种类:{} \n".format(name))

# 我们直接通过style属性来定位总排行榜

general_list = cate.find(style='display: block;')

# 找到全部的小说名字,发现他们全部都包含在li标签之中

book_list = general_list.find_all('li')

# 循环遍历出每一个小说的的名字,以及链接

for book in book_list:

link = 'http://www.qu.la/' + book.a['href']

title = book.a['title']

# 我们将所有文章的url地址保存在一个列表变量里

url_list.append(link)

# 这里使用a模式,防止清空文件

with open('novel_list.csv', 'a') as f:

f.write("小说名:{:<} \t 小说地址:{:<} \n".format(title, link))

for cate in history_finished_list:

name = cate.find('div', class_='toptab').span.string

with open('novel_list.csv', 'a') as f:

f.write("\n小说种类:{} \n".format(name))

general_list = cate.find(style='display: block;')

book_list = general_list.find_all('li')

for book in book_list:

link = 'http://www.qu.la/' + book.a['href']

title = book.a['title']

url_list.append(link)

with open('novel_list.csv', 'a') as f:

f.write("小说名:{:<} \t 小说地址:{:<} \n".format(title, link))

return url_list

获取单本小说的所有章节链接:def get_txt_url(url):

'''

获取该小说每个章节的url地址:

并创建小说文件

'''

url_list = []

html = get_html(url)

soup = bs4.BeautifulSoup(html, 'lxml')

lista = soup.find_all('dd')

txt_name = soup.find('h1').text

with open('/Users/ehco/Documents/codestuff/Python-crawler/小说/{}.txt'.format(txt_name), "a+") as f:

f.write('小说标题:{} \n'.format(txt_name))

for url in lista:

url_list.append('http://www.qu.la/' + url.a['href'])

return url_list, txt_name

获取单页文章的内容并保存到本地:这里有个小技巧:

我们从网上趴下来的文件很多时候都是带着
之类的格式化标签,

我们可以通过一个简单的方法把他过滤掉:

html = get_html(url).replace('
', '\n')

我这里单单过滤了一种标签,并将其替换成‘\n’用于文章的换行,

具体怎么扩展,大家可以开动一下自己的脑袋啦

还有,我这里的代码是不能直接在你们的机子上用的,

因为在写入文件的时候,绝对目录不一样

def get_one_txt(url, txt_name):

'''

获取小说每个章节的文本

并写入到本地

'''

html = get_html(url).replace('
', '\n')

soup = bs4.BeautifulSoup(html, 'lxml')

try:

txt = soup.find('div', id='content').text.replace(

'chaptererror();', '')

title = soup.find('title').text

with open('/Users/ehco/Documents/codestuff/Python-crawler/小说/{}.txt'.format(txt_name), "a") as f:

f.write(title + '\n\n')

f.write(txt)

print('当前小说:{} 当前章节{} 已经下载完毕'.format(txt_name, title))

except:

print('someting wrong')

缺点:本次爬虫写的这么顺利,更多的是因为爬的网站是没有反爬虫技术,以及文章分类清晰,结构优美。

但是,按照我们的这篇文的思路去爬取小说,

我大概计算了一下:

一篇文章需要:0.5s

一本小说(1000张左右):8.5分钟

全部排行榜(60本): 8.5小时!

是的! 时间太长了!

那么,这种单线程的爬虫,速度如何能提高呢?

自己洗个多线程模块?

其实还有更好的方式:下一个大的章节我们将一起学习Scrapy框架

学到那里的时候,我再把这里代码重构一边,

你会惊奇的发现,速度几十倍甚至几百倍的提高了!

这其实也是多线程的威力!

最后看一下结果吧:排行榜结果:

小说结果:

学到这里是不是越来越喜欢爬虫这个神奇的东西了呢?

加油,更神奇的东西还在后面呢!

每天的学习记录都会 同步更新到:

微信公众号: findyourownway

知乎专栏:从零开始写Python爬虫 - 知乎专栏

blog : www.ehcoblog.ml

Github: Ehco1996/Python-crawler

python 小说爬虫_从零开始写Python爬虫 --- 1.7 爬虫实践: 排行榜小说批量下载相关推荐

  1. python爬虫代理的使用_从零开始写Python爬虫 --- 2.4 爬虫实践:代理的爬取和验证...

    爬网站的时候,由于各种原因,ip被锁了,这个时候我们就需要通过代理来突破封锁.网上有很多代理网站,付费和免费的都有,这次我们就来写一个scrapy爬虫,爬一些免费的代理下来用. 目标分析: 本次爬取了 ...

  2. python 模拟浏览器selenium_从零开始写Python爬虫 --- 3.1 Selenium模拟浏览器

    本来说好要写Mechanize模拟浏览器的,结果一看居然只支持2.x版本的Python,而且已经长久没有更新维护了,本着学新不学旧的原则,我决定跳过他,直接开学Selenium(其实就是我懒,逃 Se ...

  3. python创建配置文件_如何写python的配置文件

    一.创建配置文件 在D盘建立一个配置文件,名字为:test.ini 内容如下: [baseconf] host=127.0.0.1 port=3306 user=root password=root ...

  4. 学python处理数据结构_从零开始学Python - 第009课:常用数据结构之字符串

    第二次世界大战促使了现代电子计算机的诞生,世界上的第一台通用电子计算机叫ENIAC(电子数值积分计算机),诞生于美国的宾夕法尼亚大学,占地167平米,重量27吨,每秒钟大约能够完成约5000次浮点运算 ...

  5. 代写python作业 费用_代写Python or R作业、代做Python语言程序作业、代写Longitude留学生作业...

    代写Python or R作业.代做Python语言程序作业.代写Longitude留学生作业 日期:2018-11-13 10:19 Your task is to run some analysi ...

  6. python爬斗鱼直播_从零开始写Python爬虫 --- 爬虫应用: 利用斗鱼Api抓取弹幕

    七月末的南京简直开启了「微波炉」模式,白天要学车的我,晚上自然选择宅在家看直播,看着狗贼叔叔满屏幕的弹幕,我就想着能不能把弹幕爬下来呢?说干就干 结果的展示: 这里只抓到弹幕内容和发送用户 并输出在终 ...

  7. python爬取知乎评论_从零开始写Python爬虫 --- 爬虫应用:IT之家热门段子(评论)爬取...

    不知道这里有没有喜欢刷it之家的小伙伴,我反正每天早上醒来第一件事就是打开it之家,看看有没有新鲜的段子 逃~ 其实这次是要来抓取it之家的热门评论,因为数量较多(上万),所以我们这次采用MongoD ...

  8. python爬虫软件-从零开始写Python爬虫,四大工具你值得拥有!

    如果你正在学习编程,那么"爬虫"绝对是你不可忽视的.那么,学习python爬虫之前需要哪些准备? 一颗热爱学习,不屈不挠的心 一台有键盘的电脑(什么系统都行.我用的os x,所以例 ...

  9. python语言编写爬虫_自写Python小爬虫一个 - 『编程语言区』 - 吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn...

    [Python] 纯文本查看 复制代码import requests import re import os #类型列表 Type_list = {1:'qingchun',2:'xiaohua',3 ...

最新文章

  1. 坦白讲!90%的数据分析师都不合格!!
  2. java8循环怎么给全局变量累加_JAVA使用for循环会重复调用list.size()吗?
  3. python27安装-二、Python2.7的安装并与Python3.8共存
  4. python基本使用-Python标准库详细介绍与基本使用方式,超详细!
  5. 卸载unixodbc_完全卸载旧的unixODBC并在redhat 6.3中安装2.3.2 unixODBC
  6. 下列哪个不是java的数据类型_下面哪个不是Java基本数据类型?()
  7. VVDocumenter 使用
  8. Stack Usage on Transfers to Interrupt and Exception Handling Routines
  9. 随机森林回归 python_用随机森林回归预测“美版拼多多”商品销量
  10. 【QT】QSS使用总结
  11. 电脑网页截长屏最简单的方法
  12. matlab空间计量AIC准则,关于AIC准则
  13. 三个免费的无版权图片站
  14. HikariDataSource 配置详解
  15. 青少年CTF-Web-CheckMe01
  16. 通灵学院|游戏设计研习1:人类的需求与动机★(1200字)
  17. android 手机开门,1号社区APP"手机开不了门后的处理流程"
  18. matlab数学建模-神经网络感知器函数
  19. 央行下属的上海资信网络金融征信系统(NFCS)签约机构数量突破800家
  20. 赋能B端,AI物联网“涂鸦智能”完成近2亿美元C轮融资

热门文章

  1. Java高级特性——反射
  2. idea报Can’t Open Local Terminal
  3. 查询每个用户最后一次登录信息
  4. java访问其它服务器,一个Java Web应用程序是否可以在tomcat服务器的同一本地主机中调用另一个Java Web应用程序...
  5. c语言20152016真题及答案,2016年计算机二级《C语言》基础练习题及答案(15)
  6. CTF工具-gdb插件peda,pwndbg安装
  7. 算法代码中的循环矩阵在哪体现_「Machine Learning 学习小结」| 向量在梯度下降算法当中的应用...
  8. linux获取文件的md5,linux shell 获取文件md5的命令linux操作系统 -电脑资料
  9. python创建文本、判断该文件共有多少行_python如何判断文件有多少行
  10. django mysql 游标,MySQL Cursor 存储过程之游标与相关循环