BeautifulSoup作为一个强大的从HTML或则XML文件中提取数据的Python库,它能通过解析文档为用户提供需要抓取的数据。同时,它可以很好的处理不规范标记并生成剖析树(parse tree)并提供简单又常用的导航(navigating),搜索以及修改剖析树的操作。它可以大大节省你的编程时间。
接下来归纳一下之前在看书过程中发现的一些不懂的对数据爬取得方法
先给出官方文档:http://beautifulsoup.readthedocs.io/zh_CN/latest/
解释器
Beautiful Soup支持Python标准库中的HTML解析器,还支持一些第三方的解析器,其中包括 lxml 和 html5lib 。可以通过pip或easy_install来安装这两个解释器。这几者之间的差别见这里。
首先,Beautifulsoup将复杂的HTML或者XML文件解析成复杂的树形结构,每个节点都是Python对象,所有的4个节点可以分为:Tag,NavigableString,BeautifulSoup,Comment。
Tag与HTML原生文档中的Tag标签一致
例如:
soup=BeautifulSoup('
a=soup.title
print(a)
输出结果为
Tag中有两个重要的属性:name和attributes.
每个Tag都有自己的名字,例如同样是上面的例子:
soup=BeautifulSoup('
a=soup.title
a=a.name
print(a)
输出结果:title
总结:Tag的name属性即为标签的名字,可以通过’.’操作符进行访问
attributes代表的是Tag标签内的属性,例如: This is paragraph one. This is paragraph one.
soup=BeautifulSoup('
a=soup.p
a=a['id']
print(a)
输出结果为:firstpara
同时,Python提供了attrs方法以字典的形式返回Tag内的所有属性。例如:
soup=BeautifulSoup('
a=soup.p
a=a.attrs
print(a)
输出结果为:{'id': 'firstpara', 'align': 'center'}
既然我们已经得到了标签的内容,那么要想获取标签内部的文字怎么办呢?很简单,用 .string 即可,例如
This is paragraph soup=BeautifulSoup('
a=soup.string
print(a)
输出结果为:This is paragraph
它的类型是一个 NavigableString,翻译过来叫 可以遍历的字符串,不过我们最好还是称它英文名字吧
BeautifulSoup
BeautifulSoup对象表示的是一个文档的全部内容。大部分时候,可以把它当作 Tag 对象,它支持遍历文档树和搜索文档树中描述的大部分的方法.
因为 BeautifulSoup 对象并不是真正的HTML或XML的tag,所以它没有name和attribute属性。但有时查看它的.name 属性是很方便的,所以 BeautifulSoup 对象包含了一个值为[document]的特殊属性 .name
例如:
soup=BeautifulSoup('
a=soup.name
print(a)
输出结果为:[document]
Comment 对象是一个特殊类型的 NavigableString 对象:
markup = ""
soup = BeautifulSoup(markup)
comment = soup.b.string
type(comment)
输出结果为:
b标签里的内容实际上是注释,但是如果我们利用 .string 来输出它的内容,我们发现它已经把注释符号去掉了,所以这可能会给我们带来不必要的麻烦。
另外我们打印输出下它的类型,发现它是一个 Comment 类型,所以,我们在使用前最好做一下判断,判断代码如下
if type(soup.b.string)==bs4.element.Comment:
print soup.a.string
上面说到过,BeautifulSoup将复杂的HTML或者XML文件解析成复杂的树形结构,每个节点都是Python对象。所以parent方法顾名思义,代表的是父节点。通过.parent可以访问某标签的上一个标签 This is paragraph one. This is paragraph two. This is paragraph three.
例如:
doc = ['
'
'
'
'']
soup = BeautifulSoup(''.join(doc),'html.parser')
v=soup.p
c=v.parent.name
print(c)
输出结果为body
从doc中可以看出p标签的上一个标签(父标签)为body
parent方法用于向上遍历树节点,contents方法用于向下遍历树节点,即向下访问某节点的子节点。
tag的.contents 属性可以将tag的子节点以列表的方式输出。
例如同样是上面的例子:
soup = BeautifulSoup(''.join(doc),'html.parser')
v=soup.p
c=v.contents
print(c)
输出结果为:['This is paragraph ', one, '.']
又如:soup = BeautifulSoup(”.join(doc),’html.parser’)
v=soup.head
a=v.contents
b=v.contents[0]
c=b.contents
print(a)
print(b)
print(c)
输出结果为:[
['Page title']
在b=v.contents[0]
这一行代码中,因为v.contents返回的是列表,所以不能直接用a.contents取出标签title中的内容,只能将列表中的Tag取出,在访问子节点。
为了方便,如果一个标签只有一个子节点,而且该子节点还是字符串类型的,则该子节点可以通过tag.string的形式访问。同时,如果一个节点仅有一个子节点,则该子节点也可以用.string进行访问,输出结果与当前唯一子节点的 .string 结果相同。
例如:
soup = BeautifulSoup(''.join(doc),'html.parser')
v=soup.b
b=v.string
print(b)
输出结果为:one
soup.b返回包含标签b的字典。因为b标签仅有一个子节点,且该子节点是字符串类型(同时也满足仅有一个子节点的条件),所以可以直接用.string方法访问该子节点。
注意:soup.p.string返回的是None,因为p标签的子节点并不是只有一个,而是有多个子节点,这时候不满足使用string的条件,所以会返回None。同时虽然 Tag只有一个子节点,但是这个子节点是Tag类型 (
), 不是NavigableString。