Python BS4学习笔记

BS4库的基本用法

1 简介,四大对象

BeautifulSoup 就是 Python 的一个 HTML 或 XML 的解析库,我们可以用它来方便地从网页中提取数据,

BeautifulSoup 在解析的时候实际上是依赖于解析器的,它除了支持 Python 标准库中的 HTML 解析器,还支持一些第三方的解析器比如 LXML,日常中推荐LXML ,这个解析器有解析 HTML 和 XML 的功能,而且速度快,容错能力强,所以推荐使用这个解析器来进行解析。

BeautifulSoup将复杂的HTML文档装换成一个复杂的树形结构,每个节点都是python对象,可归纳为四种:Tag、Navigablestring、Comment、BeautifulSoup.
soupobj=BeautifulSoup(html,'lxml')
print(type(soupobj))
print(type(soupobj.a))
print(type(soupobj.p.string))

#output
<class 'bs4.BeautifulSoup'>
<class 'bs4.element.Tag'>
<class 'bs4.element.NavigableString'>

2 BeautifulSoup四大对象之Tag对象:html中的一个个标签,html标签加上里面的内容就是Tag。

  1. 可以利用soup_obj加标签名获取这些标签内容,但它只返回所有内容中的第一个符合要求的标签。
soupobj=BeautifulSoup(html,'lxml')
print(soupobj.head)
print(soupobj.head.title) #直接输出节点里面的内容,包括节点本身

#output
<head><title>The HTML is for test BeautifulSoup</title></head>
<title>The HTML is for test BeautifulSoup</title>
  1. Tag的两个重要属性name和attrs
soupobj=BeautifulSoup(html,'lxml')
print(soupobj.a.name)
print(soupobj.a.attrs) #返回字典
print(soupobj.a.attrs['class'])#几种访问具体属性的方法
print(soupobj.a['class'])
print(soupobj.a.get('class'))

#output
a
{'id': 'link1', 'href': 'http://www.baidu.com', 'class': ['sister']}
['sister']
['sister']
['sister']

3 NavigableString对象

已经得到了标签,如何获得标签内的文字。

soupobj=BeautifulSoup(html,'lxml')
print(soupobj.p.string)
print(soupobj.p.get_text()) #两种方法访问节点的字符串
print(type(soupobj.p.string))
#output:
this is title
this is title
<class 'bs4.element.NavigableString'>

4 Comment对象,比较少用

Tag , NavigableString , BeautifulSoup 几乎覆盖了html和xml中的所有内容,
但是还有一些特殊对象.容易让人担心的内容是文档的注释部分,Comment 对象是一个特殊类型的 NavigableString 对象:

markup = "<b><!--Hey, buddy. Want to buy a used parser?--></b>"
soup = BeautifulSoup(markup,'lxml')
comment = soup.b.string
print(comment)
print(type(comment))

#output
Hey, buddy. Want to buy a used parser?
<class 'bs4.element.Comment'>

5 BeautifulSoup对象

BeautifulSoup 对象表示的是一个文档的全部内容.大部分时候,可以把它当作 Tag 对象,它支持 遍历文档树 和 搜索文档树 中描述的大部分的方法.

因为 BeautifulSoup 对象并不是真正的HTML或XML的tag,所以它没有name和attribute属性.但有时查看它的 .name 属性是很方便的,所以 BeautifulSoup 对象包含了一个值为 “[document]” 的特殊属性 .name

6 遍历文档树

  1. 理解子节点

一个Tag可能包含多个字符串或其它的Tag,这些都是这个Tag的子节点.Beautiful Soup提供了许多操作和遍历子节点的属性.

注意: Beautiful Soup中字符串节点不支持这些属性,因为字符串没有子节点

  1. .contents 和 .children
  • tag的 .contents 属性可以将tag的子节点以列表的方式输出:
soupobj=BeautifulSoup(html,'lxml')

print(soupobj.body.contents) #tag的 .contents 属性可以将tag的子节点以列表的方式输出:
for i in soupobj.body.contents:
print(i.name)#输出直接子节点,内嵌在子节点里面的节点不输出

#output
None
p
None
p
None
p
None
  • .children属性返回一个子节点的列表迭代器
