💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
BeautifulSoup是Python的一个HTML或XML的解析库,可以用它来方便地从网页提取数据 [TOC] # 一. 环境准备 ## 安装方式 ```python #安装beautifulsoup4 pip install beautifulsoup4 #安装lxml pip install lxml #转化本地文件: soup = BeautifulSoup(open('本地文件'), 'lxml') #转化网络文件: soup = BeautifulSoup('字符串类型或者字节类型', 'lxml') ``` ## 快速掌握知识点 ```python #(1)根据标签名查找 soup.a 只能找到第一个符合要求的标签 #(2)获取属性 soup.a.attrs 获取a所有的属性和属性值,返回一个字典 soup.a.attrs['href'] 获取href属性 soup.a['href'] 也可简写为这种形式 #(3)获取内容 soup.a.string soup.a.text soup.a.get_text() 【注意】如果标签还有标签,那么string获取到的结果为None,而其它两个,可以获取文本内容 #(4)find:找到第一个符合要求的标签 soup.find('a') 找到第一个符合要求的 soup.find('a', title="xxx") soup.find('a', alt="xxx") soup.find('a', class_="xxx") soup.find('a', id="xxx") #(5)find_all:找到所有符合要求的标签 soup.find_all('a',title="xxx") 找到title为xxx的a标签 soup.find_all(['a','b']) 找到所有的a和b标签 soup.find_all('a', limit=2) 限制前两个 #(6)根据选择器选择指定的内容 select:soup.select('#feng') 常见的选择器:标签选择器(a)、类选择器(.)、id选择器(#)、层级选择器 层级选择器: div .dudu #lala .meme .xixi 下面好多级 div > p > a > .lala 只能是下面一级 【注意】select选择器返回永远是列表,需要通过下标提取指定的对象 ``` # 二. 语法详解 ## 准备环境 ```html from bs4 import BeautifulSoup # 先定义一个html内容 html = """ <html> <head> <title>The Dormouse's story</title> </head> <body> <div class="panel"> <div class="panel-heading"> <h4>Hello</h4> </div> <div class="panel-body"> <ul class="list" id="list-1"> <li class="element">Foo</li> <li class="element">Bar</li> <li class="element">Jay</li> </ul> <ul class="list list-small" id="list-2"> <li class="element">Foo</li> <li class="element">Bar</li> </ul> </div> </div> </body> </html> """ ``` ## 1. 节点选择器: **初始化beautifulsoup** ```python soup = BeautifulSoup(html, 'lxml') ``` 初始化对于一些不标准的html,可以自动更正格式,如补全标签等等 **获取title节点,查看它的类型** ```python print(soup.title) print(type(soup.title)) #输出结果 <title>The Dormouse's story</title> <class 'bs4.element.Tag'> ``` 获取到的title节点,正是节点加文本内容 **获取title节点文本内容** ```python print(soup.title.string) #输出结果 The Dormouse's story ``` 如果想获取其他信息,比如节点的名字及其属性,这些也比较方便 **获取title节点的名字** ```python print(soup.title.name) #输出结果 title ``` **获取p节点的多个属性和某一属性** p节点有多个属性,比如class和name等,可以调用attrs获取所有属性 ```python #获取多个属性 print(soup.ul.attrs) #输出结果: {'class': ['list'], 'id': 'list-1'} #获取某个属性:方法一 print(soup.ul.attrs['id']) #输出结果: list-1 #获取某个属性:方法二 print(soup.ul['id']) #输出结果: list-1 #获取单个属性需要注意的地方 print(soup.ul['class']) #输出结果: ['list'] ``` >如果属性的值是唯一的,返回的结果就是单个字符串; >如果属性不唯一,返回的是列表,但只反复第一个p的值 **嵌套选择或层级选择** 如果多个节点层级嵌套在一起,可以通过层级关系依次选择,比如要选择title节点及其内容,之前我们是soup.title,现在可以这样操作:soup.head.title ```python print(soup.head.title) print(type(soup.head.title)) print(soup.head.title.string) #输出结果: <title>The Dormouse's story</title> <class 'bs4.element.Tag'> The Dormouse's story ``` ## 2. 方法选择器 **find_all():查询所有符合条件的元素** ```python print(type(soup.find_all(name='ul'))) print(soup.find_all(name='ul')) #运行结果: <class 'bs4.element.ResultSet'> [<ul class="list" id="list-1"> <li class="element">Foo</li> <li class="element">Bar</li> <li class="element">Jay</li> </ul>, <ul class="list list-small" id="list-2"> <li class="element">Foo</li> <li class="element">Bar</li> </ul>] ``` 利用find_all方法查询ul节点,返回结果是列表类型,长度为2, 可以通过列表操作方法操作,也可以通过for循环继续操作 ```python for ul in soup.find_all(name='ul'): print(ul.find_all(name='li')) #输出结果: [<li class="element">Foo</li>, <li class="element">Bar</li>, <li class="element">Jay</li>] [<li class="element">Foo</li>, <li class="element">Bar</li>] ``` 除了根据节点名查询,还可以传入一些属性来查询 ```python print(soup.find_all(attrs={'id': 'list-1'})) #输出结果: [<ul class="list" id="list-1"> <li class="element">Foo</li> <li class="element">Bar</li> <li class="element">Jay</li> </ul>] ``` 对于一些常用的属性,比如id和class等,可以不用attrs来传递。 比如,要查询class为element的节点,可以直接传入class这个参数。 ```python print(soup.find_all(class_='element')) #class由于是python的关键字,所以要改为class_ #输出结果: [<li class="element">Foo</li>, <li class="element">Bar</li>, <li class="element">Jay</li>, <li class="element">Foo</li>, <li class="element">Bar</li>] ``` text参数可以用来匹配节点的文本,传入的形式可以是字符串,可以是正则表达式对象 ```python print(soup.find_all(text='Foo')) #输出结果: ['Foo', 'Foo'] ``` **find():返回单个元素,也就是第一个匹配的元素** ```python print(soup.find(name='ul')) #输出结果: <ul class="list" id="list-1"> <li class="element">Foo</li> <li class="element">Bar</li> <li class="element">Jay</li> </ul> ``` **其他的查询方法** * find_parents()和find_parent(): 前者返回所有祖先节点,后者返回直接父节点 * find_next_siblings()和find_next_sibling(): 前者返回后面所有的兄弟节点,后者返回后面第一个兄弟节点 * find_previous_siblings()和find_previous_sibling(): 前者返回前面所有的兄弟节点,后者返回前面第一个兄弟节点 * find_all_next()和find_next(): 前者返回节点后所有符合条件的节点,后者返回第一个符合条件的节点 * find_all_previous()和find_previous(): 前者返回节点前所有符合条件的节点,后者返回第一个符合条件的节点 ## 3. CSS选择器 使用CSS选择器时,只需要调用select()方法,传入相应的CSS选择器即可 ```python print(soup.select('.panel .panel-heading'),'\n') print(soup.select('ul li'),'\n') print(soup.select('#list-2 .element'),'\n') print(type(soup.select('ul')[0])) #输出结果: [<div class="panel-heading"> <h4>Hello</h4> </div>] [<li class="element">Foo</li>, <li class="element">Bar</li>, <li class="element">Jay</li>, <li class="element">Foo</li>, <li class="element">Bar</li>] [<li class="element">Foo</li>, <li class="element">Bar</li>] <class 'bs4.element.Tag'> ``` **嵌套选择** select()方法同样支持嵌套选择。例如,先选择所有ul节点,再遍历每个ul节点 ```python for ul in soup.select('ul'): print(ul.select('li')) #输出结果: "C:\Program Files\Python36\python.exe" D:/data/python/t-class/pc.py [<li class="element">Foo</li>, <li class="element">Bar</li>, <li class="element">Jay</li>] [<li class="element">Foo</li>, <li class="element">Bar</li>] ``` 可以看到,这里正常输出了所有ul节点下所有li节点组成的列表 **获取属性** ```python for ul in soup.select('ul'): print(ul['id']) print(ul.attrs['id']) #输出结果: list-1 list-1 list-2 list-2 ``` 可以看到,直接传入中括号和属性名,或通过attrs属性获取属性值,都可以成功 **获取文本** 要获取文本,可以用前面所讲的string属性或者get_text()方法 ```python for li in soup.select('li'): print('Get Text:', li.get_text()) print('String:', li.string,'\n') #输出结果: Get Text: Foo String: Foo Get Text: Bar String: Bar Get Text: Jay String: Jay Get Text: Foo String: Foo Get Text: Bar String: Bar ```