Python解析库

Python解析库

目录
一、lxml库
二、BeautifulSoup库
三、PyQuery库

一、lxml库

教程:https://www.w3school.com.cn/xpath/index.asp

1.安装lxml库

pip install -i https://pypi.tuna.tsinghua.edu.cn/simple/ lxml

2.解析规则

解析规则:XPath

表达式 描述
nodename 选取此节点的所有子节点
/ 从当前节点选取直接子节点
// 从当前节点选取所有子孙节点
. 选取当前节点
.. 选取当前节点的父节点
@ 选取属性
* 通配符,选择所有元素节点与元素名
@* 选取所有属性
[@attrib] 选取具有给定属性的所有元素
[@attrib='value'] 选取给定属性具有给定值的所有元素
[tag] 选取所有具有指定元素的直接子节点
[tag='text'] 选取所有具有指定元素并且文本内容是text节点

3.XPath运算符

运算符 描述 实例 返回值
or age=19 or age=20 如果age等于19或者等于20则返回true反正返回false
and age>19 and age<21 如果age等于20则返回true,否则返回false
mod 取余 5 mod 2 1
| 取两个节点的集合 //book | //cd 返回所有拥有book和cd元素的节点集合
+ 6+4 10
- 6-4 2
* 6*4 24
div 除法 8 div 4 2
= 等于 age=19 True或False
!= 不等于 age!=19 True或False
< 小于 age<19 True或False
<= 小于或等于 age<=19 True或False
> 大于 age>19 True或False
>= 大于或等于 age>=19 True或False

4.构建etree实例

(1)从文本构建

示例:

from lxml import etree
def load_text():
    text = """
    <div>
        <ul>
            <li class="item-0"><a href="link1.html">first item</a></li>
            <li class="item-1"><a href="link2.html">second item</a></li>
            <li class="item-inactive"><a href="link3.html">third item</a></li>
            <li class="item-1"><a href="link4.html">forth item</a></li>
            <li class="item-0"><a href="link5.html">fifth item</a>
        </ul>
    </div>
    """

    html = etree.HTML(text)
    result = etree.tostring(html)
    print(result.decode("utf-8"))
运行结果

经过处理后的html代码会被自动修复,如添加一些缺失的标签。

(2)从文件构建

示例:

from lxml import etree
def load_text():
    html = etree.parse("./test.html", etree.HTMLParser())
    print(type(html))
    result = etree.tostring(html)
    print(result.decode("utf-8"))

注意:etree.tostring()方法返回的数据为bytes类型,需要调用decode方法将其转换成sgr类型。

5.节点选取

(1)选中所有节点

  • 选中所有节点

//*

html = etree.parse("./test.html", etree.HTMLParser())
result = html.xpath("//*")
print(result)
  • 选中所有的某一类节点

//标签

html = etree.parse("./test.html", etree.HTMLParser())
result = html.xpath("//li")
print(result)

(2)选取子孙节点

①选取直接子节点

/标签
/child::标签

html = etree.parse("./test.html", etree.HTMLParser())
result = html.xpath("//li/a")
print(result)

②选取后代节点

//标签
/descendant::标签

html = etree.parse("./test.html", etree.HTMLParser())
result = html.xpath("//li//a")
print(result)

(3)选取祖先节点

①选取父节点

  • 方法1

/..

html = etree.parse("./test.html", etree.HTMLParser())
result = html.xpath("//a/..")
print(result)
  • 方法2

/parent::

html = etree.parse("./test.html", etree.HTMLParser())
result = html.xpath("//a/parent::*")
print(result)

②选取祖先节点

/ancestor::*
/ancestor::标签

html = etree.parse("./test.html", etree.HTMLParser())
result = html.xpath("//li[1]/ancestor::*")
print(result)

(4)选取兄弟节点

# 获取该节点后的所有兄弟节点以及这些兄弟节点的所有子孙节点
result = html.xpath("//li[1]/following::*")
print(result)

# 获取该节点后的所有兄弟节点以及这些兄弟节点的所有子孙节点中的第一个节点
result = html.xpath("//li[1]/following::*[1]")
print(result)

# 获取该节点后的所有兄弟节点
result = html.xpath("//li[1]/following-sibling::*")
print(result)

(5)属性匹配

  • 选取具有某属性的节点

[@属性]

html = etree.parse("./test.html", etree.HTMLParser())
result = html.xpath("//li[@class]")
print(result)

选取拥有class属性的li标签。

  • 选取具有某属性且其值符合要求的节点

[@属性=值]

html = etree.parse("./test.html", etree.HTMLParser())
result = html.xpath("//li[@class='item-0']")
print(result)

选取拥有属性class='item-0'的li标签。

(6)属性多值匹配

[contains(@属性, 值)]

text = """
<li class="li li-first"><a href="link1.html">first item</a></li>
"""
html = etree.HTML(text)
result = html.xpath("//li[@class='li']/a/text()")
print(result)

result = html.xpath("//li[contains(@class, 'li')]/a/text()")
print(result)
运行结果