soupobj=BeautifulSoup(html,'lxml')
i=soupobj.body.children #返回一个子节点的列表迭代器
print(i)
for elem in i:
print(elem.name)

#output:
<list_iterator object at 0x101a88160>
None
p
None
p
None
p
None
  • .contents 和 .children 属性仅包含tag的直接子节点.例如,标签只有一个直接子节点
soupobj=BeautifulSoup(html,'lxml')
i=soupobj.body.descendants #返回一个子孙节点的生成器
print(i)
for elem in i:
print(elem.name)

#output

<generator object descendants at 0x1041de728>
None
p
b
None
None
p
None
a
None
None
a
None
None
None
p
None
None
  • 兄弟节点的 .next_sibling, .previous_sibling属性,全部兄弟节点的.next_siblings, .previous_siblings属性

7 搜索文档树

  1. find_all(name,attrs,recursive,text,limit,**kwargs)方法

搜索当前tag的所有tag子节点,并判断是否符合过滤器条件。

  • name参数:可以查找所有名字为name的tag,字符串对象会被自动忽略掉,函数返回一个list,name参数可以是字符串,正则,列表,True,
    还可以传方法等
soupobj=BeautifulSoup(html,'lxml')

for i in soupobj.find_all(re.compile('e')):#传入正则,调用search()方法
print(i.name)
for i in soupobj.find_all(['a','b']):#传入列表
print(i.name)
for i in soupobj.find_all('title'):#传入字符串
print(i.name)
for i in soupobj.find_all(True):#传入TRUE
print(i.name)

#output:
body
b
  1. **kwargs参数:关键字参数,如果一个关键字参数不是搜索内置的参数名,搜索时会把该参数当作tag的属性来搜索,如果包含一个名字为 id 的参数,Beautiful Soup会搜索每个tag的”id”属性.
for i in soupobj.find_all(id='link2'): #传入关键字参数,函数会搜索id属性等于link2的tag
print(i.name)
for i in soupobj.find_all(href=re.compile('baidu'),id='link2'):#使用关键字参数过滤多个属性:href,id
print(i.name)
#output
a
a
  1. 按CSS搜索(其实是继续使用关键字参数),可以通过 class 参数搜索有指定CSS类名的tag,class 参数同样接受不同类型的 过滤器 ,字符串,正则表达式,方法或 True
for i in soupobj.find_all(class_='story'): #单一使用'class_'属性查询
print(i.name)
for i in soupobj.find_all(href=re.compile('baidu'),class_='sister'): #联合多条件查询
print(i.name)
  1. 通过 text 参数可以搜搜文档中的字符串内容.与 name 参数的可选值一样, text 参数接受 字符串 , 正则表达式 , 列表, True . 看例子:
print(soupobj.find_all(text=re.compile('this')))#感觉用正则作为参数值效果最好
#output
['this is title', 'this is the content\n\n', 'this is herf to link baidu']
  1. 其余的参数包括limit,recursive,limit的作用是限制搜索结果的数目,recursive参数,调用tag的 find_all() 方法时,Beautiful Soup会检索当前tag的所有子孙节点,如果只想搜索tag的直接子节点,可以使用参数 recursive=False .

  2. find_all()方法的简写:BeautifulSoup 对象和 tag 对象可以被当作一个方法来使用,这个方法的执行结果与调用这个对象的 find_all() 方法相同,下面两行代码是等价的:


oup.find_all("a")
soup("a") #通过Beautifulsoup对象直接调用find_all


soup.title.find_all(text=True)#通过tag对象直接调用
soup.title(text=True)

7.CSS选择器语法来查找Tag,soup.select(),返回类型是 list,用 get_text() 方法来获取它的内容

print soup.select('title')#标签名查找

print soup.select('.sister')#class名查找

print soup.select('#link1')#id名查找

print soup.select("head > title")#直接子标签查找

print soup.select("#subject_list > ul > li > div.info > div.pub") #抓取作者,出版社信息,稍后我们用spite()

注意:

'nth-of-child' is simply not implemented in beautifulsoup4 (at time of writing),

#app > div > div > div.main > dl > dd:nth-child(1) > div > div > div.movie-item-info > p.name > a