欢迎光临散文网 会员登陆 & 注册

我爬自己or我自己爬——记录在B站专栏上的一次Python爬虫应用

2022-07-15 21:35 作者:火焰大喷菇  | 我要投稿

一、问题描述

    获取我自己写的n篇UnderMine专栏中的166件圣物数据将它们的效果、简评、评分按编号顺序录入已有的excel表格中,作为UM圣物查询软件的数据库。其中效果和简评需要保留html代码并修改成软件可渲染的html格式。

关键词:python  爬虫/web crawler  BeautifulSoup4

二、思路分析

2.1 获取专栏中的166件圣物数据

方法一:最朴素的思想——复制粘贴

如果这个方法能简单解决问题,我也不会写这篇专栏了......

首先,很遗憾,直接复制粘贴并不能达到我期望的效果。因为我想要html代码的数据,这样在查询软件中也能渲染出加粗、颜色等文字效果。如果用F12+复制指定元素,需要我手动执行166*3次,人都点麻了。

其次,专栏内容的圣物不是完全按编号升序排列的,需要手动填入表格的对应编号行,费眼睛。可以输入单元格号来快速定位,但还是好麻烦。

方法二:网络爬虫

网络爬虫,是一种按照既定规则自动抓取网络数据或执行网络请求的程序,比较适合完成此类任务。之前浅学过一段时间,现在拿出来实际运用一下。

选用的策略是:获取html文档,喂给BeautifulSoup4(简称bs4)来解析,然后抽出想要的信息。重点就在于如何抽取所需信息——需要找出这些信息的特征,才能让bs4定位到信息所在标签tag,取出内容。

2.1.1 获取html文档

我所要的信息分布在10篇专栏中,访问它们的关键就在于CV号。

共10篇圣物专栏,还有一篇在上边,没截全

还好我有做过一篇目录专栏,通过它可以很方便地获取(爬a标签)到这些CV号。

使用requests库向发送html get请求后,10篇专栏的HTML文档就到手了!

2.1.2 使用bs4来解析html文档

Beautiful Soup是一个可以从HTML或XML文件中提取数据的Python库,它能够通过你喜欢的转换器实现惯用的文档导航,查找,修改文档的方式。

——BS4官方文档

bs4的"prettify()"文档树格式化效果与谷歌浏览器的"检查"效果类似

接下来是为之后bs4定位“效果”“简评”“评分”tag做准备,先使用浏览器的“检查(inspect)”功能来查看各圣物专栏的tag特征。

文章内容部分的tag

首先,在检查后发现,专栏的内容部分在id=read-article-holder的div标签中,初步缩小了搜索范围。

编号、效果、简评、评分tag的结构

其次,可以发现在div标签下含了无数的没有id的同级p标签。

由上图可见,编号,简评,评分都在p标签里,而周围都是同级的p标签,所以无法通过标签名、只能以标签内容来定位

效果的内容都在ul列表标签内,专栏内使用此标签的也只有效果部分,可以作为标志来定位。

2.1.3 抽取信息

  • 获取编号

    只需要保留数字。对p标签内容使用正则表达式取数字或者用字符串split函数取第二段

  • 获取效果

    需要保留html代码。获取整个ul标签后使其变为字符串存储

  • 获取简评

    需要保留html代码。从简评标签之后到评分标签之前,获取连续的n个p标签后使其变为字符串存储

  • 获取评分

    需要保留普通字符串。获取去除“评分”和“空字符”后p标签内容。

2.2 效果、简评、评分按序录入已有excel

已有excel展示
  • 根据表头定位效果、评论和分数列号

    • 如果是xls文件需要xlrd、xlwt库进行读写、xlutils库允许在原表格上追加修改

    • 如果是xlsx文件只需要openpyxl库即可完成读写和修改

  • 根据编号定位行号。按行列定位单元格,依次输入对应圣物的效果、简评、评分内容

三、代码实现

2.0.0 导入包和模块

2.1.1 获取html文档

2.1.2 使用bs4来解析html文档

2.1.3~2.2 抽取信息+效果、简评、评分按序录入已有excel

2.3 测试代码

四、结果展示

第一次运行控制台结果
第二次运行控制台结果
项目的工作路径文件展示
excel内容展示
百科界面展示

五、实验反思

5.1 代码改进

以上代码似乎缺少了些面向对象的思想,这组功能围绕CV号、HTML文件和BS结构树展开,显然可以编成类,以进一步简化代码:

测试代码:

5.2 未来可能的改进

  1. 设置私有、只读属性/方法,保证数据安全。

  2. 增加容错处理,如HTML文档爬取失败的情况,调用后续函数需要检查是否初始化成功。

  3. 改进筛选函数,部分find_all可能多爬/少爬某些格式的信息,随着未来专栏的增多,可能会出现不可预期的错误,需要定期检查以及设置一些查看爬取信息的方法。

