二: 爬蟲的數據解析的三種方式

二、爬蟲數據解析的三方式

 

一.正則表達式解析

經常使用正則表達式回顧:javascript

官方文檔html

點擊這裏
單字符:
        . : 除換行之外全部字符
        [] :[aoe] [a-w] 匹配集合中任意一個字符
        \d :數字  [0-9] \D : 非數字 \w :數字、字母、下劃線、中文 \W : 非\w \s :全部的空白字符包,括空格、製表符、換頁符等等。等價於 [ \f\n\r\t\v]。 \S : 非空白 數量修飾: * : 任意屢次 >=0 + : 至少1次 >=1 ? : 無關緊要 0次或者1次 {m} :固定m次 hello{3,} {m,} :至少m次 {m,n} :m-n次 邊界: $ : 以某某結尾 ^ : 以某某開頭 分組: (ab) 貪婪模式: .* 非貪婪(惰性)模式: .*? re.I : 忽略大小寫 re.M :多行匹配 re.S :單行匹配 re.sub(正則表達式, 替換內容, 字符串)

二 Xpath解析

XPath在Python的爬蟲學習中,起着舉足輕重的地位,對比正則表達式 re二者能夠完成一樣的工做,實現的功能也差很少,但XPath明顯比re具備優點,在網頁分析上使re退居二線。html5

xpath官方文檔java

點擊這裏

測試頁面數據

<html lang="en"> <head> <meta charset="UTF-8" /> <title>測試bs4</title> </head> <body> <div> <p>百里守約</p> </div> <div class="song"> <p>李清照</p> <p>王安石</p> <p>蘇軾</p> <p>柳宗元</p> <a href="http://www.song.com/" title="趙匡胤" target="_self"> <span>this is span</span> 宋朝是最強大的王朝,不是軍隊的強大,而是經濟很強大,國民都頗有錢</a> <a href="" class="du">總爲浮雲能蔽日,長安不見令人愁</a> <img src="http://www.baidu.com/meinv.jpg" alt="" /> </div> <div class="tang"> <ul> <li><a href="http://www.baidu.com" title="qing">清明時節雨紛紛,路上行人慾斷魂,借問酒家何處有,牧童遙指杏花村</a></li> <li><a href="http://www.163.com" title="qin">秦時明月漢時關,萬里長征人未還,但使龍城飛將在,不教胡馬度陰山</a></li> <li><a href="http://www.126.com" alt="qi">岐王宅裏尋常見,崔九堂前幾度聞,正是江南好風景,落花時節又逢君</a></li> <li><a href="http://www.sina.com" class="du">杜甫</a></li> <li><a href="http://www.dudu.com" class="du">杜牧</a></li> <li><b>杜小月</b></li> <li><i>度蜜月</i></li> <li><a href="http://www.haha.com" id="feng">鳳凰臺上鳳凰遊,鳳去臺空江自流,吳宮花草埋幽徑,晉代衣冠成古丘</a></li> </ul> </div> </body> </html>

經常使用xpath表達式

'''
屬性定位:
    #找到class屬性值爲song的div標籤 //div[@class="song"] 層級&索引定位: #找到class屬性值爲tang的div的直系子標籤ul下的第二個子標籤li下的直系子標籤a //div[@class="tang"]/ul/li[2]/a 邏輯運算: #找到href屬性值爲空且class屬性值爲du的a標籤 //a[@href="" and @class="du"] 模糊匹配: //div[contains(@class, "ng")] //div[starts-with(@class, "ta")] 取文本: # /表示獲取某個標籤下的文本內容 # //表示獲取某個標籤下的文本內容和全部子標籤下的文本內容 //div[@class="song"]/p[1]/text() //div[@class="tang"]//text() 取屬性: //div[@class="tang"]//li[2]/a/@href '''

代碼中使用xpath表達式進行數據解析

1.下載:pip install lxml 2.導包:from lxml import etree 3.將html文檔或者xml文檔轉換成一個etree對象,而後調用對象中的方法查找指定的節點   2.1 本地文件:tree = etree.parse(文件名) tree.xpath("xpath表達式")   2.2 網絡數據:tree = etree.HTML(網頁內容字符串) tree.xpath("xpath表達式")

