BeautifulSoup的简单应用




from BeautifulSoup import BeautifulSoup
from BeautifulSoup import NavigableString
from BeautifulSoup import Comment
'''
html="""<html><head><title>The Dormouse's story</title></head>
<body>
<p class="title" name="dromouse"><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>"""
soup=BeautifulSoup(html)#这是一种方式
'''
soup=BeautifulSoup(open("C:\Users\lenovo\Desktop\cookie.txt"))#这是第二种方式html字符串
#BeautifulSoup的Tag类
#获得title标签
print soup.title
#获得head标签
print soup.head
#当字符串里有多个相同标签时,这种方式只能获得第一个
print soup.p
#Tag的两个重要的属性,name,attrs
print soup.name#这里我是用文件打开的方式获得的字符串,所以soup是一个文件
print soup.head.name#这里获得head标签的名字
print soup.p.attrs #这里把p标签的所有属性都打印出来了,结果是一个列表,每一属性及其值构成一个元组
print soup.p["class"]#这里是获得某个属性的值
print soup.get("class")#这是第二种方法,用get()方法传入属性名称

soup.p["class"]="newtitle" #修改这个属性的值,这里的修改应该是暂时的,你必须把修改完的soup重新写入到文件里
print soup.p.attrs
del soup.p["class"] #删除这个属性
print soup.p.attrs

#NavigableString 类
print soup.head #输出是<head>内容</head>
print soup.head.string #这里输出的就是head标签的内容
print soup.p.string

#Comment类,也是一种特殊的NavigableString的对象,它主要针对标签内容中有注释的情况,但是在输出这种标签内容的时候,注释内容不带注释符号
print soup.a
print soup.a.string
print type(soup.a.string)
#在这种情况下,我们会进行如下处理在输出
if type(soup.a.string)==bs4.element.Comment:#这个判断就说明该标签的内容是否为注释
    print soup.a.string

#上面的只是一些简单应用


from bs4 import BeautifulSoup

from bs4 import NavigableString

#BeautifulSoup的深度应用


#当我们爬取了网页代码后,他实际上是一个字符串,但是我们可以把它抽象成一个文档树,对html进行更深层的


#信息获取,这里每个标签就是一个节点,每个节点的信息就是他所包含的属性,及内容。


#1)直接子节点 .contents,.children属性


#.contents属性可以将tag的子节点以列表的方式输出


#print soup.body.contents


#我们可以通过索引的方式来获取每一个直接子节点


for children in soup.body.contents:


print children.string #输出每个直接子节点的内容


#.children 返回的不是一个列表,而是一个列表迭代器


print soup.head.children


#我们通过一个循环遍历一遍就能获取


for child in soup.body.children:


print child



#.descendants属性,它遍历一个标签的所有子孙节点,


print soup.descendants #他返回的是一个生成器


for child in soup.descendants:


print child




#.string属性获取节点内容,特点:如果一个标签里面没有标签了,那么 .string 就会返回标签里面的内容。如果标签里面只有唯一的一个标签了,那么 .string 也会返回最里面的内容。



if soup.head.string==soup.title.string:


print "true"


else:


print "false"


#如果tag包含了多个子节点,tag就无法确定,string 方法应该调用哪个子节点的内容, .string 的输出结果是 None


print soup.body.string




#获取多个内容 属性:.strings,.stripped_strings




#.string属性


print soup.strings #当获取多个内容时,返回生成器


for string in soup.strings:


print repr(string)



#.strippted_strings属性


#输出的字符串中可能包含了很多空格或空行,使用 .stripped_strings 可以去除多余空白内容


print soup.stripped_strings #同样返回的是个生成器


for string in soup.stripped_strings:


print string



#5)父节点 .parent属性


print soup.body.parent.name




content=soup.head.title.string


print content.parent.name#可以通过标签的内容来获取该标签




#6)全部父节点 .parents属性


print soup.body.parents #返回生成器




content=soup.head.title.string


for tag in content.parents: #通过标签内容来获取所有的父标签


print tag.name



#7)兄弟标签 属性: .next_sibling,.previous_sibling


#兄弟节点可以理解为和本节点处在统一级的节点,.next_sibling 属性获取了该节点的下一个兄弟节点,.previous_sibling 则与之相反,如果节点不存在,则返回 None


#注意:实际文档中的tag的 .next_sibling 和 .previous_sibling 属性通常是字符串或空白,因为空白或者换行也可以被视作一个节点,所以得到的结果可能是空白或者换行




#print soup.p.next_sibling.next_sibling #下一个节点的下一个兄弟节点是我们可以看到的节点


print soup.a.previous_sibling.previous.sibling




#8)全部兄弟节点 属性:.next_siblings,.previous_siblings


#通过 .next_siblings 和 .previous_siblings 属性可以对当前节点的兄弟节点迭代输出


print "*********************************************"


for sibling in soup.head.next_siblings:


print sibling


#9)前后节点 属性:.next_element,.previous_element


#与 .next_sibling .previous_sibling 不同,它并不是针对于兄弟节点,而是在所有节点,不分层次


print soup.head.next_element




#10)所有前后节点 属性:.next_elements,.previous_elements属性




for element in soup.head.next_elements:


print repr(element.name)



#这些都是遍历文档树的基本用法


print "********************************************************"


#搜素文档树


#1) find_all(name,attrs,recursive , text , **kwargs)


#find_all() 方法搜索当前tag的所有tag子节点,并判断是否符合过滤器的条件


# name 参数可以查找所有名字为 name 的tag,字符串对象会被自动忽略掉


#A.穿字符串


print soup.find_all('p')


#B.传正则表达式


