python笔记

BeautifulSoup常用操作

2017-06-24  本文已影响981人  我是一只菜鸟呀

  BeautifulSoup是用来从HTML or XML中提取数据的Python lib,处理高效,并且支持多种解析器。利用它不用编写正则表达式,就能方便抓取网页信息。参考

解析器

注意:同一篇文档被不同的解析器可能解析成不同结构的树型文档。参考

一、安装

pip install beautifulsoup4

二、四大对象

  Beautiful Soup将复杂HTML文档转换成一个复杂的树形结构,每个节点都是Python对象,所有对象可以归纳为4种:Tag,NavigableString,BeautifulSoup,Comment.

Tag标签

主要有两个属性:name和attributes,has_attr()方法

name属性

name就是获得标签自己的名字(感觉没啥用)。

attributes属性

可以通过attrs来获得该标签的所有属性。返回字典。

soup.p.attrs

可以通过['']的形式来获得、修改、删除每一个属性的值

print(p['class'])    #或者p.get('class')

p['class'] = 'hello'

del p['class']

注:对于html文档,有些属性是有多个属性值的,通过属性来取属性值时,返回的是list形式的属性值,例如:class等。但是对于XML文档,返回的是一整个字符串。

#html

css_soup=BeautifulSoup('<p class="body strikeout"/>')
css_soup.p['class']
# ["body", "strikeout"]

#xml

xml_soup=BeautifulSoup('<p class="body strikeout"/>','xml')
xml_soup.p['class']

#"body strikeout"

has_attr()方法

返回True或者False

NavigableString标签

字符串常被包含在tag内.Beautiful Soup用NavigableString类来包装tag中的字符串:通过string来获得。

p.string

tag中包含的字符串不能编辑,但是可以被替换成其它的字符串,用replace_with()方法:

p.string.replace_with("hello world!")

BeautifulSoup对象

表示的是一个文档的全部内容.大部分时候,可以把它当作Tag对象,但是,BeautifulSoup对象并不是真正的HTML或XML的tag,所以它没有name和attribute属性。

printsoup.name

# [document]

printsoup.attrs

#{} 空字典

comment注释对象

Comment对象是一个特殊类型的NavigableString对象:

markup="<p><!--hello--><\p>"
soup=BeautifulSoup(markup)

print(soup.p.string)

#hello

print(type(soup.p.string))

#<'class bs4.element.Comment'>

  我们知道p标签的内容是注释,但是如果我们利用 .string 来输出它的内容,我们发现它已经把注释符号去掉了,所以这可能会给我们带来不必要的麻烦。因此在使用前可以先判断:

ift ype(soup.a.string)==bs4.element.Comment:

print soup.a.string

Beautiful Soup中定义的其它类型都可能会出现在XML的文档中:CData, ProcessingInstruction,Declaration,Doctype.与Comment对象类似,这些类都是NavigableString的子类。

三、节点的定位

1.直接标签名--找到第一个

通过直接“.标签名”的方式来获取。

注意:1)这种方式只能获取到第一个标签噢。2)可以多次调用噢。也就是.标签名.标签名...3)不一定非要一级一级的标签来找哦,可以直接找孙子节点哦

soup.body.p.a

soup.body.a #直接定位到孙子噢

2.通过CSS选择器定位

通过css选择器的select()来定位,返回list噢

1)通过标签名找所有节点

soup.select("p")   #返回标签名为p的所有节点的list

2)通过类名查找所有节点,类名前面加“.”噢

soup.select(".sister")   #返回class属性值为sister的所有节点的list

3)通过id查找所有节点,id前面加“#”噢

soup.select("#hello")   #返回id为hello的所有节点的list

4)通过属性查找所有节点

soup.select('a[href="http://example.com/elsie"]')   #返回属性href为。。。的所有a的list

注意:属性用[]括起来,且与标签中间没有空格,注意与5的区别

5)混合方式查找所有节点

混合查找中,空格表示的是“递进”的意思哦,即和写 class 文件时,标签名与类名、id名进行的组合原理是一样的

soup.select("p   #.sister")   #返回p的子节点中,class属性为sister的所有节点的list

3.find_all( name , attrs , recursive , text , **kwargs )--寻找符合条件的Tag节点噢

搜索当前tag的所有tag子节点,注意,只查找Tag节点噢。参考:http://cuiqingcai.com/1319.html#crayon-594dac2620deb589249952

还有类似的find开头的函数,其实都是在之前的属性上,添加了一些过滤条件而已。

4.NavigableString节点的获得

1)获得单个--属性.string

通过父节点的".string"属性,就可以获得NavigableString节点噢

doc = "<html><title>hello</title></html>"

soup.title.string    #hello

soup.html.string   #hello

注意:

a. 如果一个标签里面只有NavigableString节点了,那么 .string 就会返回标签里面的内容。如果标签里面只有唯一的一个标签了,那么 .string 也会返回最里面的内容。

b. 如果一个标签里有多个子标签,那么.string就会返回None。

2)获得多个--strings属性

  通过.strings属性可以获得某个节点下所有的NavigableString节点(也就是字符串啦,名字高大上一点喽)。但是它会包含很多的空白符噢。返回的是generator噢

3)获得多个--stripped_string属性(去除空白符)

就是比strings返回的结果少了空白符啦,其他没啥区别哟

5.枚举所有子节点

1)枚举直接子节点

a.属性contents,返回列表

b.属性children,返回生成器(generator),可以通过for来获得。

soup.body.contents

for item in soup.body.children:

        print(item)

注意:string没有这两个属性,强行获得会报错

2)枚举所有子节点

a.属性descendants----以深度搜索的方式返回generator

6.获得父节点

1)直接父节点

属性parent

soup.p.parent  #body

2)所有父节点

属性parents,返回generator

7.获得兄弟节点

1)相邻兄弟节点

属性.next_sibling 和 .previous_sibling

<a>tim</a>

<a>lucy</a>

soup.a.next_sibling  #'\n'


<a>tim</a><a>lucy</a>

soup.a.next_sibling  #'<a>lucy</a>'

注意:NavigableString节点和其他标签节点也是兄弟关系噢

2)所有相邻节点

.next_siblings 和 .previous_siblings属性

8.解析过程中的相邻节点

1)直接相邻节点

HTML解析器会按照节点出现,将字符串转换成一些列的事件。Beautiful Soup提供了重现解析器初始化过程的方法。属性:.next_element 和 .previous_element

<p>hello<a>world</a></p>

soup.p.next_element  #hello

soup.p.next_element.next_element  #<a>world</a>

2)所有相邻节点

属性.next_elements 和 .previous_elements

四、其他

prettify():格式化输出html和xml,还能自动补全。

上一篇下一篇

猜你喜欢

热点阅读