crawler-07 信息标记与提取方法

crawler-07 信息标记与提取方法

一、信息标记

  信息标记,有利于程序对信息的读取,也有利于人对信息的理解。

UTOOLS1576467057971.png

二、信息标记的三种形式

1、XML

  扩展标记语言,eXtensibleMarkup Language,采取以标签为主来构建信息、表达信息的形式。先有了HTML,后有XML,二者很相像。

1
2
3
4
5
#空元素的缩写形式
<imgsrc=“china.jpg” size=“10” />

#注释书写形式
<!‐‐Thisisacomment, very useful ‐‐>

实例

1
2
3
4
5
6
7
8
9
10
<person> 
<firstName>Tian</firstName>
<lastName>Song</lastName>
<address>
<streetAddr>中关村南大街5号</streetAddr>
<city>北京市</city>
<zipcode>100081</zipcode>
</address>
<prof>Computer System</prof><prof>Security</prof>
</person>

2、JSON

  javaScript中,面向对象的信息表达形式,JavsScript Object Notation,使用有类型的键值对 key:value

1
2
3
4
5
6
7
8
9
10
11
#键值对嵌套用{,}
“name” :{
“newName” :“北京理工大学”,
“oldName” : “延安自然科学院” 
}

#若value含有多个信息,用方括号[]
#若需要嵌套键值对,用花括号{}
“key” :“value”
“key” :[“value1”,“value2”]
“key” : {“subkey”:“subvalue”}

实例

1
2
3
4
5
6
7
8
9
{
“firstName” :“Tian”,
“lastName” :“Song”,
“address” : {
“streetAddr” :“中关村南大街5号”,
“city” :“北京市”,
“zipcode” :“100081” } ,
“prof” :[  “Computer System” ,“Security” ]
}

3、YAML

  YAML不是一个标记语言,YAML Ain’t Markup Language,使用无类型键值对 key:value,对缩进有严格要求。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#以缩进表达所属关系
name:
newName:北京理工大学
oldName:延安自然科学院

#用符号 ‐ 表达并列关系
name:
‐北京理工大学
‐延安自然科学院

#用符号 | 表达整块数据,用符号 # 表示注释
text: | #学校介绍
这里是一大段内容这里是一大段内容这里是一大段内容这里是一大段内容
这里是一大段内容这里是一大段内容这里是一大段内容这里是一大段内容

实例

1
2
3
4
5
6
7
8
9
firstName:Tian 
lastName:Song
address:
streetAddr:中关村南大街5号
city :北京市
zipcode:100081
prof:
‐Computer System
‐Security

4、对比

1)XML :最早的通用信息标记语言,可扩展性好,但繁琐(标签太多);用于Internet上的信息交互与传递;

2)JSON:信息有类型,适合程序处理(js),较XML简洁;用于移动应用云端和节点的信息通信,即程序对接口处理的地方,作为程序的一部分,但是无注释;

3)YAML:信息无类型,文本信息比例最高(最简洁),可读性好;用于各类系统的配置文件,有注释易读;

三、信息提取

1、方法一:完整解析信息的标记形式,再提取关键信息

1)需要标记解析器,例如:bs4库的标签树遍历;

2)优点:信息解析准确;

3)缺点:提取过程繁琐,速度慢;

2、方法二:无视标记形式,直接搜索关键信息
1)对信息的文本查找函数即可;

2)优点:提取过程简洁,速度较快;

3)缺点:提取结果准确性与信息内容相关;

3、融合方法:结合形式解析与搜索方法,提取关键信息

1)需要标记解析器及文本查找函数;

2)比前两种方法好;

3)实例:提取HTML中所有URL链接

思路:

  1) 搜索到所有 a 标签;

  2)解析 a 标签格式,提取href后的链接内容;

1
2
3
4
5
6
7
>>> for link in soup.find_all('a'):
print(link.get('href'))


http://www.icourse163.org/course/BIT-268001
http://www.icourse163.org/course/BIT-1001870001
>>>

