MyException - 我的异常网
当前位置:我的异常网» Perl/Python » Python网络爬虫与信息提取(2)—— BeautifulSoup

Python网络爬虫与信息提取(2)—— BeautifulSoup

www.MyException.Cn  网友分享于:2013-10-11  浏览:0次
Python网络爬虫与信息提取(二)—— BeautifulSoup

BeautifulSoup官方介绍:

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

官方网站:https://www.crummy.com/software/BeautifulSoup/

BeautifulSoup安装

在"C:\Windows\System32"中找到"cmd.exe",使用管理员身份运行,在命令行中输入:“pip install beautifulsoup4”运行。

C:\Windows\system32>pip install beautifulsoup4
Requirement already satisfied (use --upgrade to upgrade): beautifulsoup4 in c:\users\lei\appdata\local\programs\python\p
ython35\lib\site-packages\beautifulsoup4-4.5.0-py3.5.egg
You are using pip version 8.1.1, however version 9.0.1 is available.
You should consider upgrading via the 'python -m pip install --upgrade pip' command.

提示pip版本过低,使用 python -m pip install --upgrade pip 进行升级。

Beautiful Soup库的安装测试:

from bs4 import BeautifulSoup
soup = BeautifulSoup('<p>data</p>','html.parser')

演示HTML页面地址:http://www.cnblogs.com/yan-lei

>>> import requests
>>> from bs4 import BeautifulSoup
>>> r = requests.get("http://www.cnblogs.com/yan-lei/")
>>> demo = r.text
>>> soup = BeautifulSoup(demo,"html.parser")
>>> soup

Beautiful Soup库的使用

以HTML为例,任何HTML文件都是有一组"<>"组织起来的,其实就是标签,标签之间形成了上下游关系,形成了标签树。BeautifulSoup库是解析、遍历、维护“标签树”的功能库

<p>..</p>:标签Tag

  • 标签Name一般成对出现
  • 属性Attributes 0个或多个

Beautiful Soup库的引用

Beautiful Soup库,也叫beautfulsoup4 或bs4。约定引用方式如下,即主要是用BeautifulSoup类。

from bs4 import BeautifulSoup
import bs4

Beautiful Soup类

将标签树转换为BeautifulSoup类,此时我们将HTML、标签树、BeautifulSoup类等价

from bs4 import BeautifulSoup
soup1 = BeautifulSoup("<html>data</html>","html.parser")
soup2 = BeautifulSoup(open("D://demo.html",'rb'),"html.parser")

使用 soup2 = BeautifulSoup(open("D://demo.html"),"html.parser") 报错:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Users\lei\AppData\Local\Programs\Python\Python35\lib\site-packages\beautifulsoup4-4.5.0-py3.5.egg\bs4\__init_
_.py", line 191, in __init__
UnicodeDecodeError: 'gbk' codec can't decode byte 0xbf in position 2: illegal multibyte sequence

BeautifulSoup对应一个HTML/XML文档的全部内容。

Beautiful Soup库解析器

解析器使用方法条件
bs4的HTML解析器 BeautifulSoup(mk,'html.parser') 安装bs4库
lxml的HTML解析器 BeautifulSoup(mk,'lxml') pip install lxml
lxml的XML解析器 BeautifulSoup(mk,'xml') pip install lxml
html5lib的解析器 BeautifulSoup(mk,'html5lib') pip install html5lib

Beautiful Soup类的基本元素

基本元素说明
Tag 标签,最基本的信息组织单元,分别用<>和</>标明开头和结尾
Name 标签的名字,<p>...</p>的名字是'p',格式:<tag>.name
Attributes 标签的属性,字典形式的组织,格式:<tag>.attrs
NavigleString 标签内非属性字符串,<>...</>中字符串,格式<tag>.string
Comment 标签内字符串的注释部分,一种特殊的Comment类型
  • Tag标签:任何存在于HTML语法中的标签都可以用soup.<tag>访问获得;当HTML文档中存在多个相同<tag>对应内容时,soup.<tag>返回第一个。
  • Tag的名字(name):每个<tag>都有自己的名字,通过<tag>.name获取,字符串类型。
  • Tag的attrs(属性):一个<tag>可以有0个或多个属性,字典类型。
  • Tag的NavigableString:NavigableString可以跨越多个层次
  • Tag的Comment:Comment是一种特殊类型。
