在Python中,說到html解析,很多人都會推薦使用BeautifulSoup。BeautifulSoup確實是一款功能強大,使用比較簡單的html解析器。但是這里要講的SimplifiedDoc一樣是使用簡單功能強大且專為html抽取而生的。這里說的抽取和解析的意思有點不同,解析是把字符串html 解析成對象,抽取是將html中的有用數據取出來。也就是說SimplifiedDoc重點不在解析,而是抽取出用戶想要的數據。通過下面的例子,大家也許會能明白這一點。
首先是安裝pip install simplified-scrapy
,這個庫同時支持Python2和Python3。
安裝后,可以體驗一下:
from simplified_scrapy.simplified_doc import SimplifiedDoc doc = SimplifiedDoc('<p class="test">Hello</p>') print(doc.getElementByTag('p'))
將html標簽生成為字典返回,運行結果如下
{'class': 'test', 'tag': 'p', 'html': 'Hello'}
上面是一個簡單的開胃小菜,其它的菜咱們慢慢來。
html = """ <html><head><title>The Dormouse's story</title></head> <body> <p class="title" name="dromouse" other="test"><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" 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> </body> """ doc = SimplifiedDoc(html) print (doc.title) print (doc.title.text) print (doc.head) print (doc.head.title)
用法和BeautifulSoup有點像,但結果不同,這里返回的是字典
{'tag': 'title', 'html': "The Dormouse's story"} The Dormouse's story {'tag': 'head', 'html': "<title>The Dormouse's story</title>"} {'tag': 'title', 'html': "The Dormouse's story"}
如果想抽取里面的所有鏈接數據,如下:
doc = SimplifiedDoc(html) print (doc.getElementsByTag('a'))
因為是專為抽取而生,鏈接數據必須要特殊照顧,還可以用下面的方式取到。如果這時傳入當前頁面的鏈接地址,返回的數據會自動把相對路徑轉為全路徑。
doc = SimplifiedDoc(html) print (doc.listA())
一個標簽可能有多個屬性,比如id,class等,還有內部等html標簽。其實這些數據都在返回的對象里了。
doc = SimplifiedDoc(html) print (doc.p)
運行結果如下
{'class': 'title', 'name': 'dromouse', 'tag': 'p', 'html': "<b>The Dormouse's story</b>"}
如果想要獲取到去掉html標簽的文本數據,可以直接調用text屬性,雖然返回的字典中沒有這個屬性。
doc = SimplifiedDoc(html) print (doc.p.text)
運行結果如下
The Dormouse's story
對嵌套數據的處理,例子如下
from simplified_scrapy.simplified_doc import SimplifiedDoc html = """ <body> <article> <div>this is noise</div> <h1>this is title</h1> <div>this is content</div> </article> </body> """ doc = SimplifiedDoc(html) print (doc.body.article.h1) print (doc.h1)
上面的兩行輸出的結果是一樣,在使用中,我們盡量選擇短的路徑,提高解析速度。article中有兩個div,如果我們想要第二個div,該怎么做呢。這兩個div標簽中都沒有屬性數據,如果有屬性數據,我們可以根據屬性來區分。這里我們可以根據序號來獲取,如下:
doc = SimplifiedDoc(html) print (doc.article.getElementsByTag('div')[1])
如果干擾的div數量不確定時,這種辦法就不可用了。上面說了,SimplifiedDoc是為抽取而生的,與BeautifulSoup的區分就在這里了。我們可以設定起止位置進行抽取。這里我們要抽取的數據在h1標簽之后,就可以用下面的方式去取。
doc = SimplifiedDoc(html) print (doc.article.getElementByTag('div',start='<h1>'))
SimplifiedDoc中的每個抽取方法,都包含三個參數(start,end,before),在適當的時候可以處理其它工具不容易抽取的數據。
如果h1標簽上面只有一個干擾div,我們想獲取article標簽內的所有數據,我們還可以使用removeElement方法:
doc = SimplifiedDoc(html) print (doc.article.removeElement('div'))
運行結果如下:
{'tag': 'article', 'html': '<h1>this is title</h1><div>this is content</div>'}
對於SimplifiedDoc,還有其它的技巧需要自己去探索了。