在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,还有其它的技巧需要自己去探索了。