三 Beautiful Soup

3.1 簡介

簡單來講,Beautiful Soup是python的一個庫,最主要的功能是從網頁抓取數據。官方解釋以下:python

'''
Beautiful Soup提供一些簡單的、python式的函數用來處理導航、搜索、修改分析樹等功能。
它是一個工具箱,經過解析文檔爲用戶提供須要抓取的數據,由於簡單,因此不須要多少代碼就能夠寫出一個完整的應用程序。
'''正則表達式

Beautiful Soup 是一個能夠從HTML或XML文件中提取數據的Python庫.它可以經過你喜歡的轉換器實現慣用的文檔導航,查找,修改文檔的方式.Beautiful Soup會幫你節省數小時甚至數天的工做時間.你可能在尋找 Beautiful Soup3 的文檔,Beautiful Soup 3 目前已經中止開發,官網推薦在如今的項目中使用Beautiful Soup 4。瀏覽器

安裝

pip3 install beautifulsoup4

解析器

Beautiful Soup支持Python標準庫中的HTML解析器,還支持一些第三方的解析器,若是咱們不安裝它,則 Python 會使用 Python默認的解析器,lxml 解析器更增強大,速度更快,推薦安裝。markdown

pip3 install lxml

另外一個可供選擇的解析器是純Python實現的 html5lib , html5lib的解析方式與瀏覽器相同,能夠選擇下列方法來安裝html5lib:網絡

pip install html5lib

解析器對比:
函數

3.2 BS語法

官方文檔

點擊這裏

使用流程:

- 導包:from bs4 import BeautifulSoup - 使用方式:能夠將一個html文檔,轉化爲BeautifulSoup對象,而後經過對象的方法或者屬性去查找指定的節點內容 (1)轉化本地文件: - soup = BeautifulSoup(open('本地文件'), 'lxml') (2)轉化網絡文件: - soup = BeautifulSoup('字符串類型或者字節類型', 'lxml') (3)打印soup對象顯示內容爲html文件中的內容

基礎鞏固:

