python解析库

1. Beautiful Soup (bs4 )

Beautiful Soup 是一个可以从HTML或XML文件中提取数据的Python库.它能够通过你喜欢的转换器实现惯用的文档导航,查找,修改文档的方式.Beautiful Soup会帮你节省数小时甚至数天的工作时间.

在测试学习使用bs4的过程中,需要反复用到xml文档。这里就采用bs4官方文档中提供的一个html代码。这是爱丽丝梦游仙境中的一段内容。

<html><head><title>The Dormouse's story</title></head>
<body>
<p class="title"><b>The Dormouse's story</b></p>

<p class="story">Once upon a time there were three little sisters; and their names were
<a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>,
<a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
<a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>;
and they lived at the bottom of a well.</p>

<p class="story">...</p>

包含一个简单的页面。
下面使用python做简单测试。首先是格式化输出:

# 构造BeautifulSoup 对象,其中html_doc为前文的爱丽丝梦游仙境页面
page = BeautifulSoup(html_doc, 'html.parser')
# 格式化输出
print(page.prettify())

控制台的输出结果为:

<html>
 <head>
  <title>
   The Dormouse's story
  </title>
 </head>
 <body>
  <p class="title">
   <b>
    The Dormouse's story
   </b>
  </p>
  <p class="story">
   Once upon a time there were three little sisters; and their names were
   <a class="sister" href="http://example.com/elsie" id="link1">
    Elsie
   </a>
   ,
   <a class="sister" href="http://example.com/lacie" id="link2">
    Lacie
   </a>
   and
   <a class="sister" href="http://example.com/tillie" id="link3">
    Tillie
   </a>
   ;
and they lived at the bottom of a well.
  </p>
  <p class="story">
   ...
  </p>
 </body>
</html>

显然这是一个规范的html文件。使用起来实在是太方便了~再探索一下其他的功能吧。
bs4能够很轻松地获取到文档信息,浏览结构化信息。例如,获取页面的title,只需要

page.title.name

需要注意的是,如果使用CSS选择器,应该使用select方法,如:

#查找class为sister的
print('class为sister的(CSS方式查找的):', page.select('.sister'))
#查找id为link2的
print('id为link2的(CSS方式查找的:)', page.select('#link2'))

完整的测试代码:


# 构造BeautifulSoup 对象,其中html_doc为前文的爱丽丝梦游仙境页面
page = BeautifulSoup(html_doc, 'html.parser')
# 格式化输出
# print(page.prettify())


# 获取title相关信息
print('page.title : ', page.title)
print('page.title.name : ', page.title.name)
print('page.title.text : ', page.title.text)
print('page.title.parent.name : ', page.title.parent.name)

# 获取a标签
print('单个a标签:', page.a)
print('所有a标签: ', page.find_all('a'))

# 以css的方式查找 使用select
print('class为sister的(CSS方式查找的):', page.select('.sister'))
print('id为link2的(CSS方式查找的:)', page.select('#link2'))

输出结果为:

page.title :  <title>The Dormouse's story</title>
page.title.name :  title
page.title.text :  The Dormouse's story
page.title.parent.name :  head
单个a标签: <a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>
所有a标签:  [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>, <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>, <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]
class为sister的(CSS方式查找的): [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>, <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>, <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]
id为link2的(CSS方式查找的:) [<a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>]

如果要获取标签中的某一部分,可以使用get方法。例如:获取页面中所有a标签的链接内容。

for line in page.find_all('a'):
    print(line.get('href'))

输出为:

http://example.com/elsie
http://example.com/lacie
http://example.com/tillie

如果要获取页面中所有的文字信息,只需要一行代码:

text = page.get_text()

这是bs4一些最基础的用法。遇到问题就查一下官方文档:bs4.4.0官方文档

2. lxml

lxml是一个Python库,使用它可以轻松处理XML和HTML文件,还可以用于web爬取。市面上有很多现成的XML解析器,但是为了获得更好的结果,开发人员有时更愿意编写自己的XML和HTML解析器。这时lxml库就派上用场了。这个库的主要优点是易于使用,在解析大型文档时速度非常快,归档的也非常好,并且提供了简单的转换方法来将数据转换为Python数据类型,从而使文件操作更容易。

2.1 Xpath语言

节点:元素、属性、文本、命名空间、文档节点等。
节点关系:父、字、同胞、先辈、后代等。

表达式 描述
nodename 选此节点的所有子节点
// 从任意子节点选择
/ 从根节点选择(这里是相对的)
. 从当前节点选择
.. 从上一级节点选择
@ 取属性

2.2 lxml的使用

首先需要导入lxml库

from lxml import etree
from bs4_sample import html_doc

构造etree

et = etree.HTML(html_doc)

