版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Rozol/article/details/79968795
Python3 HTML数据解析(lxml/BeautifulSoup/JsonPath)
本文由 Luzhuo 编写,转发请保留该信息.
原文: https://blog.csdn.net/Rozol/article/details/79968795
以下代码以Python3.6.1为例
Less is more!
lxml
#!/usr/bin/env python
# coding=utf-8
__author__ = 'Luzhuo'
__date__ = '2018/4/16'
'''
lxml 是一个 HTML/XML 的解析器, 主要用于解析和提取 HTML/XML 数据
lxml由 C 实现的, 我们可以用 XPath 语法来快速的定位结点
pip install lxml
lxml-4.2.1
xpath文档: http://www.w3school.com.cn/xpath/
'''
from lxml import etree
text = '''
<div>
<ul>
<li class="item_0">
<a href="/i/0123">条目1</a>
</li>
<li class="item_1">
<a href="/i/01234">条目2</a>
</li>
<li class="item_2">
<a href="/i/012345">条目3</a>
</li>
<li class="item_0">
<a href="/i/0123456">条目4</a>
<li class="item_1">
<a href="/i/01234567">条目5</a>
</ul>
</div>
'''
# 第三方库lxml的演示
def lxml_demo():
# 解析成html, 会自动修正html
html = etree.HTML(text)
# html = etree.parse('text.html') # 从文件解析
print(etree.tostring(html))
# 使用xpath匹配
result = html.xpath('//li') # 所有<li>
result = html.xpath('//li/@class') # 所有<li>下的class属性
result = html.xpath('//li/a[@href="/i/0123456"]') # 所有<li>下<a>标签href属性为"/i/0123456"的标签
result = html.xpath('//li[last()-1]/a/@href') # 最后一个 -1 的<li>下<a>标签的href属性
result = html.xpath('//a[contains(@href, "/i/")]') # 模糊匹配
html = html.xpath('//li[@class="item_0"]')[0]
text = html.xpath('./a/@href') # 获取a标签下href属性的值
text = html.xpath('./a/text()') # 获取a标签的内容
print(result)
lxml_demo()
BeautifulSoup
#!/usr/bin/env python
# coding=utf-8
# beautifulsoup.py beautifulsoup演示
from urllib import request
from bs4 import BeautifulSoup
import re
'''
Beautiful Soup 是一个可以从HTML或XML文件中提取数据的Python库
Beautiful Soup 会载入整个文档, 解析整个DOM树, 所以内存消耗会比较大
文档地址:http://beautifulsoup.readthedocs.io/zh_CN/latest
pip install beautifulsoup4
beautifulsoup4-4.6.0
'''
text = '''
<div>
<ul>
<li class="item_0">
<a href="/i/0123">条目1</a>
</li>
<li class="item_1" id="link1">
<a href="/i/01234">条目2</a>
</li>
<li class="item_2">
<a href="/i/012345">条目3</a>
</li>
<li class="item_0" id="link1">
<a href="/i/0123456">条目4</a>
<li class="item_1">
<a href="/i/01234567">条目5</a>
</ul>
</div>
'''
def fun():
'''
解析库
"html.parser": Python标准库 (内置, 速度适中, 容错能力强)
"lxml": lxml HTML 解析器 (速度快, 文档容错能力强, 需要安装lxml) [推荐][pip install lxml]
"xml": lxml XML 解析器 (速度快, 唯一支持XML的解析器, 需要安装lxml)
"html5lib": html5lib (生成HTML5格式的文档, 以浏览器的方式解析文档, 容错能力最好, 速度慢) [pip install html5lib]
不同的解析器, 解析出来的内容是不同的
'''
soup = BeautifulSoup(text, "lxml")
soup = BeautifulSoup(open('text.html')) # 打开本地文件
print(soup.prettify())
# 获取标签
print(soup.li) # 获取第一条<li>标签
print(soup.li.a) # 获取第一条<li>标签下<a>标签
print(soup.ul.contents) # <ul>标签所有(直接)子结点
print(soup.ul.contents[1])
for child in soup.ul.children: print(child) # <ul>标签所有(直接)子结点(返回list生成器)
for child in soup.descendants: print(child) # 遍历所有(直接+间接)结点
print(soup.li.a.name) # 标签的名字
print(soup.li.a.attrs) # 标签的所有属性
print(soup.li['class']) # 所有属性名为'class'的值
soup.li['class'] = 'b123' # 修改属性内容
soup.a.string = 'aaa'
del soup.li['class'] # 删除属性
print(soup.a.string) # 标签内容, 没内容返回None
for string in soup.stripped_strings: print(repr(string)) # 所有内容, 去除空格 (.strings 不去空格)
print(soup.find_all('a')[0].get('href')) # 获取标签里的内容
print(soup.find_all('a')[0].get_text()) # 获取文本内容
# --- 搜索方法 ---
# limit=2 可限制返回数量 / recursive=False 只想搜索直接子结点
print(soup.find('li')) # 搜索一个标签
print(soup.find_all("li")) # 搜索全部标签
print(soup.find_all(re.compile('^l'))) # (正则)
print(soup.find_all(['li', 'a'])) # (list)
print(soup.find_all(href="/i/0123")) # 所有href="/i/0123"的属性 (属性名不能为python保留字, 如class)
print(soup.find_all(text=re.compile('^条目'))) # 搜索所有内容, 支持参数 字符串 / 正则 / list
# --- 选择方法 ---
print(soup.select('li')) # 搜索所有标签<li>
print(soup.select('.item_0')) # 搜索所有属性 class="item_0" 的标签
print(soup.select('#link1')) # 搜索所有id id="link1" 的标签
print(soup.select("li#link1")) # 组合(不同节点加空格, 同节点不加)
print(soup.select("li#link1 a"))
print(soup.select("li > a")) # 通过子标签查找(>号分隔)
print(soup.select('li[class="item_0"]')) # <li>所有属性 class="item_0" 的标签
print(soup.select('li a[href="/i/012345"]')) # 组合
if __name__ == "__main__":
fun()
JsonPath
#!/usr/bin/env python
# coding=utf-8
__author__ = 'Luzhuo'
__date__ = '2018/4/17'
'''
介绍
JsonPath 主要用于从 JSON 文档中提取数据
文档: http://goessner.net/articles/JsonPath/
pip install jsonpath
jsonpath-0.75
语法
xpath jsonpath 描述
/ $ 根节点
. @ 现行节点
/ .or[] 取子节点
// .. 就是不管位置,选择所有符合条件的条件
* * 匹配所有元素节点
[] [] 迭代器标示(可以在里边做简单的迭代操作,如数组下标,根据内容选值等)
| [,] 支持迭代器中做多选。
[] ?() 支持过滤操作.
() 支持表达式计算
'''
import jsonpath
import json
json_str = '''
{ "store": {
"book": [
{ "category": "reference",
"author": "Nigel Rees",
"title": "Sayings of the Century",
"price": 8.95
},
{ "category": "fiction",
"author": "Evelyn Waugh",
"title": "Sword of Honour",
"price": 12.99
},
{ "category": "fiction",
"author": "Herman Melville",
"title": "Moby Dick",
"isbn": "0-553-21311-3",
"price": 8.99
},
{ "category": "fiction",
"author": "J. R. R. Tolkien",
"title": "The Lord of the Rings",
"isbn": "0-395-19395-8",
"price": 22.99
}
],
"bicycle": {
"color": "red",
"price": 19.95
}
}
}
'''
def funcs():
jsonobj = json.loads(json_str)
result = jsonpath.jsonpath(jsonobj, '$..author') # 同xpath的 //author
result = jsonpath.jsonpath(jsonobj, '$.store.book[*].author') # 同xpath的 /store/book/author
result = jsonpath.jsonpath(jsonobj, '$.store..price') # 同xpath的 /store//price
result = jsonpath.jsonpath(jsonobj, '$..book[3]') # 同xpath的 //book[3]
result = jsonpath.jsonpath(jsonobj, '$..book[-1:]') # 同xpath的 //book[last()]
result = jsonpath.jsonpath(jsonobj, '$..book[0,1]') # 同xpath的 //book[position()<3]
result = jsonpath.jsonpath(jsonobj, '$..book[?(@.price<10)]') # 同xpath的 //book[price<10]
print(result)
if __name__ == "__main__":
funcs()