數據的解析
解析數據的方式大概有三種
- xpath
- JsonPath
- BeautifulSoup
xpath
?安裝xpath插件
打開谷歌瀏覽器擴展程序,打開開發者模式,拖入插件,重啟瀏覽器,ctrl+shift+x,打開插件頁面
安裝lxml庫?
安裝在python環境中的Scripts下邊,這里就是python庫的位置,例如我的地址為:E:\python\python3.10.11\Scripts
pip install lxml -i https://pypi.tuna.tsinghua.edu.cn/simple
xpath使用和基本語法
解析本地文件etree.parse( 'xx.html')4.etree.HTML()
解析服務器響應文件html_tree = etree.HTML(response.read().decode( 'utf-8')4.html tree.xpath(xpath路徑)
xpath基本語法:
路徑查詢
????????// : 查找所有子孫節點,不考慮層級關系
????????/? :找直接子節點
謂詞查詢
????????//div[@id] :包含id屬性的div
????????//div[@id="maincontent"] :id = maincontent的div
屬性查詢
????????//@class :? ?返回指定標簽的class屬性
模糊查詢
????????//div[contains(@id,"he")] : 包含
? ? ????//div[starts-with(@id,"he")] :以he開頭
內容查詢
????????//div/h1/text() : text()顯示內容
邏輯運算
? ????//div[@id="head" and @class="s down"] : 邏輯&&?
xpath解析本地文件?
本地文件如下
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"/><title>Title</title>
</head>
<body><ul><li id="00" class="beijing">北京</li><li>上海</li><li>深圳</li><li>廣州</li></ul><ul><li id="11" class="shenyang">沈陽</li><li>南京</li></ul>
</body>
</html>
解析本地文件
from lxml import etree# 解析本地文件 使用etree.parse
tree = etree.parse('Test.html')# 找到所有的ul
ul_list = tree.xpath("//ul")# 查找所有的li
li_list = tree.xpath("//ul/li")# 查找所有包含id的li
id_li_list = tree.xpath("//ul/li[@id]")# 查找id為00的li,并找到內容 注意引號問題
content_list = tree.xpath("//ul/li[@id='00']/text()")# 查找id包含0的li的內容
contains_list = tree.xpath("//ul/li[contains(@id,'0')]/text()")# 獲取id為11的li class屬性值@class
li = tree.xpath("//ul/li[@id='11']/@class")
print(ul_list)print(li_list)print(id_li_list)print(contains_list)print(content_list)print(li)"""
輸出結果:
[<Element ul at 0x22c26c38240>, <Element ul at 0x22c26c38600>]
[<Element li at 0x22c26c38640>, <Element li at 0x22c26c385c0>, <Element li at 0x22c26c38680>, <Element li at 0x22c26c386c0>, <Element li at 0x22c26c38700>, <Element li at 0x22c26c38780>]
[<Element li at 0x22c26c38640>, <Element li at 0x22c26c38700>]
['北京']
['北京']
['shenyang']
"""
xpath解析服務器文件?
使用xpath插件檢查xpath路徑的匹配,解析定位dom
from lxml import etree
import urllib.request as request# 下載圖片
url = "https://www.baidu.com/"headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36',
}# 構建的請求對象
geneRequest=request.Request(url=url,headers = headers)
# 模擬瀏覽器發送請求
response = request.urlopen(geneRequest)
# 獲取內容
content = response.read().decode('utf-8')# 解析服務器文件
tree = etree.HTML(content)# 找到百度一下的值
result = tree.xpath('//input[@id="su"]/@value')print(result)"""
輸出結果:['百度一下']
"""
jsonpath
jsonpath是一種信息抽取類庫,是從JSON文檔中抽取指定信息的工具,只能讀取本地的json文件,與xpath類似,只不過對應符號不同
?jsonpath安裝
pip install jsonpath -i https://pypi.tuna.tsinghua.edu.cn/simple
xpath和jsonpath的對應關系?
XPath?? ? | JSONPath | ?描述 |
/?? | $? | 根節點 |
. | ?@? | 現行節點 |
/ | .or[] | 取子節點 |
、、 | n/a | 取父節點,Jsonpath未支持 |
//? | 、、 | 就是不管位置,選擇所有符合條件的條件 |
*? | *? | 匹配所有元素節點 |
@ | n/a? | 根據屬性訪問,Json不支持,因為Json是個Key-value遞歸結構,不需要 |
[]? | []? | 迭代器標識(可以在里邊做簡單的迭代操作,如數組下標,根據內容選值等 |
[]? | ?() | 支持過濾操作 |
| | [,] | 支持迭代器中做多選 |
n/a | () | 支持表達式計算 |
() | n/a | 分組,JsonPath不支持 |
jsonpath解析
準備json
{"store": {"book":[{ "category": "射手","author": "魯班七號","title": "王者榮耀","price": 8.95},{"category": "打野","author": "李白","title": "大河之水天上來","price": 22.99}],"bicycle": {"color": "red","price": 19.95}}}
?通過jsonpath解析json數據
import json
import jsonpathobj = json.load(open('test.json',"r",encoding="utf-8"))# 查看store下的bicycle的color屬性 $ 對應xpath/
colorAttr = jsonpath.jsonpath(obj, "$.store.bicycle.color")# 輸出book節點的第一個對象
bookFirst = jsonpath.jsonpath(obj, "$.store.book[0]")# 輸出book節點中所有對象對應的屬性title值
titles = jsonpath.jsonpath(obj, "$.store.book[*].title")# 輸出book節點中所有價格小于10的對象 ?() 對應xpath [] @ 對應當前節點
books = jsonpath.jsonpath(obj, "$.store.book[?(@.price<10)]")print(colorAttr)print(bookFirst)print(titles)print(books)"""
輸出結果:
['red']
[{'category': '射手', 'author': '魯班七號', 'title': '王者榮耀', 'price': 8.95}]
['王者榮耀', '大河之水天上來']
[{'category': '射手', 'author': '魯班七號', 'title': '王者榮耀', 'price': 8.95}]
"""
BeautifulSoup
Beautifulsoup簡稱bs4,Beautifulsoup,和lxml一樣,是一個html的解析器,主要功能也是解析和提取數據
- 缺點: 效率沒有1xm1的效率高
- 優點: 接口設計人性化,使用方便
BeautifulSoup安裝
pip install bs4 - i https://pypi.tuna.tsinghua.edu.cn/simple
?BeautifulSoup節點定位規則
soup =?soup = Beautifulsoup(response.read().decode(),'Ixml') 解析服務器文件
soup =?soup = Beautifulsoup(open('1.html').lxml')? 解析本地文件
根據標簽名查找節點
????????soup.a? 只能找到第一個a
????????soup.a.namesoup.a.attrs???獲取標簽的屬性和屬性值函數查找
? .find (返回一個對象?只能找到第一個a標簽)
? ? ? ? find('a')
? ? ? ? find('a',title='名字')
? ? ? ? find('a',class='名字')
? .find_all (返回一個列表 )
????????find all('a')?
????????find all(['a’,'span']) 返回所有的a和span
? .select(根據選擇器得到節點對象)[推薦]
????????element
? ? ? ? ? ? ? ? eg: div
????????class
? ? ? ? ? ? ? ? eg:.firstname
????????id
? ? ? ? ? ? ? ? eg:#firstname
????????屬性選擇器
????????????????eg:li = soup.select('li[class]')
????????????????eg:li = soup.select('li[class="hengheng"]')
????????層級選擇器
????????????????element element
? ? ? ? ? ? ? ? ? ????????div p
????????????????????????????????eg:soup = soup.select('a span')
????????????????element>element
? ? ? ? ? ? ? ? ? ? ? ? ??div>p
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??eg:soup = soup.select('a>span')
????????????????element,element
? ? ? ? ? ? ? ? ? ? ? ? ? div,p
????????????????????????????????eg:soup = soup.select('a,span')
BeautifulSoup節點信息
獲取節點內容
????????obj.string
????????obj.get_text()[推薦]?
獲取節點的屬性
????????eg:tag = find('li)
????????????????tag.name 獲取標簽名
????????????????tag.attrs將屬性值作為一個字典返回
獲取節點屬性
????????obj.attrs.get('title')[常用]
????????obj.get('title')
????????obj['title']
BeautifulSoup解析文件
以上述xpath中的本地文件Test.html為例,上邊已經寫過,這里直接上代碼
from bs4 import BeautifulSoupsoup = BeautifulSoup(open('Test.html',encoding='utf-8'),'lxml')# 查找第一個ul
print(soup.find("ul"))# 查找所有的ul
print(soup.find_all("ul"))# 選擇查找 li class為beijing的標簽
print(soup.select("li[class =beijing]"))#層級選擇查找ul下的class為beijing的li節點
nodeli=soup.select("ul li[class = beijing]")[0]# 獲取li節點內容
print(nodeli.get_text())# 獲取li標簽名
print(nodeli.name)#獲取li的屬性
print(nodeli.attrs)# 獲取li的id屬性
print(nodeli.attrs.get('id'))"""
輸出結果:
<ul>
<li class="beijing" id="00">北京</li>
<li>上海</li>
<li>深圳</li>
<li>廣州</li>
</ul>
[<ul>
<li class="beijing" id="00">北京</li>
<li>上海</li>
<li>深圳</li>
<li>廣州</li>
</ul>, <ul>
<li class="shenyang" id="11">沈陽</li>
<li>南京</li>
</ul>]
[<li class="beijing" id="00">北京</li>]
北京
li
{'id': '00', 'class': ['beijing']}
00"""