#如果传入正则表达式作为参数,Beautiful Soup会通过正则表达式的 match() 来匹配内容


import re


print soup.find_all(re.compile("^b"))




for tag in soup.find_all(re.compile("^b")):


print tag.name


#C.传入列表


#如果传入列表参数,Beautiful Soup会将与列表中任一元素匹配的内容返回.


print soup.find_all(['a','b'])


#D.串True


#True 可以匹配任何值,下面代码查找到所有的tag,但是不会返回字符串节点


for tag in soup.find_all(True):


print tag.name


#E.传入方法


#如果没有合适过滤器,那么还可以定义一个方法,方法只接受一个元素参数 [4] ,如果这个方法返回 True 表示当前元素匹配并且被找到,如果不是则反回 False


def has_class_but_no_id(tag):


return tag.has_attr("class") and not tag.has_attr("id")


print soup.find_all(has_class_but_no_id)




#2) keyword 参数


#注意:如果一个指定名字的参数不是搜索内置的参数名,搜索时会把该参数当作指定名字tag的属性来搜索,如果包含一个名字为 id 的参数,Beautiful Soup会搜索每个tag的”id”属性


print soup.find_all(id="link2")




#使用多个指定名字的参数可以同时过滤tag的多个属性


print soup.find_all("a",id="link2")


#在这里我们想用 class 过滤,不过 class 是 python 的关键词,这怎么办?加个下划线就可以


print soup.find_all("a",class_="sister")




#有些tag属性在搜索不能使用,比如HTML5中的 data-* 属性


#data_soup = BeautifulSoup('<div data-foo="value">foo!</div>')


#data_soup.find_all(data-foo="value")


# SyntaxError: keyword can't be an expression




#通过 find_all() 方法的 attrs 参数定义一个字典参数来搜索包含特殊属性的tag


#data_soup.find_all(attrs={"data-foo":"value"})




#text 参数


#通过 text 参数可以搜搜文档中的字符串内容.与 name 参数的可选值一样, text 参数接受 字符串 , 正则表达式 , 列表, True


print soup.find_all(text="Elsie")




print soup.find_all(text=re.compile("Dormouse"))


#4)limit 参数:


#find_all() 方法返回全部的搜索结构,如果文档树很大那么搜索会很慢.如果我们不需要全部结果,可以使用 limit 参数限制返回结果的数量.效果与SQL中的limit关键字类似,当搜索到的结果数量达到 limit 的限制时,就停止搜索返回结果.


#5)recursive 参数


#调用tag的 find_all() 方法时,Beautiful Soup会检索当前tag的所有子孙节点,如果只想搜索tag的直接子节点,可以使用参数 recursive=False .




print soup.html.find_all("title",recursive=False)




#(2)find( name , attrs , recursive , text , **kwargs )




#它与 find_all() 方法唯一的区别是 find_all() 方法的返回结果是值包含一个元素的列表,而 find() 方法直接返回结果




#(3)find_parents() find_parent()




#find_all() 和 find() 只搜索当前节点的所有子节点,孙子节点等. find_parents() 和 find_parent() 用来搜索当前节点的父辈节点,搜索方法与普通tag的搜索方法相同,搜索文档搜索文档包含的内容




#(4)find_next_siblings() find_next_sibling()


#这2个方法通过 .next_siblings 属性对当 tag 的所有后面解析的兄弟 tag 节点进行迭代, find_next_siblings() 方法返回所有符合条件的后面的兄弟节点,find_next_sibling() 只返回符合条件的后面的第一个tag节点


#(5)find_previous_siblings() find_previous_sibling()


#这2个方法通过 .previous_siblings 属性对当前 tag 的前面解析的兄弟 tag 节点进行迭代, find_previous_siblings() 方法返回所有符合条件的前面的兄弟节点, find_previous_sibling() 方法返回第一个符合条件的前面的兄弟节点




#(6)find_all_next() find_next()




#这2个方法通过 .next_elements 属性对当前 tag 的之后的 tag 和字符串进行迭代, find_all_next() 方法返回所有符合条件的节点, find_next() 方法返回第一个符合条件的节点




#(7)find_all_previous() 和 find_previous()




#这2个方法通过 .previous_elements 属性对当前节点前面的 tag 和字符串进行迭代, find_all_previous() 方法返回所有符合条件的节点, find_previous()方法返回第一个符合条件的节点




#注:以上(2)(3)(4)(5)(6)(7)方法参数用法与 find_all() 完全相同,原理均类似,在此不再赘述。



# CSS选择器


#我们在写 CSS 时,标签名不加任何修饰,类名前加点,id名前加 #,在这里我们也可以利用类似的方法来筛选元素,用到的方法是 soup.select(),返回类型是 list


# 通过标签名查找


print soup.select("title")


#通过类名查找


print soup.select(".sister")


#通过ID查找


print soup.select("#link1")


#组合查找


#组合查找即和写 class 文件时,标签名与类名、id名进行的组合原理是一样的,例如查找 p 标签中,id 等于 link1的内容,二者需要用空格分开


print soup.select('p #link1')




#直接子标签查找




print soup.select("head > a")




#属性查找


#查找时还可以加入属性元素,属性需要用中括号括起来,注意属性和标签属于同一节点,所以中间不能加空格,否则会无法匹配到。




print soup.select('a[class="sister"]')


#[<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>, <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>, <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]




print soup.select('a[href="http://example.com/elsie"]')


#[<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>]


#同样,属性仍然可以与上述查找方式组合,不在同一节点的空格隔开,同一节点的不加空格




print "***********************************"


print type(soup.select("title"))


print soup.select("title")[0].string


for title in soup.select("title"):


print title.get_text()


#get_text和.string作用相似

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值