您的位置:首页 > 理论基础 > 计算机网络

Python网络爬虫与信息提取-Day9-信息标记与提取方法

2017-09-07 19:56 585 查看
一、信息标记的三种形式
我们需要对信息进行表记,使得我们能够理解信息所反馈的真实含义。

标记后的信息可形成信息组织结构,增加了信息维度

标记的结构与信息一样具有重要价值

标记后的信息可用于通信、存储或展示

标记后的信息更利于程序理解和运用,也利于人对信息的深入理解与运用

HTML的信息标记

HTML是WWW(World Wide Web)的信息组织方式

它能够将声音、图像、视频等超文本信息嵌入到文本中

HTML通过预定义的<>…</>标签形式组织不同类型的信息

 

现在国际公认的信息标记格式有三种,分别是XML,JSON和YAML

 

XML(eXtensible Markup Language)叫做扩展标记语言,它是一种与HTML很接近的标记语言。它以标签(Tag)为主来标记信息

<img src=“china.jpg” size=“10”> … </img>

它有名称 Name和属性Attribute

如果标签中没有内容,我们可以用相关的缩写形式,用一个尖括号来表示一个标签。

<img src=“china.jpg” size=“10” />空元素的缩写形式

在XML中也可以嵌入注释,它以<!开头,并且以>结尾

<!‐‐ This is a comment, very useful ‐‐>注释书写形式

可以说XML是HTML发展以来的一种通用的信息标记格式

 

JSON(JavsScript Object Notation),它是JavaScript语言中面向对象的一种语言形式,简单讲JSON是一种有类型的键值对构建的信息表达方式。键值对是key:value的一个组合,也就是给出一个信息,并且对信息内容做一个定义。其中对信息类型的定义叫“键”,对信息值的描述叫value。

要注意,无论是键还是值,它都通过增加双引号来表示它是字符串。说明它是一个有数据类型的键值对。

如果一个键对应多个值的时候,我们使用方括号加逗号[,]的形式来组织

键值对可以嵌套使用,也就是一个键值对放在另一个键值对的值的部分,在嵌套使用时,我们用大括号来表示

总结:JSON用有类型的键值把信息组织起来

“key” : “value”

“key” : [“value1”, “value2”]

“key” : {“subkey” : “subvalue”}

JSON语言使用有类型的键值对,一个很大好处就是对于JavaScript等编程语言来说可以直接将JSON格式变为程序的一部分,使得编写程序大大地简化

 

YAML(YAML Ain’t Markup Language),它在命名的时候使用一种递归的定义。它也使用键值对,不过是无类型键值对key:value。可以用缩进来表达所属的关系,用减号表达并列关系,用竖线表达整块数据,用#表示注释

key : value

key : #Comment

‐value1

‐value2

key :

subkey : subvalue

 

三种信息标记形式的比较

XML实例:

<person&g
4000
t;

<firstName>Tian</firstName>

<lastName>Song</lastName>

<address>

<streetAddr>中关村南大街5号</streetAddr>

<city>北京市</city>

<zipcode>100081</zipcode>

</address>

<prof>Computer System</prof><prof>Security</prof>

</person>

每一个信息域定义相关的标签,并且用嵌套的形式组织起来

在整个文本中,有效信息所占的比例并不高,大多数信息被标签占用

 

JSON实例:

{

“firstName” :“Tian” ,

“lastName” :“Song” ,

“address”  : {

“streetAddr” :“中关村南大街5号” ,

“city”  :“北京市” ,

“zipcode”  :“100081”

} ,

“prof”  : [ “Computer System” ,“Security” ]

}

JSON使用键值对的形式组织信息,但是无论标签还是后面的值,键值都要用双引号来表达它们的类型

 

YAML实例:

firstName : Tian

lastName : Song

address  :

streetAddr : 中关村南大街5号

city  : 北京市

zipcode : 100081

prof  :

‐Computer System

‐Security

用无类型的键值对来表示,很简洁的关联

 

XML:最早的通用信息标记语言,可扩展性好,但繁琐

JSON:信息有类型,适合程序处理(js),较XML简洁

