1. 程式人生 > >Python網路爬蟲與資訊提取-Day9-資訊標記與提取方法

Python網路爬蟲與資訊提取-Day9-資訊標記與提取方法

一、資訊標記的三種形式

我們需要對資訊進行表記,使得我們能夠理解資訊所反饋的真實含義。

標記後的資訊可形成資訊組織結構,增加了資訊維度

標記的結構與資訊一樣具有重要價值

標記後的資訊可用於通訊、儲存或展示

標記後的資訊更利於程式理解和運用,也利於人對資訊的深入理解與運用

HTML的資訊標記

HTMLWWW(World Wide Web)的資訊組織方式

它能夠將聲音、影象、視訊等超文字資訊嵌入到文字中

HTML通過預定義的<>…</>標籤形式組織不同型別的資訊

現在國際公認的資訊標記格式有三種分別是XMLJSONYAML

XMLeXtensible Markup Language

)叫做擴充套件標記語言,它是一種與HTML很接近的標記語言。它以標籤(Tag)為主來標記資訊

<img src=“china.jpg” size=“10”> … </img>

它有名稱 Name和屬性Attribute

如果標籤中沒有內容,我們可以用相關的縮寫形式,用一個尖括號來表示一個標籤。

<img src=“china.jpg” size=“10” />空元素的縮寫形式

XML中也可以嵌入註釋,它以<!開頭,並且以>結尾

<!‐‐ This is a comment, very useful ‐‐>註釋書寫形式

可以說XMLHTML

發展以來的一種通用的資訊標記格式

JSONJavsScript Object Notation),它是JavaScript語言中面向物件的一種語言形式,簡單講JSON是一種有型別的鍵值對構建的資訊表達方式。鍵值對是key:value的一個組合,也就是給出一個資訊,並且對資訊內容做一個定義。其中對資訊型別的定義叫,對資訊值的描述叫value

要注意,無論是鍵還是值,它都通過增加雙引號來表示它是字串。說明它是一個有資料型別的鍵值對。

如果一個鍵對應多個值的時候,我們使用方括號加逗號[,]的形式來組織

鍵值對可以巢狀使用,也就是一個鍵值對放在另一個鍵值對的值的部分,在巢狀使用時,我們用大括號來表示

總結:JSON用有型別的鍵值把資訊組織起來

“key” : “value”

“key” : [“value1”, “value2”]

“key” : {“subkey” : “subvalue”}

JSON語言使用有型別的鍵值對,一個很大好處就是對於JavaScript等程式語言來說可以直接將JSON格式變為程式的一部分,使得編寫程式大大地簡化

YAMLYAML Ain’t Markup Language),它在命名的時候使用一種遞迴的定義。它也使用鍵值對,不過是無型別鍵值對key:value。可以用縮排來表達所屬的關係,用減號表達並列關係,用豎線表達整塊資料,用#表示註釋

key : value

key : #Comment

‐value1

‐value2

key :

subkey : subvalue

三種資訊標記形式的比較

XML例項:

<person>

<firstName>Tian</firstName>

<lastName>Song</lastName>

<address>

<streetAddr>中關村南大街5</streetAddr>

<city>北京市</city>

<zipcode>100081</zipcode>

</address>

<prof>Computer System</prof><prof>Security</prof>

</person>

每一個資訊域定義相關的標籤,並且用巢狀的形式組織起來

在整個文字中,有效資訊所佔的比例並不高,大多數資訊被標籤佔用

JSON例項:

{

firstName :Tian ,

lastName :Song ,

address  : {

streetAddr :“中關村南大街5號” ,

city  :“北京市” ,

zipcode  :100081

} ,

prof  : [ Computer System ,Security ]

}

JSON使用鍵值對的形式組織資訊,但是無論標籤還是後面的值,鍵值都要用雙引號來表達它們的型別

YAML例項:

firstName : Tian

lastName : Song

address  :

streetAddr : 中關村南大街5

city  : 北京市

zipcode : 100081

prof  :

Computer System

Security

用無型別的鍵值對來表示,很簡潔的關聯

XML:最早的通用資訊標記語言,可擴充套件性好,但繁瑣

JSON:資訊有型別,適合程式處理(js),較XML簡潔

YAML:資訊無型別,文字資訊比例最高,可讀性好

實際使用中:

XML:Internet上的資訊互動與傳遞

JSON:移動應用雲端和節點的資訊通訊,無註釋

YAML:各類系統的配置檔案,有註釋易讀

二、資訊提取的一般方式

資訊提取指,從標記後的資訊中提取所關注的內容。之前的XML,JSON,YAML的三種形式,無論哪種形式,在資訊提取中,包含標記,和資訊兩部分,我們關心的是所要提取出的內容

·方法一:完整解析資訊的標記形式,再提取關鍵資訊

用標記解析器去解析XML JSON YAML格式,然後將其中所需要的資訊提取出來

例如:bs4庫的標籤樹遍歷

優點:資訊解析準確

缺點:提取過程繁瑣,速度慢

