内容简介
本篇文章主要围绕HTML基本结构框架和正则表达式基础内容进行讲解,后期将会详细对HTML结构框架进行介绍,由于本篇博客主题是爬虫,简单的普及一下HTML的基础知识。
HTML基本结构框架
由于考虑到为大家讲解知识点比较枯燥,因此在讲解HTML基本结构框架的时候将会结合医院的网页结构进行讲解
图1
根据第一张图,了解整体的框架结果,在<div class="mw-parser-output"></div>标签下,包含着需要爬取的所有信息
可以看到<ul></ul>这个标签中包含很多<li></li>标签,在图中已经说明这两个标签的含义
图2
现在再来看打开<li></li>标签以后,在<li>标签中包含什么
可以在图中看到含有<b>和<ul>标签 在<b>标签中存放的是医院的名称
在<li>标签中存放的是医院中的详细信息
图3
分别打开图2中的<b>和<ul>标签,可以发现<b>标签对应是这个医院的URL和医院名称
<ul>标签对应的是许多<li>标签,这个<li>标签就是分别代表了:医院地址、联系电话、医院等级等医院信息。
相信大家在这里并不是很难理解
需要注意一点的就是在医院地址、联系电话和医院等级这些医院信息的<li>标签中,心细的小伙伴可以发现在<li>标签中含有<b>标签
<li>
<b>医院地址</b>
:北京市东城区帅府园1号(东院)/西城区大木仓胡同41号(西院)
</li>
这里是爬取医院信息的核心,为了方便大家理解,用两种方式进行讲解
1、学过python的小伙伴应该会知道字典吧(没学过的可以直接看第二种方式),字典是由键值对构成的,这里的<b>医院地址</b>可以看做键, :北京市东城区帅府园1号(东院)/西城区大木仓胡同41号(西院)可以看做值 在数据爬取的时候,可以理解成键值对的方式进行爬取
2、Excel大家都知道吧,<b>医院地址</b>可以看做表头,:北京市东城区帅府园1号(东院)/西城区大木仓胡同41号(西院)可以看该表头下的信息 举个例子说,有一个Excel表格,A列的表头是姓名,下面对应的信息:张三、李四、王五等等
大家可以看到在数据进行保存的时候,就是按照Excel表格的形式进行保存的
到这里,相信大家对于HTML的基本结构框架已经有一个初步的了解
正则表达式
什么是正则表达式?
正则表达式是一种用于匹配和查找文本模式的工具。 是由一系列字符和特殊符号组成的字符串,可以用来描述、识别和提取符号某种模式的文本数据。
正则表达式的语法相对复杂,但一旦掌握,就可以成为处理文本数据的强大工具
当时我进行这项工作时,系统的学习过正则表达式,但是过一段时间以后不用,就会遗忘,在我看来爬虫时,只需要牢记正则表达式几个常用的元字符即可
为了方便大家更好的去理解正则表达式,我将会依据代码带着大家着步了解代码中的正则表达式
pattern = r'<li><b><a href=".+?" title=".+?">(.+?)</b>\s*<ul>' \
r'<li><b>医院地址</b>:(.+?)</li>\s*' \
r'(<li><b>联系电话</b>:(.+?)</li>)?\s*' \
r'(<li><b>医院等级</b>:(.+?)</li>)?\s*' \
r'(<li><b>重点科室</b>:(.+?)</li>)?\s*' \
r'(<li><b>经营方式</b>:(.+?)</li>)?\s*' \
r'(<li><b>传真号码</b>:(.+?)</li>)?\s*' \
r'(<li><b>电子邮箱</b>:(.+?)</li>)?'
以上这个代码就是正则表达式获取信息的全部代码,下面将会对每行代码进行分析:
第一行
pattern = r'<li><b><a href=".+?" title=".+?">(.+?)</b>\s*<ul>' \
大家首先来看这里的pattern,这个大家可以理解成正则表达式的一种方法(可以理解为一个模版,当引用这个模版的时候,就会从大量的信息中提取有用的信息) 所有绿色的代码都被赋值给pattern这个变量 (除了最后一行代码以外,其余行的代码都有 \ 进行一个换行的操作)
现在就开始代码进行详细的介绍
正则表达式是依据与HTML标签进行提取信息的:
<li><b><a href=".+?" title=".+?">(.+?(?<!<a))</b>\s*<ul>
这里的<li>标签就是该医院下的所有信息,<b>标签是这个医院的一个名称,大家可以看到在<b>标签中包含了一个<a>标签,这个a标签中是该医院的一个跳转超链接,<a>标签中有两个属性,分别是是href和title属性,<a href=".+?" title=".+?">,在这两个属性的后方都有.+?,这个正则表达式的名称是非贪婪模式匹配符(尽可能的少匹配字符)
举个例子方便理解非贪婪
在字符串 "abcabc" 中使用正则表达式 ".+?b",它将匹配 "ab" 而不是整个字符串。
那么在咱们代码中所需要提取的信息,并不包括href和title属性 大家就会想如果<a href=".+?" title=".+?">这样写的话,这两个属性信息是不是就被提取出来了? 答案是不是的,在正则表达式中,需要使用 () 对正则表达式进行一个包裹,也就是说如果是(.+?)就可以将属性给提取出来了
() 这个符号在正则表达式中称为捕获组,简单理解就是,所有需要爬取出来的信息,都需要在正则表达式的最外层加上一个捕获组 ()
还有小伙伴就想了,既然我不提取医院链接和title这个属性,我是不是可以将<a href=".+?" title=".+?">这一块代码进行删除?答案是不可以的,因为正则表达式是一个遍历的过程,如果删除这一段代码以后,那么就会自动将这一段文字全部提取出来。也就是说正则表达式是一个将无用信息使用正则表达式删除,将有用信息进行一个提取的一个过程。
下面将为大家讲解第一行代码的后半段
(.+?)</b>\s*<ul> 这一块代码依旧是结合HTML代码进行理解,在</b>之前就是对医院名称进行一个提取了 也就是下方标红的这一块代码
(.+?)这一块代码是对:北京协和医院</a>(协和医院) 这一块信息进行的一个提取 (这里需要注意一点,(.+?)这个捕获组中,捕获了</a>这一块信息,在将所有信息全部提取来以后,再将这个</a>进行删除,后续代码中有介绍)
\s*的作用是允许匹配可能存在的空白字符,如空格、制表符、换行符等。 在上图中,可以看到在(协和医院)的末尾可以发现会有很多空白字符,因此,\s*是来匹配这些空白字符的
在第一行代码的末尾有<ul>标识着对下方医院的具体信息,进行识别开始
第二行
r'<li><b>医院地址</b>:(.+?)</li>\s*' \
在第一行代码的末尾有<ul>说明对该医院的详细信息,开始进行爬取
每一个<li>都代表着 医院各种信息 li标签的下属b标签代表着某一项医院信息的名称
(.+?)捕获了该医院地址的具体信息 (大家有可能会好奇为什么在捕获组前会有:,如果没有这个冒号的话,在匹配的结果中,会含有:这个标识:北京市东城区帅府园1号(东院)/西城区大木仓胡同41号(西院))因此在捕获组前加上:,在最后获取信息时就不会有这个:了
第三行
r'(<li><b>联系电话</b>:(.+?)</li>)?\s*' \
这一行代码和第二行代码相比多了一个 ()? 是由于联系电话这个医院属性,部分医院没有联系电话,因此()?代表可选项 (要注意一点就是,这个可选项是包裹在最外围的在<li>标签的最外方)
后续代码就不再一一解释了,都和第三行代码同样的道理
下期博客将会讲解完剩余的全部代码