資料提取
結構化資料: json,xml
非結構化資料:Html,字元串
結構化資料處理的方式有:jsonpath,xpath,轉換python類型處理,bs4
非結構化資料處理方式有:正規表達式,xpath,bs4
1.用json子產品提取資料
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsICM38FdsYkRGZkRG9lcvx2bjxiNx8VZ6l2csc3aE9EeVpmYsBnMMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnL5MjN3QDNyYTM4IzNwkTMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
類檔案對象的了解:
具有read()或者write()方法的對象就是類檔案對象,比如f = open(“a.txt”,”r”) f就是類檔案對象
具體使用方法:
mydict = {
"name": "孫威",
"age": 16
}
#json.dumps 實作python類型轉化為json字元串
#indent實作換行和空格
#ensure_ascii=False實作讓中文寫入的時候保持為中文
json_str = json.dumps(mydict,indent=2,ensure_ascii=False)
#json.loads 實作json字元串轉化為python的資料類型
my_dict = json.loads(json_str)
#json.dump 實作把python類型寫入類檔案對象
with open("temp.txt","w") as f:
json.dump(mydict,f,ensure_ascii=False,indent=2)
# json.load 實作類檔案對象中的json字元串轉化為python類型
with open("temp.txt","r") as f:
my_dict = json.load(f)
# 或者my_dict = json.load(open("temp.txt","r"))
jsonpath子產品提取資料
jsonpath用來解析多層嵌套的json資料;JsonPath 是一種資訊抽取類庫,是從JSON文檔中抽取指定資訊的工具,提供多種語言實作版本,包括:Javascript, Python, PHP 和 Java。
jsonpath | 文法描述 |
---|---|
$ | 根節點 |
@ | 現行節點 |
. or [] | 子節點 |
. . | 不管位置,選取所有符合條件的條件 |
* | 比對所有元素節點 |
[] | 疊代器辨別,可以在裡面做簡單的疊代操作,如數組下标,根據内容選值 |
[,] | 支援疊代器中做多選 |
?() | 支援過濾操作 |
() | 支援表達式計算 |
- | 不支援去父節點 |
- | 不支援屬性通路 |
- | 不支援分組 |
# 文法使用示例
data = { "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
}
}
}
# 轉換成json格式的資料
data_dict = json.loads(data)
# 解析資料,傳回的是所有的author
result_list = jsonpath.jsonpath(data_dict, '$..author')
文法使用示例:
jsonpath | result |
---|---|
$.store.book[*].author | store中的所有的book的作者 |
$..author | 所有的作者 |
$.store.* | store下的所有的元素 |
$.store..price | store中的所有的内容的價格 |
$..book[2] | 第三本書 |
$..book[(@.length-1)] | $..book[-1:] | 最後一本書 |
$..book[0,1] | $..book[:2] | 前兩本書 |
$..book[?(@.isbn)] | 擷取有isbn的所有數 |
$..book[?(@.price<10)] | 擷取價格大于10的所有的書 |
$..* | 擷取所有的資料 |
2.正規表達式提取資料
3.xpath文法
XPath (XML Path Language) 是一門在 HTML\XML 文檔中查找資訊的語言,可用來在 HTML\XML 文檔中對元素和屬性進行周遊。
xpath文法
表達式 | 描述 |
---|---|
nodename | 選中該元素。 |
/ | 從根節點選取、或者是元素和元素間的過渡。 |
// | 從比對選擇的目前節點選擇文檔中的節點,而不考慮它們的位置。 |
. | 選取目前節點。 |
.. | 選取目前節點的父節點。 |
@ | 選取屬性。 |
text() | 選取文本。 |
執行個體
<bookstore>
<book>
<title lang="eng">Harry Potter</title>
<price>29.99</price>
</book>
<book>
<title lang="eng">Learning XML</title>
<price>39.95</price>
</book>
</bookstore>
路徑表達式 | 結果 |
---|---|
bookstore | 選擇bookstore元素。 |
/bookstore | 選取根元素 bookstore。注釋:假如路徑起始于正斜杠( / ),則此路徑始終代表到某元素的絕對路徑! |
bookstore/book | 選取屬于 bookstore 的子元素的所有 book 元素。 |
//book | 選取所有 book 子元素,而不管它們在文檔中的位置。 |
bookstore//book | 選擇屬于 bookstore 元素的後代的所有 book 元素,而不管 |
//book/title/@lang | 選擇所有的book下面的title中的lang屬性的值。 |
//book/title/text() | 選擇所有的book下面的title的文本。 |
//title[@lang=“eng”] | 選擇lang屬性值為eng的所有title元素 |
/bookstore/book[1] | 選取屬于 bookstore 子元素的第一個 book 元素。 |
/bookstore/book[last()] | 選取屬于 bookstore 子元素的最後一個 book 元素。 |
/bookstore/book[last()-1] | 選取屬于 bookstore 子元素的倒數第二個 book 元素。 |
/bookstore/book[position()>1] | 選擇bookstore下面的book元素,從第二個開始選擇 |
//book/title[text()=‘Harry Potter’] | 選擇所有book下的title元素,僅僅選擇文本為Harry Potter的title元素 |
/bookstore/book[price>35.00]/title | 選取 bookstore 元素中的 book 元素的所有 title 元素,且其中的 price 元素的值須大于 35.00。 |
/bookstore/* | 選取 bookstore 元素的所有子元素。 |
//* | 選取文檔中的所有元素。 |
//title[@*] | 選取所有帶有屬性的 title 元素。 |
注意點: 在xpath中,第一個元素的位置是1,最後一個元素的位置是last(),倒數第二個是last()-1
4.lxml子產品
lxml是一款高性能的 Python HTML/XML 解析器,我們可以利用XPath,來快速的定位特定元素以及擷取節點資訊
text = ''' <div> <ul>
<li class="item-1"><a href="link1.html" target="_blank" rel="external nofollow" >first item</a></li>
<li class="item-1"><a href="link2.html" target="_blank" rel="external nofollow" >second item</a></li>
<li class="item-inactive"><a href="link3.html" target="_blank" rel="external nofollow" >third item</a></li>
<li class="item-1"><a href="link4.html" target="_blank" rel="external nofollow" >fourth item</a></li>
<li class="item-0"><a href="link5.html" target="_blank" rel="external nofollow" >fifth item</a>
</ul> </div> '''
# 導入lxml 的 etree 庫
from lxml import etree
# 利用etree.HTML,将字元串轉化為Element對象,Element對象具有xpath的方法
html = etree.HTML(text)
#擷取href的清單和title的清單
href_list = html.xpath("//li[@class='item-1']/a/@href")
title_list = html.xpath("//li[@class='item-1']/a/text()")
我們取到屬性,或者是文本的時候,傳回字元串 但是如果我們取到的是一個節點,傳回的是element對象,可以繼續使用xpath方法
5.BeautifulSoup4
和 lxml 一樣,Beautiful Soup 也是一個HTML/XML的解析器,lxml 隻會局部周遊,而Beautiful Soup 是基于HTML DOM的,會載入整個文檔,解析整個DOM樹,是以時間和記憶體開銷都會大很多,是以性能要低于lxml。
html = """
<html><head><title>The Dormouse's story</title></head>
<body>
<p class="title" name="dromouse"><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" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" class="sister" id="link1"><!-- Elsie --></a>,
<a href="http://example.com/lacie" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" class="sister" id="link2">Lacie</a> and
<a href="http://example.com/tillie" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" class="sister" id="link3">Tillie</a>;
and they lived at the bottom of a well.</p>
<p class="story">...</p>
"""
# 導入 bs4 庫
from bs4 import BeautifulSoup
#建立 Beautiful Soup 對象
soup = BeautifulSoup(html)
# 傳字元串
print soup.find_all('a')
#[<a class="sister" href="http://example.com/elsie" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" id="link1"><!-- Elsie --></a>, <a class="sister" href="http://example.com/lacie" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" id="link2">Lacie</a>, <a class="sister" href="http://example.com/tillie" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" id="link3">Tillie</a>]
# 傳正規表達式
soup.find_all(re.compile("^b"))
# 傳清單
# keyword 參數
soup.find_all(class = "sister")
# text 參數
soup.find_all(text="Elsie")
# (1)通過标簽選擇器查找
print soup.select('title')
# (2)通過類選擇器查找
print soup.select('.sister')
# (3)通過 id 選擇器查找
print soup.select('#link1')
# (4)層級選擇器 查找
print soup.select('p #link1')
# (5)通過屬性選擇器查找
print soup.select('a[class="sister"]')
# (6) 擷取文本内容 get_text()
for title in soup.select('title'):
print title.get_text()
# (7) 擷取屬性 get('屬性的名字')
print soup.select('a')[0].get('href')
find_all(name, attrs, recursive, text, **kwargs):
查找所有名字為 name 的标簽
CSS選擇器:
通過标簽選擇器查找