>>> import requests
>>> from bs4 import BeautifulSoup
>>> r = requests.get('http://www.cnblogs.com/yan-lei/')
>>> html = r.text
>>> soup = BeautifulSoup(html,'html.parser')
>>> soup.title
<title>Python学习者 - 博客园</title>
>>> soup.a
<a name="top"></a>
>>> soup.a.name
'a'
>>> soup.a.parent.name
'body'
>>> soup.a.attrs
{'name': 'top'}
>>> type(soup.a)
<class 'bs4.element.Tag'>
>>> type(soup.a.attrs)
<class 'dict'>
>>> soup.h1.string
'Python学习者'
>>> type(soup.h1.string)
<class 'bs4.element.NavigableString'>

基于bs4库的HTML内容遍历方法

HTML中 <...>构成了所属关系,形成了标签的树形结构,有三种遍历方式。

使用以下的HTML进行测试:E:\BeautifulSoupTest.html

<html>
    <head>
        <meta charset="utf-8">
        <title>BeautifulSoup</title>
    </head>
    <body>
        <div id="header">
            <h1  style="font-size:16px;text-align:center">这里是标题</h1>
        </div>
        <div id="nav">
            <h1>左导航</h1>
        </div>
        <div id="main">
            <p>第一段</p>
            <p>第二段</p>
            <img src="test.jpg"/>
            <p><a href="http://www.cnblogs.com/yan-lei/">博客园</a></p>

        </div>
        <div id="footer">
            <h1>底边</h1>
        </div>

    </body>
</html>

标签树的下行遍历

属性说明
.contents 子节点的列表,将<tag>所有儿子节点存入列表
.contents 子节点的列表,将<tag>所有儿子节点存入列表
.children 子节点的迭代类型,与.contents类似,用于循环遍历儿子节点
.descendants 子孙节点的迭代类型,包含所有子孙节点,用于循环遍历

BeautifulSoup类是标签树的根节点

>>> from bs4 import BeautifulSoup
>>> soup = BeautifulSoup(open('E:\\BeautifulSoupTest.html','rb'),'html.parser')
>>> soup.head.contents #返回的是列表
['\n', <meta charset="utf-8">
<title>BeautifulSoup</title>
</meta>]
>>> len(soup.body.contents)
9
>>> for child in soup.body.children:   # 遍历儿子节点
...     print(child)
...


<div id="header">
<h1 style="font-size:16px;text-align:center">这里是标题</h1>
</div>


<div id="nav">
<h1>左导航</h1>
</div>


<div id="main">
<p>第一段</p>
<p>第二段</p>
<img src="test.jpg">
<p><a href="http://www.cnblogs.com/yan-lei/">博客园</a></p>
</img></div>


<div id="footer">
<h1>底边</h1>
</div>


>>> for child in soup.body.descendants:  # 遍历子孙节点
...     print(child)
...


<div id="header">
<h1 style="font-size:16px;text-align:center">这里是标题</h1>
</div>


<h1 style="font-size:16px;text-align:center">这里是标题</h1>
这里是标题




<div id="nav">
<h1>左导航</h1>
</div>


<h1>左导航</h1>
左导航




<div id="main">
<p>第一段</p>
<p>第二段</p>
<img src="test.jpg">
<p><a href="http://www.cnblogs.com/yan-lei/">博客园</a></p>
</img></div>


<p>第一段</p>
第一段


<p>第二段</p>
第二段