·方法二:無視標記形式,直接搜尋關鍵資訊

對資訊的文字查詢函式即可

優點:提取過程簡潔,速度較快

缺點:提取結果準確性與資訊內容相關

·融合方法:結合形式解析與搜尋方法,提取關鍵資訊

XML JSON YAML 搜尋

需要標記解析器及文字查詢函式

例項:

提取HTML中所有URL連結

思路: 1) 搜尋到所有<a>標籤

2) 解析<a>標籤格式,提取href後的連結內容

import requests
r = requests.get("http://python123.io/ws/demo.html")
demo = r.text

from bs4 import BeautifulSoup
soup = BeautifulSoup(demo,"html.parser")
for link in soup.find_all('a'):
   print(link.get('href'))

http://www.icourse163.org/course/BIT-268001

http://www.icourse163.org/course/BIT-1001870001

三、基於bs4庫的HTML內容查詢方法

import requests
r = requests.get(“http://python123.io/ws/demo.html”)
demo = r.text

<>.find_all(name, attrs, recursive, string, **kwargs)

find_all方法可以在soup的變數中查詢裡面的資訊

它能夠返回一個列表型別,儲存查詢的結果

第一個引數name:對標籤名稱的檢索字串

from bs4 import BeautifulSoup
soup = BeautifulSoup(demo,"html.parser")
print(soup.find_all("a"))

[<a class="py1" href="http://www.icourse163.org/course/BIT-268001" id="link1">Basic Python</a>, <a class="py2" href="http://www.icourse163.org/course/BIT-1001870001" id="link2">Advanced Python</a>]

如果想要同時得到ab,則用一個方括號

print(soup.find_all(["a","b"]))

[<b>The demo python introduces several python courses.</b>, <a class="py1" href="http://www.icourse163.org/course/BIT-268001" id="link1">Basic Python</a>, <a class="py2" href="http://www.icourse163.org/course/BIT-1001870001" id="link2">Advanced Python</a>]

如果給出的標籤名稱是True,則顯示當前標籤的所有資訊

for tag in soup.find_all(True):
   print(tag.name)

html

head

title

body

p

b

p

a

a

我們看到這個文件中的所有標籤名稱被列印了出來

希望只顯示其中以b開頭的標籤,包括bbody標籤,就需要使用一個新的第三方庫,叫做“正則表示式庫”

首先引入這個庫

正則表示式反饋的結果是以b開頭的所有表達的資訊

import re
for tag in soup.find_all(re.compile('b')):
   print(tag.name)

body

b

attrs: 對標籤屬性值的檢索字串,可標註屬性檢索

我們查詢p標籤中中包含course字串的資訊

print(soup.find_all('p','course'))

[<p class="course">Python is a wonderful general-purpose programming language. You can learn Python from novice to professional by tracking the following courses:

<a class="py1" href="http://www.icourse163.org/course/BIT-268001" id="link1">Basic Python</a> and <a class="py2" href="http://www.icourse163.org/course/BIT-1001870001" id="link2">Advanced Python</a>.</p>]

我們也可以對屬性值作約定

print(soup.find_all(id='link1'))

[<a class="py1" href="http://www.icourse163.org/course/BIT-268001" id="link1">Basic Python</a>]

print(soup.find_all(id='link'))

[]

所以我們對屬性賦值要做精確的賦值

如果我們需要查詢包含link的屬性,我們就需要引入正則表示式庫

print(soup.find_all(id=re.compile('link')))

[<a class="py1" href="http://www.icourse163.org/course/BIT-268001" id="link1">Basic Python</a>, <a class="py2" href="http://www.icourse163.org/course/BIT-1001870001" id="link2">Advanced Python</a>]

正則表示式就像平常搜尋一樣搜尋詞的一部分,如果不使用正則表示式就需要完整準確地給出詞的資訊,不多也不少

recursive: 是否對子孫全部檢索,預設True

如果我們只需要搜尋兒子這一層面的資訊,我們就把recursive設為False

print(soup.find_all('a',recursive=False))

[]

string: <></>中字串區域的檢索字串

print(soup.find_all(string='Basic Python'))

['Basic Python']

print(soup.find_all(string=re.compile('python')))

['This is a python demo page', 'The demo python introduces several python courses.']

<tag>(..) 等價於 <tag>.find_all(..)

soup(..)  等價於 soup.find_all(..)

拓展方法

方法

說明

<>.find()

搜尋且只返回一個結果,同.find_all()引數

<>.find_parents()

在先輩節點中搜索,返回列表型別,同.find_all()引數

<>.find_parent()

在先輩節點中返回一個結果,同.find()引數

<>.find_next_siblings()

在後續平行節點中搜索,返回列表型別,同.find_all()引數

<>.find_next_sibling()

在後續平行節點中返回一個結果,同.find()引數

<>.find_previous_siblings()

在前序平行節點中搜索,返回列表型別,同.find_all()引數

<>.find_previous_sibling()

在前序平行節點中返回一個結果,同.find()引數

區別僅在於查詢區域的不同以及檢索返回的結果個數不同