四、基于bs4库的HTML内容查找方法

1、find_all() 方法

1)第一个参数:对标签名称的检索

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#查找a标签,返回的列表类型包含了所有a标签
>>> soup.find_all('a')
[<a class="py1" href="http://www.icourse163.org/course/BIT-268001" id="link1">Basic Python</a>, <a class="py2" href="http://www.icourse163.org/course/BIT-1001870001" id="link2">Advanced Python</a>]

#同时查找a标签和b标签,
>>> soup.find_all(['a','b'])
[<b>The demo python introduces several python courses.</b>, <a class="py1" href="http://www.icourse163.org/course/BIT-268001" id="link1">Basic Python</a>, <a class="py2" href="http://www.icourse163.org/course/BIT-1001870001" id="link2">Advanced Python</a>]
>>>

#打印文档中所有标签的名称
>>> for tag in soup.find_all(True):
print(tag.name)

html
head
title
body
p
b
p
a
a
>>>


#只显示以b开头的标签,例如b标签、body标签等,用正则表达式即可
>>> import re
>>> for tag in soup.find_all(re.compile('b')):
print(tag.name)


body
b
>>>

2)第二个参数:对标签属性值的检索字符串,可标注属性检索

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#查找p标签中,包含course字符串的信息
>>> soup.find_all('p','course')
[<p class="course">Python is a wonderful general-purpose programming language. You can learn Python from novice to professional by tracking the following courses:

<a class="py1" href="http://www.icourse163.org/course/BIT-268001" id="link1">Basic Python</a> and <a class="py2" href="http://www.icourse163.org/course/BIT-1001870001" id="link2">Advanced Python</a>.</p>]
>>>

#直接以属性值为根据,查找目标内容
#查找id=link1的元素
>>> soup.find_all(id='link1')
[<a class="py1" href="http://www.icourse163.org/course/BIT-268001" id="link1">Basic Python</a>]
>>>
#精确赋值信息才能找到,否则不能
>>> soup.find_all(id='link')
[]
>>>

#加上正则表达式,可以模糊查找
>>> import re
>>> soup.find_all(id=re.compile('link'))
[<a class="py1" href="http://www.icourse163.org/course/BIT-268001" id="link1">Basic Python</a>, <a class="py2" href="http://www.icourse163.org/course/BIT-1001870001" id="link2">Advanced Python</a>]
>>>

3)第三个参数:是否对子孙全部检索,默认True

1
2
3
4
5
6
7
8
#如下,说明soup根标签下的子孙节点里有a标签
>>> soup.find_all('a')
[<a class="py1" href="http://www.icourse163.org/course/BIT-268001" id="link1">Basic Python</a>, <a class="py2" href="http://www.icourse163.org/course/BIT-1001870001" id="link2">Advanced Python</a>]

#如下,说明soup根标签下的儿子节点里没有a标签
>>> soup.find_all('a',recursive=False)
[]
>>>

4)第四个参数:对标签中字符串区域的检索字符串

1
2
3
4
5
6
7
8
9
#精确查找
>>> soup.find_all(string='Basic Python')
['Basic Python']

#模糊查找
>>> import re
>>> soup.find_all(string=re.compile('Python'))
['Python is a wonderful general-purpose programming language. You can learn Python from novice to professional by tracking the following courses:\r\n', 'Basic Python', 'Advanced Python']
>>>

5)总结:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<>.find_all(name,attrs,recursive, string, **kwargs)
∙name : 对标签名称的检索字符串
∙attrs: 对标签属性值的检索字符串,可标注属性检索
∙recursive: 是否对子孙全部检索,默认True
∙string: <>…</>中字符串区域的检索字符串

#由于find_all函数太常用了,这里就有了其简写
<tag>(..) 等价于<tag>.find_all(..)
soup(..) 等价于soup.find_all(..)

#例如:
>>> soup(string='Basic Python')
['Basic Python']
>>>

2、扩展方法

UTOOLS1576467100574.png

欢迎打赏,谢谢
------ 本文结束------
0%