与BeautifulSoup一样强的SimplifiedDoc,专为html抽取而生

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

posted @ 2019-12-05 18:03  dabingsou  阅读(828)  评论(0)    收藏  举报