我们上一讲已经学习了request的用法。
现在我们需要来处理得到的HTML信息。 本章节我们使用BeautifulSoup。漂亮的汤
耗时约15min,建议实操。
使用的网站延续前一讲。
这一小节我们的任务是得到网站上的基础信息,比如作者等。
- 系列文章目录
- 前言
- 一、BeautifulSoup是什么?
- 二、使用步骤
- 1.使用HTML数据构建soup
- 2.soup.find('tagName')
- 3.soup.find_all()
- 三、实操
- 目标分析
- 定位目标
- 字符串提取
- 四、总结
HTML的本质还是文本。那么对于python而言就是字符串。
所以从网页中提取信息,就变成了从字符串中提取子字符串。
但是又有什么不同呢?
-
HTML的文本并不是线性的,而是树形的(DOM树)。
-
HTML有很多标签属性等,这些和目标信息强相关。
所以提取子字符串有其特定的方法
beautifulsoup4库,也称为Beautiful Soup库或者bs4库,用于解析和处理HTML和XML。 名字有那么点恶趣味,但是功能还是很强大的。
pip install beautifulsoup4
import bs4
print bs4
# 最经常
from bs4 import BeautifulSoup
二、使用步骤
1.使用HTML数据构建soup
代码如下(示例):
soup = BeautifulSoup(html_text, 'html.parser')
print(soup.p.string) # 第一段的字符串内容
# 作 者:圣骑士的传说
这里用.去索引信息,是比较简单的情形,所以有缩写。。。 但是真正主力的是接下来的两个工具。
2.soup.find(‘tagName’):param name: A filter on tag name. 一般就是tag
:param attrs: A dictionary of filters on attribute values. 用于限定的属性
:param recursive: If this is True, find() will perform a
recursive search of this PageElement's children. Otherwise, only the direct children will be considered.
:param limit: Stop looking after finding this many results. :kwargs: A dictionary of filters on attribute values.
:return: A PageElement.
:rtype: bs4.element.Tag | bs4.element.NavigableString
注意: 1. find的返回结果也是soup类型,所以可以迭代,一步步逼近目标。 2. recursive默认是FALSE,防止抓取到过多的信息。除非没什么干扰项 3. find只会返回自上而下找到的第一个。
3.soup.find_all()爬虫大部分情况是在信息比较丰富的网页上批量的爬取数据。 所以find有很大的局限性。这个时候就需要find_all
和上面的find基本一致,除了返回的是一个列表之外。。。 见下面实操。
三、实操为了避免反复爬取所以我们保存到文件中。
html_text = rep.text.encode('iso-8859-1').decode('gbk')
with open("shouye.txt","w",encoding="gbk") as outfile:
outfile.write(html_text)
with open("shouye.txt","r",encoding="gbk") as infile:
html_text=infile.read()
然后注释掉爬取的部分。
修真聊天群
作 者:圣骑士的传说
状 态:连载
动 作:直达底部 加入书架
最后更新:2020-08-10 11:24:43
最新章节:新书上传啦,《万界点名册》
定位目标
工具是有限的,但是组合是无限的
定位的目的是为了快速的实现唯一性。
笔趣阁 > 修真聊天群最新章节
修真聊天群
作 者:圣骑士的传说
状 态:连载
动 作:直达底部 加入书架
最后更新:2020-08-10 11:24:43
最新章节:新书上传啦,《万界点名册》
根据观察。我们id属性为book的div是唯一的。所以我们可以从这里开始。  代表空格键,转义了而已。
实际上可以更进一步从这里开始。甚至可以直接用id。但是为了展示一下层层递进的定位方式。。。 没有困难,就要创造困难!!!
print(soup.find("div",attrs={"id":"book"}).find("div",attrs={"id":"info"})) # 递进的写法
print(soup.find_all("div",attrs={"id":"info"})) # 直接的写法
# find_all的结果 find的结果没有列表!!!
[
修真聊天群
作 者:圣骑士的传说
状 态:连载
动 作:直达底部 加入书架
最后更新:2020-08-10 11:24:43
最新章节:新书上传啦,《万界点名册》
]
我想说的是find返回的还是soup可以一直在后面追加,就像从树的根节点到叶结点的过程。每一次find都相当于路径
显然这个路径是可以跳步的。只要思路好!!!
接下来更进一步!
字符串提取如何将作者打印出来?
我们以作者为例
content = soup.find("div",attrs={"id":"book"}).find("div",attrs={"id":"info"}).find('p').string
print(content.split(":")) # 注意这个冒号
author = re.findall(r"作\xa0\xa0\xa0\xa0者:(.*)",content)[0]
print(author)
# 结果
['作\xa0\xa0\xa0\xa0者', '圣骑士的传说']
['圣骑士的传说']
还是很容易写错的。比如中间的空格符因为编码不一样所以可能匹配不到。 作 者,中间四个加空格就不行。 还有冒号也有中英文的区别。
\xa0 是不间断空白符 我们通常所用的空格是 \x20 ,是在标准ASCII可见字符 0x20~0x7e 范围内。 而 \xa0 属于 latin1 (ISO/IEC_8859-1)中的扩展字符集字符,代表空白符nbsp(non-breaking space)
' '.join(v.split())# 是用这个去转化然后处理,相当于换成了一般的空格。
四、总结
剩下的几个信息,大同小异,我相信留给诸位并不是很难。(用find_all)
还记得一开始,保存HTML到文件,然后用记事本打开吗?
用记事本打开的小伙伴基本是要翻车的。。。没错,我在误导你,就是这么邪恶。
记事本往往不会很好的显示格式或者空字符等等。但是这对我们定位信息是大忌。
推荐使用notepad++。 小而美的软件值得拥有。 链接:https://pan.baidu.com/s/19xovb6z086ycmbB_zc4siw 提取码:fmg5
仅仅这一个实例是不够的。 下一讲,是关于章节标题的爬取以及处理。