1)根據標籤名查找 - soup.a 只能找到第一個符合要求的標籤 (2)獲取屬性 - soup.a.attrs 獲取a全部的屬性和屬性值,返回一個字典 - soup.a.attrs['href'] 獲取href屬性 - soup.a['href'] 也可簡寫爲這種形式 (3)獲取內容 - soup.a.string - soup.a.text - soup.a.get_text() 【注意】若是標籤還有標籤,那麼string獲取到的結果爲None,而其它兩個,能夠獲取文本內容 (4)find:找到第一個符合要求的標籤 - soup.find('a') 找到第一個符合要求的 - soup.find('a', title="xxx") - soup.find('a', alt="xxx") - soup.find('a', class_="xxx") - soup.find('a', id="xxx") (5)find_all:找到全部符合要求的標籤 - soup.find_all('a') - soup.find_all(['a','b']) 找到全部的a和b標籤 - soup.find_all('a', limit=2) 限制前兩個 (6)根據選擇器選擇指定的內容 select:soup.select('#feng') - 常見的選擇器:標籤選擇器(a)、類選擇器(.)、id選擇器(#)、層級選擇器 - 層級選擇器: div .dudu #lala .meme .xixi 下面好多級 div > p > a > .lala 只能是下面一級 【注意】select選擇器返回永遠是列表,須要經過下標提取指定的對象

重點方法

BeautifulSoup定義了不少搜索方法,這裏着重介紹2個: find() 和 find_all() .其它方法的參數和用法相似

一、find_all()方法

#搜索文檔樹:BeautifulSoup定義了不少搜索方法,這裏着重介紹2個: find() 和 find_all() .其它方法的參數和用法相似 html_doc = """ <html><head><title>The Dormouse's story</title></head> <body> <p id="my p" class="title"><b id="bbb" class="boldest">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" class="sister" id="link1">Elsie</a>, <a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and <a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>; and they lived at the bottom of a well.</p> <p class="story">...</p> """ from bs4 import BeautifulSoup soup=BeautifulSoup(html_doc,'lxml') #一、name的五種過濾器: 字符串、正則表達式、列表、True、方法 #1.一、字符串:即標籤名 print(soup.find_all('b')) #1.二、正則表達式 import re print(soup.find_all(re.compile('^b'))) #找出b開頭的標籤,結果有body和b標籤 #1.三、列表:若是傳入列表參數,Beautiful Soup會將與列表中任一元素匹配的內容返回.下面代碼找到文檔中全部<a>標籤和<b>標籤: print(soup.find_all(['a','b'])) #1.四、True:能夠匹配任何值,下面代碼查找到全部的tag,可是不會返回字符串節點 print(soup.find_all(True)) for tag in soup.find_all(True): print(tag.name) #1.五、方法:若是沒有合適過濾器,那麼還能夠定義一個方法,方法只接受一個元素參數 ,若是這個方法返回 True 表示當前元素匹配而且被找到,若是不是則反回 False def has_class_but_no_id(tag): return tag.has_attr('class') and not tag.has_attr('id') print(soup.find_all(has_class_but_no_id)) #二、按照類名查找,注意關鍵字是class_,class_=value,value能夠是五種選擇器之一 print(soup.find_all('a',class_='sister')) #查找類爲sister的a標籤 print(soup.find_all('a',class_='sister ssss')) #查找類爲sister和sss的a標籤,順序錯誤也匹配不成功 print(soup.find_all(class_=re.compile('^sis'))) #查找類爲sister的全部標籤 #三、attrs print(soup.find_all('p',attrs={'class':'story'})) #四、text: 值能夠是:字符,列表,True,正則 print(soup.find_all(text='Elsie')) print(soup.find_all('a',text='Elsie')) #五、limit參數:若是文檔樹很大那麼搜索會很慢.若是咱們不須要所有結果,可使用 limit 參數限制返回結果的數量.效果與SQL中的limit關鍵字相似,當搜索到的結果數量達到 limit 的限制時,就中止搜索返回結果 print(soup.find_all('a',limit=2)) #六、recursive:調用tag的 find_all() 方法時,Beautiful Soup會檢索當前tag的全部子孫節點,若是隻想搜索tag的直接子節點,可使用參數 recursive=False . print(soup.html.find_all('a')) print(soup.html.find_all('a',recursive=False)) ''' 像調用 find_all() 同樣調用tag find_all() 幾乎是Beautiful Soup中最經常使用的搜索方法,因此咱們定義了它的簡寫方法. BeautifulSoup 對象和 tag 對象能夠被看成一個方法來使用, 這個方法的執行結果與調用這個對象的 find_all() 方法相同,下面兩行代碼是等價的: soup.find_all("a") soup("a") 這兩行代碼也是等價的: soup.title.find_all(text=True) soup.title(text=True) '''

二、find( name , attrs , recursive , text , **kwargs )

find_all() 方法將返回文檔中符合條件的全部tag,儘管有時候咱們只想獲得一個結果.好比文檔中只有一個<body>標籤,那麼使用 find_all() 方法來查找<body>標籤就不太合適, 使用 find_all 方法並設置 limit=1 參數不如直接使用 find() 方法.下面兩行代碼是等價的: soup.find_all('title', limit=1) # [<title>The Dormouse's story</title>] soup.find('title') # <title>The Dormouse's story</title> 惟一的區別是 find_all() 方法的返回結果是值包含一個元素的列表,而 find() 方法直接返回結果. find_all() 方法沒有找到目標是返回空列表, find() 方法找不到目標時,返回 None . print(soup.find("nosuchtag")) # None soup.head.title 是 tag的名字方法的簡寫.這個簡寫的原理就是屢次調用當前tag的 find() 方法: soup.head.title # <title>The Dormouse's story</title> soup.find("head").find("title") # <title>The Dormouse's story</title>
相關文章
相關標籤/搜索