夜曲编程学习笔记之爬虫:为何BS4模块库的使用也需要安装lxml模块库?

[!NOTE]

【夜曲编程学习笔记】此系列文章均为个人在学习夜曲编程课时对课程不理解内容的进一步理解,来源包含对AI的无限追问及官方文档的不仔细查看,可能理解不到位、不准确,且记录非常匆忙,一般当天作业后完成,但由于仍用了些心,所以放到博客作为学习记录吧!对于不正确之处,望各位帮忙指正!谢谢!❤

问题来源于群里的一位友友:为什么既要安装BS4模块库又要安装lxml模块库?

先po上作业完整代码:题目是提取一网页中的部分文字(实际这部分文字是 <em> 标签内)

# 使用import导入requests模块
import requests

# 从bs4中导入BeautifulSoup
from bs4 import BeautifulSoup

# 将URL地址赋值给变量url
url = "https://nocturne-spider.baicizhan.com/2020/08/07/1/"

# 将变量url传入requests.get(),赋值给response
response = requests.get(url)

# 将服务器响应内容转换为字符串形式,赋值给html
html = response.text

# 使用BeautifulSoup()读取html,添加lxml解析器,赋值给soup
soup = BeautifulSoup(html, "lxml")

# 使用find_all()查询soup中em的节点,赋值给content_all
content_all = soup.find_all(name="em")

# 使用print输出content_all
print(content_all)

在我学完当天课程后,也有相同的疑惑,继展开了进一步求证,以下是求证后的个人理解:

这是两个模块库,里面有两个功能,一个是BeautifulSoup,一个是lxml的解析器。我们目的是用BS4里 BeautifulSoup()函数调用lxml的解析器将HTML片段转换为DOM树(转换成 DOM树的时候其实就做了一些底层处理,如:修复html片段,将其标签完整,对节点属性、层级关系等进行了结构化封装,这样就方便我们后续通过BS的API来提取我们需要的内容)。

为什么不接用lxml库?

其实lxml就有很强大的功能,比如修复html片段,分配节点、层级关系,而且lxml基于C语言开发,所以速度更快,但是因为lxml提取的时候需要的语法更复杂些,所以我们使用BS来用更符合自然语言的语法来直接提取我们所需的内容,比如今天课程里的find_all()函数,可以直接提取所指标签 <h1>或者 <em>里的内容。

所以BS是什么?它的优势是什么?

Beautiful Soup(http://www.crummy.com/software/BeautifulSoup/) 是一个可以从HTML或XML文件中提取数据的Python库.它能够通过你喜欢的转换器实现惯用的文档导航,查找,修改文档的方式.

所以它的优势是:

  1. 可以更换多种解析器来帮助我们提取html或xml的数据。
  2. 相较于lxml库更容易上手 。

以上就是为何我们使用BS+lxml的方式来完成今天的内容的原因。

关于HTML片段和DOM树

作业中我们是通过这句话

# TODO 将服务器响应内容转换为字符串形式,赋值给html
html = response.text

把html源代码提取了部分,所以这里的html其实不是html源代码,而是html片段,是一段字符串。他是不完整的,比如它可能没有闭合的标签,如 </div></body>等。

那为啥我们不直接在 html = response.text之后直接提取我们想要的内容呢?还需要再利用BS函数转换成DOM树?soup = BeautifulSoup(html,"lxml")

其实即便是 Html源代码,也可能会是不完整的,因为毕竟是人写的,会有不闭合的情况。所以这就需要转换为 DOM树,DOM树是动态的,它有结构,显式表明了元素的父子,兄弟关系。DOM树就是当我们按F12或者右键检查时,elements里显示的像Html源代码一样的代码,但是会发现它们是可以点击展开,再点击就折叠的交互,代表这时候就已经被结构化了,就已经赋予了各元素的节点属性,帮助我们后面利用BS的API去提取我们想要的内容。

而如果我们直接去提取这段Html片段的字符串行不行呢? 可以,但是对于字符串的提取我们需要正则表达式,需要编写非常复杂的正则表达式来过滤,而且感觉很难先去固定某个范围再去提取。

新补充

更多更准确的知识可访问:BS4 中文文档