YAML:信息无类型,文本信息比例最高,可读性好

 

实际使用中:

XML:Internet上的信息交互与传递

JSON:移动应用云端和节点的信息通信,无注释

YAML:各类系统的配置文件,有注释易读

 

二、信息提取的一般方式

信息提取指,从标记后的信息中提取所关注的内容。之前的XML,JSON,YAML的三种形式,无论哪种形式,在信息提取中,包含标记,和信息两部分,我们关心的是所要提取出的内容

 

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

用标记解析器去解析XML JSON YAML格式,然后将其中所需要的信息提取出来

例如:bs4库的标签树遍历

优点:信息解析准确

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

·方法二:无视标记形式,直接搜索关键信息

对信息的文本查找函数即可

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

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

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

XML JSON YAML 搜索

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

 

实例:

提取HTML中所有URL链接

思路: 1) 搜索到所有<a>标签

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

import requests
r = requests.get("http://python123.io/ws/demo.html")
demo = r.text

from bs4 import BeautifulSoup
soup = BeautifulSoup(demo,"html.parser")
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内容查找方法

import requests
r = requests.get(“http://python123.io/ws/demo.html”)
demo = r.text


<>.find_all(name, attrs, recursive, string, **kwargs)

find_all方法可以在soup的变量中查找里面的信息

它能够返回一个列表类型,存储查找的结果

第一个参数name:对标签名称的检索字符串

 

from bs4 import BeautifulSoup
soup = BeautifulSoup(demo,"html.parser")
print(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,则用一个方括号

print(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>]

 

如果给出的标签名称是True,则显示当前标签的所有信息

for tag in soup.find_all(True):
print(tag.name)


html

head

title

body

p

b

p

a

a

我们看到这个文档中的所有标签名称被打印了出来

 

希望只显示其中以b开头的标签,包括b和body标签,就需要使用一个新的第三方库,叫做“正则表达式库”

首先引入这个库

正则表达式反馈的结果是以b开头的所有表达的信息

import re
for tag in soup.find_all(re.compile('b')):
print(tag.name)


body

b

 

attrs: 对标签属性值的检索字符串,可标注属性检索

我们查找p标签中中包含course字符串的信息

print(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>]

 

我们也可以对属性值作约定

print(soup.find_all(id='link1'))


[<a class="py1" href="http://www.icourse163.org/course/BIT-268001" id="link1">Basic Python</a>]

 

print(soup.find_all(id='link'))


[]

所以我们对属性赋值要做精确的赋值

 

如果我们需要查找包含link的属性,我们就需要引入正则表达式库

print(soup.find_all(id=re.compile('link')))


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

 

正则表达式就像平常搜索一样搜索词的一部分,如果不使用正则表达式就需要完整准确地给出词的信息,不多也不少

 

recursive: 是否对子孙全部检索,默认True

如果我们只需要搜索儿子这一层面的信息,我们就把recursive设为False

print(soup.find_all('a',recursive=False))


[]

 

 

string: <>…</>中字符串区域的检索字符串

print(soup.find_all(string='Basic Python'))


['Basic Python']

 

print(soup.find_all(string=re.compile('python')))


['This is a python demo page', 'The demo python introduces several python courses.']

 

<tag>(..) 等价于
<tag>.find_all(..)

soup(..)  等价于
soup.find_all(..)

 

拓展方法

方法

说明

<>.find()

搜索且只返回一个结果,同.find_all()参数

<>.find_parents()

在先辈节点中搜索,返回列表类型,同.find_all()参数

<>.find_parent()

在先辈节点中返回一个结果,同.find()参数

<>.find_next_siblings()

在后续平行节点中搜索,返回列表类型,同.find_all()参数

<>.find_next_sibling()

在后续平行节点中返回一个结果,同.find()参数

<>.find_previous_siblings()

在前序平行节点中搜索,返回列表类型,同.find_all()参数

<>.find_previous_sibling()

在前序平行节点中返回一个结果,同.find()参数

 

区别仅在于查找区域的不同以及检索返回的结果个数不同
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  python 网络爬虫