python beautiful soup
官方文档:https://www.crummy.com/software/BeautifulSoup/bs4/doc.zh/
使用前需要先安装模块,并安装解析器
1 2 3 | pip install beautifulsoup4 pip install lxml pip install html5lib |
安装完成后导入模块
1 | from bs4 import BeautifulSoup |
安装解析器
1 2 | pip install lxml pip install html5lib |
解析器比较
推荐使用lxml作为解析器,因为效率更高. 在Python2.7.3之前的版本和Python3中3.2.2之前的版本,必须安装lxml或html5lib, 因为那些Python版本的标准库中内置的HTML解析方法不够稳定.
选择解析器创建对象
1 2 | html = urllib.request.urlopen(url).read() bs = BeautifulSoup(html, 'lxml' ) |
格式化输出
1 | print (bs.prettify()) |
Beautiful Soup将复杂HTML文档转换成一个复杂的树形结构,每个节点都是Python对象,所有对象可以归纳为4种: Tag , NavigableString , BeautifulSoup , Comment
1.Tag:Tag有很多方法和属性,最重要的属性为name和attributes
1 2 3 4 | >>> soup = BeautifulSoup( '<b class="boldest">Extremely bold</b>' ) >>> tag = soup.b >>> type (tag) < class 'bs4.element.Tag' > |
name属性:每个tag都有自己的名字,通过 .name 来获取:
1 2 3 4 5 6 7 | >>> tag.name 'b' #如果改变了tag的name,那将影响所有通过当前Beautiful Soup对象生成的HTML文档 >>> tag.name = "blockquote" >>> tag <blockquote class = "boldest" >Extremely bold< / blockquote> |
attributes属性:获取标签内的属性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | #可以直接通过.attrs获取 >>> tag.attrs { 'class' : [ 'boldest' ]} #也可以以字典的方式获取 >>> tag[ 'class' ] [ 'boldest' ] >>> tag.get( 'class' , None) [ 'boldest' ] #tag的属性可以被添加,删除或修改 >>> tag[ 'class' ] = 'verybold' #修改 >>> tag[ 'id' ] = 1 #添加 >>> tag <blockquote class= "verybold" id = "1" >Extremely bold< /blockquote > >>> del tag[ 'class' ] #删除 >>> del tag[ 'id' ] #删除 >>> tag <blockquote>Extremely bold< /blockquote > |
2.NavigableString:获取标签内的字符串
1 2 3 4 5 6 | >>> soup = BeautifulSoup( '<b class="boldest">Extremely bold</b>' ) >>> tag = soup.b >>> tag.string 'Extremely bold' >>> type (tag.string) < class 'bs4.element.NavigableString' > |
tag中包含的字符串不能编辑,但是可以被替换成其它的字符串,用 replace_with() 方法
1 2 3 4 | >>> tag.string.replace_with( "No longer bold" ) 'Extremely bold' >>> tag <blockquote>No longer bold< / blockquote> |
3.BeautifulSoup:
BeautifulSoup 对象表示的是一个文档的全部内容.大部分时候,可以把它当作 Tag对象,它支持 遍历文档树 和 搜索文档树 中描述的大部分的方法.
因为 BeautifulSoup 对象并不是真正的HTML或XML的tag,所以它没有name和attribute属性.但有时查看它的 .name 属性是很方便的,所以 BeautifulSoup 对象包含了一个值为 “[document]” 的特殊属性 .name
1 2 | >>> soup.name '[document]' |
4.comment:注释部分
Tag , NavigableString , BeautifulSoup 几乎覆盖了html和xml中的所有内容,但是还有一些特殊对象.容易让人担心的内容是文档的注释部分
1 2 3 4 5 6 7 | >>> markup = "<b><!--Hey, buddy. Want to buy a used parser?--></b>" >>> soup = BeautifulSoup(markup) >>> comment = soup.b.string >>> type (comment) < class 'bs4.element.Comment' > >>> comment 'Hey, buddy. Want to buy a used parser?' |
findall方法:搜索当前tag的所有tag子节点,并判断是否符合过滤器的条件,find方法相当于find_all(limit=1)
1 | find_all( name , attrs , recursive , text , * * kwargs ) |
name 参数:
可以查找所有名字为 name 的tag,字符串对象会被自动忽略掉.简单的用法如下
1 2 | soup.find_all( "title" ) # [<title>The Dormouse's story</title>] |
keyword 参数:
如果一个指定名字的参数不是搜索内置的参数名,搜索时会把该参数当作指定名字tag的属性来搜索,如果包含一个名字为 id 的参数,Beautiful Soup会搜索每个tag的”id”属性.
1 2 | soup.find_all( id = 'link2' ) # [<a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>] |
如果属性名和关键字重复,可以在属性名后加上_,例如class_
1 | soup.find_all( 'div' , class_ = "p12" ) |
如果传入 href 参数,Beautiful Soup会搜索每个tag的”href”属性:
1 2 | soup.find_all(href = re. compile ( "elsie" )) # [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>] |
下面的例子在文档树中查找所有包含 id 属性的tag,无论 id 的值是什么
1 2 3 4 | soup.find_all( id = True ) # [<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>] |
使用多个指定名字的参数可以同时过滤tag的多个属性,相当于and
1 2 | soup.find_all(href = re. compile ( "elsie" ), id = 'link1' ) # [<a class="sister" href="http://example.com/elsie" id="link1">three</a>] |
指定多个值,相当于or
1 | soup.find_all( id =[ 'link1' , 'link2' ]) |
有些tag属性在搜索不能使用,比如HTML5中的 data-* 属性
1 2 3 | 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:
1 2 | data_soup.find_all(attrs = { "data-foo" : "value" }) # [<div data-foo="value">foo!</div>] |
text 参数:
通过 text 参数可以搜搜文档中的字符串内容.与 name 参数的可选值一样, text参数接受 字符串 , 正则表达式 , 列表, True . 看例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | soup.find_all(text = "Elsie" ) # [u'Elsie'] soup.find_all(text = [ "Tillie" , "Elsie" , "Lacie" ]) # [u'Elsie', u'Lacie', u'Tillie'] soup.find_all(text = re. compile ( "Dormouse" )) [u "The Dormouse's story" , u "The Dormouse's story" ] def is_the_only_string_within_a_tag(s): " "Return True if this string is the only child of its parent tag." " return (s = = s.parent.string) soup.find_all(text = is_the_only_string_within_a_tag) # [u"The Dormouse's story", u"The Dormouse's story", u'Elsie', u'Lacie', u'Tillie', u'...'] |
limit 参数:
find_all() 方法返回全部的搜索结构,如果文档树很大那么搜索会很慢.如果我们不需要全部结果,可以使用 limit 参数限制返回结果的数量.效果与SQL中的limit关键字类似,当搜索到的结果数量达到 limit 的限制时,就停止搜索返回结果.
文档树中有3个tag符合搜索条件,但结果只返回了2个,因为我们限制了返回数量:
1 2 3 | soup.find_all( "a" , limit = 2 ) # [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>, # <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>] |
查找文档中所有的<b>标签
1 | soup.find_all( 'b' ) |
如果传入正则表达式作为参数,Beautiful Soup会通过正则表达式的 match() 来匹配内容.下面例子中找出所有以b开头的标签,这表示<body>和<b>标签都应该被找到
1 2 3 | import re for tag in soup.find_all(re. compile ( "^b" )): print (tag.name) |
如果传入列表参数,Beautiful Soup会将与列表中任一元素匹配的内容返回.下面代码找到文档中所有<a>标签和<b>标签
1 | soup.find_all([ "a" , "b" ]) |
True 可以匹配任何值,下面代码查找到所有的tag,但是不会返回字符串节点
1 2 3 4 5 6 7 8 9 10 11 12 13 | for tag in soup.find_all( True ): print (tag.name) # html # head # title # body # p # b # p # a # a # a # p |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· DeepSeek在M芯片Mac上本地化部署
· 葡萄城 AI 搜索升级:DeepSeek 加持,客户体验更智能