(7)多属性匹配

[contains(@属性, 值) and @属性=值]
[contains(@属性, 值) or @属性=值]

text = """
<li class="li li-first" name='item'><a href="link1.html">first item</a></li>
"""
html = etree.HTML(text)
result = html.xpath("//li[contains(@class, 'li') and @name='item']/a/text()")
print(result)

(8)按顺序位置选取节点

# 选取第一个节点
html = etree.parse("./test.html", etree.HTMLParser())
result = html.xpath("//li[1]/a/text()")
print(result)

# 选取最后一个节点
result = html.xpath("//li[last()]/a/text()")
print(result)

# 选取前两个节点
result = html.xpath("//li[position() < 3]/a/text()")
print(result)

# 选取倒数第三个节点
result = html.xpath("//li[last() - 2]/a/text()")
print(result)
运行结果

6.属性获取

(1)获取节点属性

/@*
/@属性

html = etree.parse("./test.html", etree.HTMLParser())
result = html.xpath("//a[@href='link4.html']/../@class")
print(result)

获取拥有属性href='link4.html的a标签的父亲节点的class属性的值。

(2)获取节点内容

/text()

html = etree.parse("./test.html", etree.HTMLParser())
result = html.xpath("//li[@class='item-0']/text()")
print(result)

获取拥有属性class='item-0'的li标签的文本内容。

二、BeautifulSoup库

文档:https://www.crummy.com/software/BeautifulSoup/bs4/doc.zh/

1.安装BeautifulSoup库

pip install -i https://pypi.tuna.tsinghua.edu.cn/simple/ beautifulsoup4
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple/ bs4

2.解析

(1)文档解析语法

soup = BeautifulSoup(待解析文档, 解析器)

(2)解析器

  • 常用解析器
解析器 使用方法 性能
Python标准库 BeautifulSoup(html_doc,"html.parser") 执行速度适中
文档容错能力强
lxml HTML 解析器 BeautifulSoup(html_doc,"lxml") 执行速度快
容错能力强
要求安装lxml扩展
lxml XML 解析器 BeautifulSoup(html_doc,"xml")
BeautifulSoup(markup,["lxml", "xml"])
支持解析xml
执行速度快
要求安装外部扩展
html5lib解析器 BeautifulSoup(html_doc,"html5lib") 以浏览器的方式解析文档,生成HTML5格式文档
执行速度慢
最好的容错性
要求安装html5lib扩展
  • 解析器安装
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple/ lxml
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple/ html5lib

3.修复文档

soup = BeautifulSoup(html, "lxml")
print(soup.prettify())

4.节点选取

# 整个HTML文档
soup
# title节点的HTML文本
soup.title
# title节点的文本内容
soup.title.string
print(type(soup))
print(type(soup.title))
print(type(soup.title.string))
运行结果

(1)按标签名

# 获取节点名称
print(soup.title.name)

# 获取属性值(字典类型)
print(soup.p.attrs)
print(soup.p.attrs['name'])

# 获取文本内容(str类型)
print(soup.p.string)

# 嵌套选择
print(soup.head.title)

# 关联选择
# contents属性:选取直接子节点
print(soup.p.contents)

(2)按节点关系

# 获取直接子节点(返回列表)
print(soup.p.contents)

# 获取直接子节点(返回生成器)
for i, child in enumerate(soup.p.children):
    print(i, child)
    
# 获取所有子孙节点(返回生成器)
for i, child in enumerate(soup.p.descendants):
    print(i, child)

获取直接父节点:parent
获取祖先节点:parents
获取兄弟节点:

next_sibling(下一个兄弟节点) | previous_sibling(上一个兄弟节点)
next_siblings(后面的所有兄弟节点) | previous_siblings(前面的所有兄弟及诶单)

(3)find方法

  • find_all()方法:返回符合条件的所有节点元素
# 通过name查找
print(soup.find_all(name="ul"))
print(type(soup.find_all(name="ul")[0]))
print(soup.find_all(name="ul")[0].find_all(name='li'))

# 通过属性查找
print(soup.find_all(attrs={'id': 'list'}))
print(soup.find_all(attrs={'id': 'list', 'name': 'elements'}))
print(soup.find_all(id='list2'))
print(soup.find_all(class_='list'))

# 通过文本查找节点
import re
print(soup.find_all(text=re.compile('^1+')))
print(type(soup.find_all(text=re.compile('^1+'))[0]))
  • find():返回单个元素(即匹配的第一个元素)

find_parent() | find_parents()
find_next_sibling() | find_next_siblings()
find_previous_sibling() | find_previous_siblings()
find_next() | find_all_next():返回节点后 第一个|所有 符合条件的节点
find_previous() | find_all_previous():返回节点前 第一个|所有 符合条件的节点

(4)CSS选择器

soup.select("CSS选择器")

三、PyQuery库

1.安装PyQuery库

pip install -i https://pypi.tuna.tsinghua.edu.cn/simple/ pyquery

2.语法类似jQuery

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

推荐阅读更多精彩内容