python3学习笔记

python解析库

2020-03-14  本文已影响0人  一个王二不小

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)

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

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)语句所生成对象的结构。

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

功能 方法
检查是否存在子元素 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
上一篇下一篇

猜你喜欢

热点阅读