BeautifulSoup是Python爬虫应用解析Html的利器,是Python三方模块bs4中提供的进行HTML解析的类,可以认为是一个HTML解析工具箱,对HTML报文中的标签具有比较好的容错识别功能。lxml是一款html文本解析器,BeautifulSoup构建对象时需要指定HTML解析器,推荐使用lxml。
BeautifulSoup和lxml安装命令:
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple bs4
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple lxml
加载BeautifulSoup:
from bs4 import BeautifulSoup
BeatifulSoap解析HTML报文的常用功能:
from bs4 import BeautifulSoup
import urllib.request
def getURLinf(url):
header = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36'}
req = urllib.request.Request(url=url,headers=header)
resp = urllib.request.urlopen(req,timeout=5)
html = resp.read().decode()
soup = BeautifulSoup(html,'lxml')
return (soup,req,resp)
soup,req ,resp = getURLinf(r'https://blog.csdn.net/LaoYuanPython/article/details/111303395')
print(soup.p)
print(soup.link)
print(soup.title)
print(soup.link.attrs)
print(soup.link['rel'])
print(soup.body.contents)
具体的大家可以参考老猿博客的免费专栏《爬虫:https://blog.csdn.net/laoyuanpython/category_9103810.html》或付费专栏《Python爬虫入门:https://blog.csdn.net/laoyuanpython/category_10762553.html》的相关介绍。
在HTML解析时,如果通过简单的tag、或单个tag属性(如id、class)或文本一次搜索或select定位是最简单的,而有些情况需要使用组合方法才能处理。
经常有些要定位的标签有很多,按单个属性查找也有很多,得使用多个属性查找。如:
<div id="article_content" class="article_content clearfix">
......
div>
<div id="article_content" class="article_view">
......
div>
<div id="article_view" class="article_view">
......
div>
上面的html文本中有多个id为article_content的div标签,如果使用:
>>> text="""```html
<div id="article_content" class="article_content clearfix">
......
div>
<div id="article_content" class="article_view">
......
div>
<div id="article_view" class="article_view">
......
div>"""
>>> s = BeautifulSoup(text,'lxml')
>>> s.select('div#article_content')
[<div class="article_content clearfix" id="article_content">......div>,
<div class="article_view" id="article_content">......div>]
>>>
就会返回两条记录。这时候就可以使用多标签属性定位的如下4种语句:
>>>s.select('div#article_content[class="article_content clearfix"]')
[<div class="article_content clearfix" id="article_content">......div>]
>>>s.select('div[id="article_content"][class="article_content clearfix"]')
[<div class="article_content clearfix" id="article_content">......div>]
>>>s.find_all("div",id="article_content",class_='article_content clearfix')
[<div class="article_content clearfix" id="article_content">......div>]
>>>s.find_all("div","#article_content",class_='article_content clearfix')
[<div class="article_content clearfix" id="article_content">......div>]
以上四种方式是等价的,因为id可以用#来标记,class在查找时需要和Python关键字class区分,因此有上述不同方法,注意select的每个属性必须用中括号括起来,不同属性的中括号之间不能有空格,如果有空格表示的就不是查找同一标签的属性,空格后的属性表示前一个属性对应标签的子孙标签的属性。
tag标签关系包括父子、兄弟、祖先等关系,有时要查找或定位的内容本身不是很好定位,但结合其他标签关系(主要是父子、祖先关系)则可以唯一确认。
案例:
这是CSDN的博文中关于博主个人信息的部分报文:
<div class="data-info d-flex item-tiling">
<dl class="text-center" title="1055">
<a href="https://blog.csdn.net/LaoYuanPython" data-report-click='{
"mod":"1598321000_001","spm":"1001.2101.3001.4310"}' data-report-query="t=1">
<dt><span class="count">1055span>dt>
<dd class="font">原创dd>
a>
dl>
<dl class="text-center" data-report-click='{
"mod":"1598321000_002","spm":"1001.2101.3001.4311"}' title="22">
<a href="https://blog.csdn.net/rank/writing_rank" target="_blank">
<dt><span class="count">22span>dt>
<dd class="font">周排名dd>
a>
dl>
div>
以上报文中,如果要取博主的原创文章数和周排名,原创文章数和博主周排名的tag标签完全相同,二者都在span标签内,标签的属性及值都相同,只是span标签的父标签dt标签的兄弟标签dd标签的string的中文内容才能区分。对于这种情况,首先要通过祖先标签 示例代码如下: 注意:上面的select使用的也是标签的属性来定位标签,并且两个中括号之间有空格,表明后一个要查找的标签在前一个属性对应标签的子孙标签范围内。 在解析HTML报文时,绝大多数情况是需要分析有用的标签信息,但作为技术文章,大部分的博文中都有代码,这些代码可能会对分析进行干扰。如本文中的代码含有一些分析的HTML报文,如果获取本文的完整HTML内容,这些报文在非代码部分也会出现,此时要排除代码的影响,可以将代码先从分析内容中去除再来分析。 目前大多数技术平台的博文编辑器都支持对代码的标识,象markdown等编辑器代码的标签为code标检,如果有其他编辑器用不同标签的,只有确认了标签名,都可以按下面介绍的类似方式来处理。 关于这部分内容的案例可以参考《https://blog.csdn.net/LaoYuanPython/article/details/114729045 n行Python代码系列:四行程序分离HTML报文中的程序代码》的详细介绍。 本文介绍了使用BeatifulSoap解析HTML报文的三个使用技巧,包括通过多属性组合查找或定位标签、通过结合多个标签关系来定位标签以及去除html报文中的代码标签来避免代码对解析的影响。 如果阅读本文于您有所获,敬请点赞、评论、收藏,谢谢大家的支持! 前两个专栏都适合有一定Python基础但无相关知识的小白读者学习,第三个专栏请大家结合《https://blog.csdn.net/laoyuanpython/category_9979286.html OpenCV-Python图形图像处理 》的学习使用。 对于缺乏Python基础的同仁,可以通过老猿的免费专栏《https://blog.csdn.net/laoyuanpython/category_9831699.html 专栏:Python基础教程目录)从零开始学习Python。 如果有兴趣也愿意支持老猿的读者,欢迎购买付费专栏。>>> text="""
<div class="data-info d-flex item-tiling">
<dl class="text-center" title="1055">
<a href="https://blog.csdn.net/LaoYuanPython" data-report-click='{
"mod":"1598321000_001","spm":"1001.2101.3001.4310"}' data-report-query="t=1">
<dt><span class="count">1055span>dt>
<dd class="font">原创dd>
a>
dl>
<dl class="text-center" data-report-click='{
"mod":"1598321000_002","spm":"1001.2101.3001.4311"}' title="22">
<a href="https://blog.csdn.net/rank/writing_rank" target="_blank">
<dt><span class="count">22span>dt>
<dd class="font">周排名dd>
a>
dl>
div>"""
>>> s = BeautifulSoup(text,'lxml')
>>> subSoup = s.select('[class="data-info d-flex item-tiling"] [class="font"]')
>>> for item in subSoup:
parent = item.parent
if item.string=='原创':
orignalNum = int(parent.select('.count')[0].string)
elif item.string=='周排名':
weekRank = int(parent.select('.count')[0].string)
>>> print(orignalNum,weekRank)
1055 22
>>>
2.3、分析前去除程序代码避免干扰
处理步骤如下:
三、小结
写博不易,敬请支持:
关于老猿的付费专栏
跟老猿学Python!
☞ ░ 前往老猿Python博文目录 https://blog.csdn.net/LaoYuanPython ░