Python爬虫初级(四)—— 信息组织与提取方法

欢迎关注公众号K的笔记阅读博主更多优质学习内容
K的笔记公众号

上一篇内容:Python爬虫初级(三)—— Beautiful Soup 库入门

信息标记的三种形式

信息的标记:
标记后的信息可形成信息组织结构,增加信息维度
标记后的信息可用于通信、存储或展示
标记的结构和信息一样具有重要价值
标记后的信息更利于程序理解和运用

国际公认的信息标记的三种形式分别是 XML、JSON、YAML,下面分别介绍这三者:
XML 即 eXtensible Markup Language,采用了以标签为主来构建信息和表达信息的方式,比如:

<img src="china.jpg size="10"> ... </img>
<img src="china.jpg size="10" />
<!-- This is a comment -->

我们不难发现,XML 的形式与 HTML 几乎完全一致,可以说 XML 是通过 HTML发展而来的通用表达形式。
另一种信息标记形式是 JSON (JavaScript Object Notation),它是 JavaScript 语言中对面向对象的信息的一种表达形式,简单来讲,JSON 是由有类型的键值对构建的信息表达方式,具体形式如下:

"key1":"value1"
"key2":["value2", "value3"]
"key3":{"subkey":"subvalue"}

YAML(YAML Ain’t Markup Language) 是一种递归的定义,采用的是五类型的键值对来组织信息,和 Python 语言类似,YAML 通过缩进的方式表达所属关系比如:

name:	# 用 tab 表示所属关系
	newName : abc
	oldName : ABC

name:	# 用-表示并列关系
	-abc
	-ABC

text: |	# 用 | 表示整块数据
	简介:汉武帝刘彻(前156年7月7日—前87年3月29日),
	西汉第七位皇帝(含前后少帝),政治家、文学家。
	汉武帝在位期间(前141年—前87年),在政治上,创设中外朝制、刺史制、察举制,
	颁行推恩令,加强君主专制与中央集权。

三种信息标记形式的比较

信息标记形式特点应用情况
XML是最早的通用信息标记语言,可扩展性好,但较为繁琐Internet 上的信息交互与传递
JSON信息有类型,适合程序处理,比 XML 更简洁移动应用云端和节点的信息通信,无注释
YAML信息无类型,文本信息比例最高,可读性好各类系统的配置文件,有注释易读,应用相对较广泛

信息提取的一般方法

方法例子优点缺点
完整解析信息标记形式,再提取关键信息,需要标记解析器bs4 库的标签树遍历信息解析准确提取过程繁琐、速度慢
无视标记形式,直接搜索关键信息Word 对信息的文本查找函数提取过程简介,速度较快提取结果准确性与信息内容相关

实际上更常用的是两者结合的融合方法:即结合形式解析与搜索方法,提取关键信息,这需要标记解析器及文本查找函数。下面我们考虑实例:提取 HTML 中所有的 URL 链接,具体思路是:

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

具体代码如下:

>>> import requests
>>> from bs4 import BeautifulSoup
>>> url = "http://python123.io/ws/demo.html"
>>> res = requests.get(url)
>>> demo = res.text
>>> demo
'<html><head><title>This is a python demo page</title></head>\r\n<body>\r\n<p class="title"><b>The demo python introduces several python courses.</b></p>\r\n<p class="course">Python is a wonderful general-purpose programming language. You can learn Python from novice to professional by tracking the following courses:\r\n<a href="http://www.icourse163.org/course/BIT-268001" class="py1" id="link1">Basic Python</a> and <a href="http://www.icourse163.org/course/BIT-1001870001" class="py2" id="link2">Advanced Python</a>.</p>\r\n</body></html>'
>>> 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

基于 BeautifulSoup 库的内容查找方法

由前例我们可以看见, find_all 方法可以返回一个列表类型,存储查找的结果,find_all 的具体使用方法为:

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

其中,name 为对标签的检索字符串,如果我们希望查找两个标签,可以以列表形式传入:

>>> 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.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

我们看到,若 find_all(true) ,则会返回所有标签。若希望只显示所有以 b 开头的标签,包括 b 和 body 标签,我们应该怎么办呢?这时我们应该使用正则表达式:

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

find_all 的第二个参数 attrs 是对标签属性值的检索字符串,可标注属性检索。

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

>>> 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")
[]
>>> 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>]

find_all 的第三个参数是 recursive,即是否对子孙进行全部检索,默认为 True。

>>> 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.find_all("a",recursive=False)
[]

上述代码说明,soup 的根节点下是没有 a 标签的, a 标签在其子孙节点中。
find_all 的第四个参数是 string,是对 <>…</> 中字符串区域的检索字符串,下面看一个例子:

>>> import re 
>>> soup.find_all(string="Basic Python")
['Basic Python']
>>> soup.find_all(string="Python")
[]
>>> 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']

事实上,我们有一个简写的形式,即:

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

BeautifulSoup 库有八个常用方法,都是顾名思义的,就不在此做详细介绍了,方法列举为:find_all, find, find_parent, find_parents, find_next_siblings, find_next_sibling, find_previous_sibling, find_previous_siblings

下一篇内容:Python爬虫初级(五)—— “中国大学排名定向爬虫”

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值