<img src="test.jpg">
<p><a href="http://www.cnblogs.com/yan-lei/">博客园</a></p>
</img>


<p><a href="http://www.cnblogs.com/yan-lei/">博客园</a></p>
<a href="http://www.cnblogs.com/yan-lei/">博客园</a>
博客园




<div id="footer">
<h1>底边</h1>
</div>


<h1>底边</h1>
底边
for child in soup.body.children:   # 遍历儿子节点
    print(child)

for child in soup.body.descendants:  # 遍历子孙节点
    print(child)

标签树的上行遍历

属性说明
.parent 节点的父亲标签
.parents 节点先辈标签的迭代类型,用于循环遍历先辈节点
>>> for parent in soup.a.parents:
...     if parent is None:
...             print(parent)
...     else:
...             print(parent.name)
...
p
img
div
body
html
[document]
# 判断所有先辈节点,包括soup本身,所以要区别判断
for parent in soup.a.parents:
    if parent is None:
            print(parent)
    else:
            print(parent.name)

标签树的平行遍历

属性说明
.next_sibling 返回按照HTML文本顺序的下一个平行节点标签
.previous_sibling 返回按照HTML文本顺序的上一个平行节点标签
.next_siblings 迭代类型,返回按照HTML文本顺序的后续所有平行节点标签
.previous_siblings 迭代类型,返回按照HTML文本顺序的前续所有平行节点标签

*所有的平行遍历发生在同一个父节点下的各节点间。

# div标签下一个平行节点标签
soup.div.next_sibling

# div标签上一个平行节点标签
soup.div.previous_sibling


# 遍历后续节点
for sibling in soup.div.next_sibling:
    print(sibling) 

# 遍历前续节点
for sibling in soup.div.previous_sibling:
    print(sibling) 

基于bs4库的HTML格式输出

bs4库的prettify()方法

.prettify()为HTML文本<>及其内容增加'\n'

.prettify()可用于标签,方法:<tag>.prettify()

print(soup.prettify())

bs4库将任何HTML输入都变成utf-8编码,Python 3.x默认支持编码是utf-8,解析无障碍。

信息标记的三种形式

信息的标记:

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

HTML的信息标记:

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

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

XML eXtensible Markup Language

XML格式是基于HTML格式发展以来的一种通用的信息格式。

  • XML基本格式:<name> ... </name>
  • 空元素缩写形式:<name />
  • 注释书写形式:<!-- -->

JSON JavaScript Object Notation

有类型的键值对 key:value

使用 "" 表达是字符串类型,没有字符串则是数字类型。

YAML YAML Ain't Markup Language

无类型键值对 key:value

通过缩进表达所属关系

  • - 表达并列关系
  • | 表达整块数据
  • # 表示注释
key : value
key : #Comment
-value1
-value2
key :
    subkey : subvalue

三种信息标记形式的比较:

XML 最早的通用信息标记语言,可扩展性好,但繁琐。Internet上的信息交互与传递。

JSON 信息有类型,适合程序处理(js),较XML简洁。移动应用云端和节点的信息通信,无注释。

YAML 信息无类型,文本信息比例最高,可读性好。各类系统的配置文件,有注释易读。

信息提取的一般方法

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

XML JSON YAML

需要标记解析器 例如bs4库的标签树遍历

优点:信息解析准确

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

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

搜索

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

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

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

方法三:融合方法

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

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

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

返回一个列表类型,存储查找结果。

  • name:对标签名称的检索字符串。
  • attrs:对标签属性值的检索字符串,可标注属性检索。
  • recursive:是否对子孙全部检索,默认True。
  • string:<>...</>中字符串区域的检索字符串。

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

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

>>> soup.div()
[<h1 style="font-size:16px;text-align:center">这里是标题</h1>]
>>> for tag in soup.find_all(True):  # 返回所有的标签
...     print(tag.name)
...
html
head
meta
title
body
div
h1
div
h1
div
p
p
img
p
a
div
h1