5.3 已解决的疑问

一开始,我的评分过滤器是从解析顺序着手的,用了BS遍历文档树-回退和前进的.next/previous_element方法:

但对第一篇专栏的提取数据却不符合预期:

应该只有20个评分标签,多了不少无关标签

于是我尝试查看这些无关标签满足筛选条件的原因:

显示解析上一步的标签名,和解析下一步的寻找"评分"结果

问题得以迎刃而解:

  • 字符串的find方法结果出现了None!而不是-1,所以通过了检测。原因是解析的结果不一定是字符串也有可能是tag,find方法接收到了非str类型的数据,返回了None

  • "评分标准"字符串的开头的确是评分二字,但不含有圣物信息,所以需要额外增加筛选条件,把此类信息滤掉

正确地筛选到了数据

后来又改用get_text方法获取tag中包含的所有文本内容,还能去除tag间多余的空格,好用!

六、笔记总结

6.1 BeautifulSoup常用方法总结

6.1.1 筛选出指定条件的tag

find_all()方法

功能:搜索当前tag的所有子孙节点,并筛选出所有符合条件的tag,返回值为列表

语法:tag或BeautifulSoup对象.find_all(name, attrs, recursive, string, **kwargs)

简写可以省略掉.find_all

参数

  • name,表示tag名称,可以是字符串/正则表达式/列表/方法/True

  • attrs,表示特殊属性的tag,字典类型(本文没用到)

  • recursive,表示是否检索当前tag的所有子孙节点,布尔类型,默认为True,False表示只搜索tag的直接子节点

  • string,表示搜索字符串内容,可以是字符串/正则表达式/列表/方法/True

  • **kwargs,表示一堆关键字参数。其中,limit表示返回结果的最大数量,int类型;class_表示按照CSS类名搜索tag,可以是过滤器/字符串/正则表达式/方法/True;其他参数名表示搜索指定名字的属性,可以是字符串/正则表达式/列表/True

相似方法find()方法,是find_all()方法的单数版本,有相同的形参,返回首个符合条件的tag


find_previous()方法

功能:搜索当前节点前符合条件的首个tag或字符串

语法:tag.find_previous(name, attrs, recursive, string, **kwargs)

参数:参考find_all()方法

相似方法find_all_previous()方法,是find_previous()方法的复数版本,返回当前节点前所有符合条件的tag或字符串;而find_next(),find_all_next()是搜索当前节点后。它们都有相同的形参。


find_next_sibling()方法

功能:搜索当前节点后的所有兄弟节点,返回首个符合条件的tag

语法:tag或BeautifulSoup.find_next_sibling(name, attrs, recursive, string, **kwargs)

参数:参考find_all()方法

相似方法find_next_siblings()方法,是find_next_sibling()方法的复数版本;而find_previous_sibling(),find_previous_siblings()是搜索当前节点前。它们都有相同的形参。

6.1.2 得到tag内的字符串

string方法

功能:对于仅含一段文本的tag或只有一个子标签且文本只出现在子标签间的tag,返回这段文本字符串

语法:tag.string

注意tag包含多个子节点时,tag.string无法确定调用哪个子节点的内容,返回None

相似方法strings方法,对于包含多个文本字符串的tag,返回一个包含所有文本字符串的生成器,可以使用for循环来获取其中的内容;stripped_strings方法,是去除空格、空行的strings版本。它们都不需要形参。


get_text()方法

功能获取tag所含所有文本内容,包括子孙tag中的内容,返回合并后的Unicode字符串

语法:tag或BeautifulSoup对象.get_text(sep, strip=True)

参数

  • sep表示相邻文本内容的分隔符,str类型

  • strip表示是否去除文本内容前后的空白符,布尔类型,True则去除


七、参考资料

1. BS4官方说明文档-中文版

https://beautifulsoup.readthedocs.io/zh_CN/v4.4.0/

2. xlsx文件的读写(openpyxl库的使用)

https://blog.csdn.net/liuyingying0418/article/details/101066630

3. xls文件的读写(xlrd/xlwt/xlutils库的使用)

https://cooc.cqmu.edu.cn/Course/KnowledgePoint/9389.aspx

4. 正则表达式的用法(re模块的使用)

https://www.cnblogs.com/huxi/archive/2010/07/04/1771073.html

5. BS4中string和text的区别

https://www.cnblogs.com/kaibindirver/p/11374669.html

我爬自己or我自己爬——记录在B站专栏上的一次Python爬虫应用的评论 (共 条)

分享到微博请遵守国家法律