写在前面的废话

  1. 没错,这个爬虫的确只是我想统计下自己读小说的速度和自己已经读了多少小说写的,可以爬一些小说的数据,不能用来爬小说本身。不过稍加改进可以实现更多的功能,我会在之后的文章实现其他的功能。
  2. 话说我都好久没有发过文章了啊,所以就来水一篇博客了(x)

正文

一、使用工具和目标网站的分析

使用的工具,恩,如题,我使用的是 python3.7,其他版本问题应该也不大。
我用到的包有三个:

  • requests 用于发出http请求来获取数据
  • re 用来匹配正则表达式的(我没有使用 HTML 解析器)
  • time

然后是网站的分析了。
这次我拿 SF轻小说 http://book.sfacg.com/ 这个网站开刀。

对网站分析就不难整理接下来的思路了。网站自带收藏夹功能,而访问别人的收藏夹并不需要登录,因而在之后爬取数据的时候不需要模拟登录,可以比较方便地爬取数据。收藏夹内有各本小说的标题,作者,链接等数据,在小说页就可以看到字数以及更多我们想要的数据了。因此我们可以在阅读时把小说添加进收藏夹内,之后统计整个收藏夹就可以得到我们想要的数据了。

二、开工!

随便打开一个火袋页:

就可以看到里面的基本信息了。
比如这个火袋的 URL 是: http://p.sfacg.com/p/1892478/1/
不难得出,前面的 http://p.sfacg.com/p/ 就是每个火袋共有的前缀了。 1892478 是这个火袋的id, 最后的1/是页码,第一页默认不会有这个页码,这里是我加的。默认一页现实10本书,可以根据上面显示的总共的小说数计算出总页数。虽然最下面可以选择每页数量,但是有最大限制,当总数过多时就起不到作用了。所以这里就按照默认的数量来。

开 f12,分析下html:

先找到小说的总数。

然后可以看到,一个 <ul class="content_comment cover" eid="xxxx">就是一本小说了。点开标签还可以看到这本小说的封面标题作者等信息,不过这些我们都可以等进入详情页再去爬取。
SF轻小说的每本小说详情页的格式为: http://book.sfacg.com/Novel/xxx/ 这后面的xxx就是前面的 eid 了。
我们先试试把这个火袋里的所有小说爬出来:

三、开爬!

代码写出来大概是这个样子:

import requests
import re
import timefavlist = 'http://p.sfacg.com/p/1892478/'
headers={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36'}req = requests.get(favlist, headers=headers)pat_getcount = re.compile(r'<a href="javascript:void\(0\)">全部小说\(([0-9]*)\)</a>')
pat_getnovel = re.compile(r'<ul class="content_comment cover" eid="([0-9]*)">')content = req.content.decode('utf-8')pages = int(pat_getcount.findall(content)[0])
pages = pages // 10 + 2for page in range(1,pages):req = requests.get(favlist+str(page)+'/', headers=headers)content = req.content.decode('utf-8')eid_list = pat_getnovel.findall(content)print(eid_list)

运行一下看看:

可以看到,这个火袋里所有小说的id都被爬下来了,之后只要拼接下字符串就可以得到每本小说的url了。
然后简单讲解下:
首先是三个包的导入,收藏夹地址和header的定义,就不用多讲了。
然后是正则表达式的定义。从html里可以找到相应的规律。因为小说的数量和eid都是数字,所以用 ([0-9]*) 来代替。写的时候注意下给原有的括号加上转义就行了。
总页数的计算可以用 总页数 = 小说总数 // 每页的小说数 + 1 来计算。代码中是 +2 而不是 +1 是为了后面的 range(1, pages) 方便一些所以这样的。
然后就是后面的遍历了。根据刚才算出来的页数遍历每一页,然后从每页提取相应的id,后面用id去访问详情页就可以了。
这里有一点,在开始获取总页数之后,第一页是不用再访问一遍的,不过为了方便些,我还是把第一页放到底下的for里了。
最后储存小说id的list也不会去打印了,之后会把所有的id放到一个list里然后去遍历的。

三、继续分析

接着刚才,随便打开一本小说的详情页看看:

可以看到小说的详情了,至少我想要的字数信息就在这里啦!
url的格式也很清楚了,最后的那串数字就是eid了:

base_url = 'http://book.sfacg.com/Novel/'
for eid in eid_list:req = requests.get(base_url+eid+'/', headers=headers)

按f12看看源码:


字数很好找,不过如果直接匹配 字数:([0-9]*) 的话会匹配到多个,加上前面的 span 标签就可以了。
对于标题,同理,加上前面的 h1 标签就行了。涉及到多行的时候使用 \s 匹配空白字符。

pat_gettitle = re.compile(r'<h1 class="title">\s*<span class="text">(.*?)</span>')
pat_getchara = re.compile(r'<span class="text">字数:([0-9]*)字')

最后别忘了用一个变量储存下总字数。最后的代码差不多是这样的:

import requests
import re
import timefavlist = 'http://p.sfacg.com/p/1892478/'
headers={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36'}req = requests.get(favlist, headers=headers)pat_getcount = re.compile(r'<a href="javascript:void\(0\)">全部小说\(([0-9]*)\)</a>')
pat_getnovel = re.compile(r'<ul class="content_comment cover" eid="([0-9]*)">')content = req.content.decode('utf-8')pages = int(pat_getcount.findall(content)[0])
pages = pages // 10 + 2
eid_list=[]for page in range(1,pages):req = requests.get(favlist+str(page)+'/', headers=headers)content = req.content.decode('utf-8')eid_list += pat_getnovel.findall(content)pat_gettitle = re.compile(r'<h1 class="title">\s*<span class="text">(.*?)</span>')
pat_getchara = re.compile(r'<span class="text">字数:([0-9]*)字')base_url = 'http://book.sfacg.com/Novel/'
all_character = 0
for eid in eid_list:req = requests.get(base_url+eid+'/', headers=headers)content = req.content.decode('utf-8')title = pat_gettitle.findall(content)[0]chara = pat_getchara.findall(content)[0]print(title, chara)all_character += int(chara)print('All count of character: ', all_character)

运行下看看:

成功!

总结

这次算是成功搞定了这个项目,对这个网站的目录页和小说详情页都有访问。虽然这次我只是想算下字数,但之后只要稍加改动便可以实现更多更复杂的效果,整体还是不错的,而且以后写其他代码时的参考性也很高。
这次的代码涉及到了requests库的使用,正则表达式还有html的审计等相关知识,以后想复习的时候可以回来参考下。

什么,你说我time库没有用?time库相关主要是用来计算时间以及通过sleep防止请求过快被封的情况的。你要问什么时候在哪用哪个相关的函数?这个我就先不讲了,自己研究吧2333(x)

Python爬虫 - 统计自己读过小说的字数相关推荐

  1. python统计小说人物_Python爬虫 - 统计自己读过小说的字数

    写在前面的废话 没错,这个爬虫的确只是我想统计下自己读小说的速度和自己已经读了多少小说写的,可以爬一些小说的数据,不能用来爬小说本身.不过稍加改进可以实现更多的功能,我会在之后的文章实现其他的功能. ...

  2. linux 定时任务 (python 爬虫统计博客数据)

    linux 定时任务 (python 爬虫统计博客数据) 1. 任务目标 定时任务中,每天统计一下今日博客的各项数据,并以邮件的形式发送给自己. 2. linux 定时任务 (python) 一切复杂 ...

  3. Python 爬虫统计当地所有医院信息

    这是上周五在微信群里看到的问题: 之前曾尝试过对知乎和微博热榜的简单爬虫,算是小有经验但仍需锻炼,于是趁着这个机会,主动包揽了爬虫代码,并在这回顾整理一番. 对于爬虫的概念,往复杂说会涉及很多技术点, ...

  4. Python 爬虫统计影评,超详细(按照步骤弄不出来杀楼主祭天)

    在学习网络爬虫之前,先看一下完成效果吧,勾起大家的学习兴趣 图片中显示的文字,正是爬取的豆瓣电影中第一个正在热播的电影的评价中出现的高频词汇 是不是很有学习兴趣呀?准备开始Python的学习之旅吧,在 ...

  5. python爬虫统计上证指数周、月涨跌现象

    题目:统计2018年上证指数,在每周.每月周期中每天的涨跌情况 知识点分解: 1.抓取2018年全年的上证指数数据,元数据为{时间:指数},保存为csv格式 2.解析元数据中'时间'为星期属性,月属性 ...

  6. 【Python爬虫网站数据实战】Python爬虫 统计淘宝商品数据+数据可视化

  7. Python爬虫及其它函数知识读记及简单用法,持续更新中...

    Python爬虫相关函数知识读记及简单用法,持续更新中- requests [riˈkwests] n. 请求,要求( request的名词复数 ): 需要: 所请求的事物: 申请书 函数或单词- 音 ...

  8. python爬虫难点_Python爬虫技巧

    ​在本文中,我们将分析几个真实网站,来看看我们在<用Python写网络爬虫(第2版)>中学过的这些技巧是如何应用的.首先我们使用Google演示一个真实的搜索表单,然后是依赖JavaScr ...

  9. Python爬虫网易云歌词及词频统计--(周杰伦top50)

    本篇博客是利用Python爬虫网易云音乐,并利用jieba分词,对歌词进行分词,然后分析周杰伦top50中最常出现的词语. 我们先尝试获取一首歌的歌词吧,比如等你下课这首歌 上面的id就是等你下课这首 ...

最新文章

  1. uboot、kernel和rootfs烧录
  2. 架构师之前,请先进阶,不要只会 Spring
  3. 邀请参加活动的邀请函_圣诞节点灯仪式活动邀请函制作
  4. Java黑皮书课后题第5章:*5.50(对大写字母计数)编写一个程序,提示用户输入一个字符串,然后显示该字符串中大写字母的数目
  5. 《标准普通话教程》中对平舌音的发音方法的说明
  6. php 0和字符串比较为真
  7. 性能测试搭建Jmeter分布式压测与监控
  8. GeoServer设置栅格影像的发布样式
  9. iOS弹幕库OCBarrage-如何hold住每秒5000条巨量弹幕
  10. python高斯求和函数_选择积分方法—高斯积分
  11. docker视频教程下载
  12. 计算机二级 Excel常用函数公式总结
  13. Halcon 回形针方向计算
  14. 协方差矩阵与PCA原理深入剖析
  15. 戴尔G3 Ubuntu18.04双系统安装
  16. xlsx格式转csv
  17. 机器学习概要(MACHINE LEARNING SUMMARY)
  18. originPro导出图像的关键设置
  19. 【HDU 2612 Find a Way(BFS)】(兼BFS入门笔记)
  20. 【技能向--之一】EDA探索性数据分析--以kaggle美国信用卡评分项目为例

热门文章

  1. Axure 进阶 | 制作携程网酒店“入住日期”与“退房日期”控件
  2. NLP | 自然语言处理经典seq2seq网络BERT详解及代码
  3. 2的24次方等于多少MB?(附计算过程)
  4. keep-alive的作用是什么? 使用它的目的是什么?
  5. 玩转NVIDIA Jetson AGX Xavier(1)--- jetson是什么
  6. 非华为电脑多屏协同安装最新的电脑管家
  7. 并行数据转换为串行数据的转换器
  8. Android 8.1 DisplayPowerController(四) 自动调节亮度(1)——流程
  9. MTK平台 SIM双卡改成单卡修改
  10. Unity UGUI中的rebatch和rebuild理解