扩展方法

方法说明
<>.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()参数

回到顶部

文章评论

旅行,写作,编程
旅行,写作,编程
 程序员的样子
程序员的样子
团队中“技术大拿”并非越多越好
团队中“技术大拿”并非越多越好
写给自己也写给你 自己到底该何去何从
写给自己也写给你 自己到底该何去何从
看13位CEO、创始人和高管如何提高工作效率
看13位CEO、创始人和高管如何提高工作效率
当下全球最炙手可热的八位少年创业者
当下全球最炙手可热的八位少年创业者
那些争议最大的编程观点
那些争议最大的编程观点
做程序猿的老婆应该注意的一些事情
做程序猿的老婆应该注意的一些事情
“懒”出效率是程序员的美德
“懒”出效率是程序员的美德
为啥Android手机总会越用越慢?
为啥Android手机总会越用越慢?
鲜为人知的编程真相
鲜为人知的编程真相
10个帮程序员减压放松的网站
10个帮程序员减压放松的网站
2013年中国软件开发者薪资调查报告
2013年中国软件开发者薪资调查报告
60个开发者不容错过的免费资源库
60个开发者不容错过的免费资源库
老程序员的下场
老程序员的下场
Web开发人员为什么越来越懒了?
Web开发人员为什么越来越懒了?
我的丈夫是个程序员
我的丈夫是个程序员
Java 与 .NET 的平台发展之争
Java 与 .NET 的平台发展之争
编程语言是女人
编程语言是女人
2013年美国开发者薪资调查报告
2013年美国开发者薪资调查报告
如何区分一个程序员是“老手“还是“新手“?
如何区分一个程序员是“老手“还是“新手“?
亲爱的项目经理,我恨你
亲爱的项目经理,我恨你
程序员的鄙视链
程序员的鄙视链
如何成为一名黑客
如何成为一名黑客
中美印日四国程序员比较
中美印日四国程序员比较
那些性感的让人尖叫的程序员
那些性感的让人尖叫的程序员
程序员最害怕的5件事 你中招了吗?
程序员最害怕的5件事 你中招了吗?
程序员眼里IE浏览器是什么样的
程序员眼里IE浏览器是什么样的
聊聊HTTPS和SSL/TLS协议
聊聊HTTPS和SSL/TLS协议
我跳槽是因为他们的显示器更大
我跳槽是因为他们的显示器更大
程序猿的崛起——Growth Hacker
程序猿的崛起——Growth Hacker
为什么程序员都是夜猫子
为什么程序员都是夜猫子
代码女神横空出世
代码女神横空出世
“肮脏的”IT工作排行榜
“肮脏的”IT工作排行榜
我是如何打败拖延症的
我是如何打败拖延症的
程序员的一天:一寸光阴一寸金
程序员的一天:一寸光阴一寸金
什么才是优秀的用户界面设计
什么才是优秀的用户界面设计
程序员都该阅读的书
程序员都该阅读的书
每天工作4小时的程序员
每天工作4小时的程序员
一个程序员的时间管理
一个程序员的时间管理
程序员应该关注的一些事儿
程序员应该关注的一些事儿
十大编程算法助程序员走上高手之路
十大编程算法助程序员走上高手之路
初级 vs 高级开发者 哪个性价比更高?
初级 vs 高级开发者 哪个性价比更高?
5款最佳正则表达式编辑调试器
5款最佳正则表达式编辑调试器
10个调试和排错的小建议
10个调试和排错的小建议
漫画:程序员的工作
漫画:程序员的工作
不懂技术不要对懂技术的人说这很容易实现
不懂技术不要对懂技术的人说这很容易实现
Google伦敦新总部 犹如星级庄园
Google伦敦新总部 犹如星级庄园
程序员必看的十大电影
程序员必看的十大电影
软件开发程序错误异常ExceptionCopyright © 2009-2015 MyException 版权所有