需要使用单个属性获取所需内容

  • 变量.tag——标签名——字符串
  • 变量.attrib——节点标签a的属性——字典
  • 变量.text——标签文本——字符串
    通过例子体会:
et = etree.HTML(html_doc)
print(et)

for tag in et:
    print("TAG : ", et.tag)
for attrib in et:
    print("ATTRIB : ", et.attrib)
for text in et:
    print("TEXT : ", et.text)

输出结果为:

TAG :  html
TAG :  html
ATTRIB :  {}
ATTRIB :  {}
TEXT :  None
TEXT :  None

也就是说,et变量实际上是这个html页面的根节点。若执行

print(et)

输出的是

<Element html at 0x1a5b5135b40>

也就是html,也即该页面的最外层:

html

测试代码:

for i in range(len(et)):
    print(et[i].tag)

输出结果为:

head
body

观察页面的结构,发现html下两个同胞节点为head 和body。如图:


页面结构

获取各个子节点的信息,以类似于多维数组的方式,通过代码实现遍历:

for i in range(len(et)):
    print(et[i].tag)
    for j in range(len(et[i])):
        print("      "+et[i][j].tag)

输出结果为:

head
      title
body
      p
      p
      p

与页面标签结构相符。这样就基本理解了etree.HTML(html_doc)语句所生成对象的结构。

下面来做几件爬虫可能需要的工作。

  • 检查元素是都有子元素
  • 检查节点是都为一个elements
  • 检查一个元素是否有父元素
  • 检查同胞元素
  • 寻找元素
    在python代码中依次做这些测试。比较简单,基本方法总结见表:
功能 方法
检查是否存在子元素 len(et)>0
检查是否为element etree.iselement(et[i]))
检查是否存在父元素 getparent() 注意:是方法 不是getparent属性!
检查同胞元素 getprevious()和getnext()方法
寻找元素 find()方法

代码比较简单,测试结果写在注释中:

# 1.检查元素是都有子元素   ——检查长度
#   1.1 检查根节点是否有子元素
if len(et) > 0:
    print("根节点有%s个子元素" % len(et))
else:
    print("根节点没有子元素!")
#   1.2检查根节点的子节点是否有子元素
for i in range(len(et)):
    if len(et[i]) > 0:
        print("%s标签有子节点,第一个子节点为:%s" % (et[i].tag, et[i][0].tag))
    else:
        print("%s标签没有子节点!" % et[i].tag)
# 此部分的输出结果为:
# 根节点有2个子元素
# head标签有子节点,第一个子节点为:title
# body标签有子节点,第一个子节点为:p

# 2.检查是否为elements           etree.iselement(et[i]))
for i in range(len(et)):
    print("%s是否为element : %s" % (et[i].tag, etree.iselement(et[i])))
# 此部分输出结果为:
# head是否为element : True
# body是否为element : True

# 3.检查是否存在父元素——getparent() 注意:是方法 不是getparent属性!
print(et.getparent())
for i in range(len(et)):
    if et[i].getparent():
        print("%s存在父元素!" % et[i].tag)
    else:
        print("%s不存在父元素!" % et[i].tag)
# 此部分输出结果:
# None
# head存在父元素!
# body存在父元素!

# 4.检查同胞——getprevious()和getnext()方法
# 代码略

# 5.寻找元素
print(et[1].find('p'))
print(et[1].find('p').tag)
# 此部分输出结果:
# <Element p at 0x1b688db5c40>
# p

2.3 lxml的xpath方法

取出所有的a标签中的href链接:et.xpath('//a/@href')

x = et.xpath('//a/@href')
for i in range(len(x)):
    print(x[i])

输出结果为:

http://example.com/elsie
http://example.com/lacie
http://example.com/tillie
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,402评论 6 499
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,377评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,483评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,165评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,176评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,146评论 1 297
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,032评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,896评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,311评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,536评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,696评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,413评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,008评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,659评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,815评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,698评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,592评论 2 353

推荐阅读更多精彩内容

  • Python解析库 目录一、lxml库二、BeautifulSoup库三、PyQuery库 一、lxml库 教程:...
    Recalcitrant阅读 1,381评论 0 0
  • 解析库的安装 lxml 安装 lxml能够支持HTML和XML 的解析支持XPath解析,安装方式如下: lxml...
    AlanV阅读 430评论 0 0
  • lxml解析库用来解析html xml等安装 https://www.cnblogs.com/magic8sky/...
    JXeddy阅读 174评论 0 0
  •   DOM(文档对象模型)是针对 HTML 和 XML 文档的一个 API(应用程序编程接口)。   DOM 描绘...
    霜天晓阅读 3,640评论 0 7
  • 其实今天在看之前,我在朋友圈问了下《廉政风云》和《流浪地球》哪个好看。 因为完全是两个不同的风格,一个偏悬疑,一个...
    玛嗒嗒阅读 276评论 1 5