BeautifulSoup4库
和lxml一样,Beautiful Soup也是一个HTML/XML的解析器,主要的功能也是如何解析和提取 HTML/XML数据。
lxml只会局部遍历,而Beautiful Soup是基于HTMLDOM的,会载入整个文档,解析整个DOM树,因此时间和内存开销都会大很多,所以性能要低于lxml。
BeautifulSoup用未解析HTML比较简单,AP非常人性化,支持CSS选择器、Python标准库中的HTML解析器,也支持lxml的XML解析器。
Beautiful Soup3目前已经停止开发,推荐现在的项目使用Beautiful Soup 4。
解析工具
解析工具 | 解析速度 | 使用难度 |
BeautifulSoup | 最慢 | 最简单 |
lxml | 快 | 简单 |
re正则 | 最快 |
简单使用:
import requests from bs4 import BeautifulSoup url = "https://baike.baidu.com/item/%E7%99%BE%E5%BA%A6%E7%99%BE%E7%A7%91" headers = { "User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.62 Safari/537.36", "Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8" } url1 = requests.get(url, headers=headers) url1.encoding="urf-8" #适用于文字出现乱码 soup = BeautifulSoup(url1.text,'lxml') ''' print(soup.title) #输出标题(标签) print(soup.a.string) #输出a标签内的文字 print(soup.p.attrs) #输出p标签的所有属性 得到的类型是一个字典 如果想单独获得一个属性 :soup.p['class'] #遍历文档树 print(soup.head.contents) # .content 属性可以将tag的子节点以列表的方式输出 #print(soup.head.children) 通过遍历获取所有子节点 for child in soup.body.children: print(child) for child in soup.descendants: print(child) for string in soup.stripped_strings: print(repr(string)) #可以去除多余空白内容 content = soup.head.title.string for parent in content.parents: print(parent.name) #全部父节点 ''' for sibling in soup.a.next_siblings: print(repr(sibling))
提取数据
from bs4 import BeautifulSoup text = """ <table class="tablelist" cellpadding="0" cellspacing="0"> <tbody><tr class="h"> <td class="l" width="374">职位名称</td> <td>职位类别</td> <td>人数</td> <td>地点</td> <td>发布时间</td> </tr> <tr class="even"> <td class="l square"><a target="_blank" href="position_detail.php?id=44606&keywords=技术&tid=0&lid=0">MIG09-QQ浏览器视频前端开发工程师</a></td> <td>技术类</td> <td>1</td> <td>深圳</td> <td>2018-10-01</td> </tr> <tr class="odd"> <td class="l square"><a target="_blank" href="position_detail.php?id=44599&keywords=技术&tid=0&lid=0">17520-U3D手游客户端开发</a></td> <td>技术类</td> <td>2</td> <td>深圳</td> <td>2018-10-01</td> </tr> <tr class="even"> <td class="l square"><a target="_blank" href="position_detail.php?id=44602&keywords=技术&tid=0&lid=0">22989-腾讯云高级文档开发经理(深圳)</a></td> <td>产品/项目类</td> <td>2</td> <td>深圳</td> <td>2018-10-01</td> </tr> <tr class="odd"> <td class="l square"><a target="_blank" href="position_detail.php?id=44604&keywords=技术&tid=0&lid=0">18796-Android开发工程师(深圳)</a><span class="hot"> </span></td> <td>技术类</td> <td>1</td> <td>深圳</td> <td>2018-10-01</td> </tr> <tr class="even"> <td class="l square"><a target="_blank" href="position_detail.php?id=44591&keywords=技术&tid=0&lid=0">29050-数据安全经理/专家(北京)</a></td> <td>职能类</td> <td>2</td> <td>北京</td> <td>2018-10-01</td> </tr> <tr class="odd"> <td class="l square"><a target="_blank" href="position_detail.php?id=44587&keywords=技术&tid=0&lid=0">29050-CII政策发展经理</a></td> <td>职能类</td> <td>2</td> <td>深圳</td> <td>2018-10-01</td> </tr> <tr class="even"> <td class="l square"><a target="_blank" href="position_detail.php?id=44588&keywords=技术&tid=0&lid=0">29050-CII政策发展经理</a></td> <td>职能类</td> <td>2</td> <td>北京</td> <td>2018-10-01</td> </tr> <tr class="odd"> <td class="l square"><a target="_blank" href="position_detail.php?id=44590&keywords=技术&tid=0&lid=0">29050-数据安全经理/专家(深圳)</a></td> <td>职能类</td> <td>2</td> <td>深圳</td> <td>2018-10-01</td> </tr> <tr class="even"> <td class="l square"><a target="_blank" href="position_detail.php?id=44581&keywords=技术&tid=0&lid=0">28994-区块链底层开发工程师(深圳)</a></td> <td>技术类</td> <td>2</td> <td>深圳</td> <td>2018-10-01</td> </tr> <tr class="odd"> <td class="l square"><a target="_blank" href="position_detail.php?id=44583&keywords=技术&tid=0&lid=0">29050-CII产品合规经理</a></td> <td>职能类</td> <td>2</td> <td>深圳</td> <td>2018-10-01</td> </tr> <tr class="f"> <td colspan="5"> <div class="left">共<span class="lightblue total">1184</span>个职位</div> <div class="right"><div class="pagenav"><a href="javascript:;" class="noactive" id="prev">上一页</a><a class="active" href="javascript:;">1</a><a href="position.php?keywords=技术&start=10#a">2</a><a href="position.php?keywords=技术&start=20#a">3</a><a href="position.php?keywords=技术&start=30#a">4</a><a href="position.php?keywords=技术&start=40#a">5</a><a href="position.php?keywords=技术&start=50#a">6</a><a href="position.php?keywords=技术&start=60#a">7</a><a href="position.php?keywords=技术&start=70#a">...</a><a href="position.php?keywords=技术&start=1180#a">119</a><a href="position.php?keywords=技术&start=10#a" id="next">下一页</a><div class="clr"></div></div></div> <div class="clr"></div> </td> </tr> </tbody> </table> """ soup = BeautifulSoup(text,'lxml') # 1.获得所有tr标签 # trs = soup.find_all('tr') #find_all('tr',limit=2) limit为上限值 意思是只获得2个tr标签 # for tr in trs: # print(tr) # 2.获取第二个标签 # tr = soup.find_all('tr')[1] # print(tr) # 3.获取所有class等于even的tr标签 # (方法1) # trs = soup.find_all('tr',class_='even') #class后必须加_ 对python关键字进行区分 # for tr in trs: # print(tr) # (方法2) # trs = soup.find_all('tr',attrs={'class':"even"}) #指定字典的显示匹配 # for tr in trs: # print(tr) # 4.将所有id等于prev,class等于noactive的a标签提取出来 # trs = soup.find_all('a',class_='noactive',id='prev') #多个条件 或 trs = soup.find_all('a',attrs={"id":"prev","class":"noactive"}) # for tr in trs: # print(tr) # 5.获得所有a标签的href属性 # alist = soup.find_all('a') # # for a in alist: # # (1).通过下标操作的方式 # # href=a['href'] #下标方式 # # print(href) # # (2).通过attrs属性的方式 # href= a.attrs['href'] # print(href) # 6.获取职位信息 trs = soup.find_all("tr")[1:] #第0个(地址)tr标签过滤 movies = [] for tr in trs: movie = {} #(方法1) # tds = tr.find_all("td") # print(tds[1].string) # title = tds[0].string # category = tds[1].string # nums = tds[2].string # city = tds[3].string # pubtime = tds[4].string # movie['title'] = title # movie['category'] = category # movie['nums'] = nums # movie['city'] = city # movie['pubtime'] = pubtime # movies.append(movie) #(方法2) infos = list(tr.stripped_strings) #获取所有非空白字符(过滤空格、回车等字符) movie['title'] = infos[0] movie['category'] = infos[1] movie['nums'] = infos[2] movie['city'] = infos[3] movie['pubtime'] = infos[4] movies.append(movie) print(movies)
#BeautifulSoup笔记:
##find_a11的使用:
1.在提取标签的时候,第一个参数是标签的名字。然后如果在提取标签的时候想要使用标签属性进行过滤,那么可以在这个方法中通过关键字参数的形式,将属性的名字以及对应的值传进去。或者是使用“attrs“属性,将所有的属性以及对应的值放在一个字典中传给attrs 属性。
2.有些时候,在提取标签的时候,不想提取那么多,那么可以使用‘1imit'参数。限制提取多少个。
##find与find_a11的区别:
1.find:找到第一个满足领件的标签就返回。说白了,就是只会返回一个元素。
2.find_al1:将所有满足条件的标签都返回。说白了,会返回很多标签(以列表的形式)
##使用find和find_al1的过滤条件:
1.关键字参数:将属性的名字作为关键字参数的名字,以及属性的值作为关键字参数的值进行过滤
2.attrs参数:将属性条件放到一个字典中,传给attrs参数。
##strings和stripped_strings、string属性以及get_text方法:
1.string:获取某个标签下的非标签字符串。
2.strings:获取某个标签下的子孙非标签字符串。
2.stripped_strings:获取某个标签下的子孙非标签字符串,会去掉空白字符。
4.get_text:获取某个标签下的子孙非标签字符串。不是以列表的形式返回。
eg: tr=soup.find_all('tr')[1]
text=tr.get_text()
##常见的四种对象:
1.Tag:Beautifulsoup中所有的标签都是Tag类型,并且BeautifulSoup的对象其实本质上也是一个Tag类型。所以其实一些方法比如find、find_all并不是BeautifulSoup的,而是Tag的。
2.Navigablestring:继承自python中的str,用起来就跟使用python的str是一样的。
3.BeautifulSoup:继承自Tag。用来生成BeautifulSoup树的。对于一些查找方法,比如find、select这些,其实还是Tag的。
4.Comment:这个也没什么好说,就是继承自Navigablestring。
##contents和children:
返回某个标签下的直接子元素,其中也包括字符串。他们两的区别是:.contents返回来的是一个列表,.children返回的是一个迭代器。|