原文 https://mp.weixin.qq.com/s/U3NMa20KBW0ShQruNgU_7w
BeautifulSoup 是一个解析 html 或 xml 文件的第三方库. HTML 或 xml 文件可以用 DOM 模型解释. 一般包含三种节点:
元素节点 - 通常指 HTML 或 xml 的标签
文本节点 - 标签内部的文本内容
属性节点 - 每个标签的属性
BeautifulSoup 库可以对 HTML 或 xml 文件解析, 查找到一个或多个标签元素, 并获取每个标签里的文本和属性.
BeautifulSoup 很好的特性是它接受一个 str 或 byte 对象后会对编码自动检测, 并对当前文档编码并转换成 Unicode 编码. 这样可以不用担心乱码问题.
安装: pip install beautifulsoup4
使用: from bs4 import BeautifulSoup
推荐安装: pip install lxml, 比 python 自带的解析库 HTML.parser 更快
BeautifulSoup 库的使用方法:
对一个元素的查找主要有 3 种方法:
根据标签名直接查找: soup.title, soup.p . 仅适用于查找单个元素
使用 find 和 find_all 方法 - 根据标签名和属性对文档遍历查找提取一个或多个元素
使用 select 方法 - 根据 CSS 样式选择器对文档进行遍历提取一个或多个元素
- # 根据 tag 直接获取元素
- soup.p #获取 p 标签元素对象, 只获取第一个
- soup.p.name #获取 p 标签的名字, 即'p"
- soup.p.string # 获取 p 标签元素内的文本
- soup.p['class'] #获取 p 标签元素的 class 属性
- soup.p.get('class') #等同于上述案例
- soup.a['href'] #获取第一个 a 元素的 href 属性
- # find_all 方法. find 方法类似, 仅用于提取首个匹配元素
- # find_all( name , attrs , recursive , text , **kwargs )
- # name : 要查找的标签名(字符串, 正则, 方法, True)
- # attrs: 标签的属性
- # recursive: 递归
- # text: 查找文本
- # **kwargs : 其它 键值参数
- # 因 class 是关键字, 所以要写成 class_="value", 等同于 attrs={"class":"value"}
- soup.find_all('p') # 以列表形式返回所有 p 标签
- soup.find_all('p', attrs={"class":"sister"}) # 以列表形式返回所有 class 属性 ==sister 的 p 标签
- soup.find_all('p', class_="sister") # 以列表形式返回所有 class 属性 ==sister 的 p 标签
- soup.find_all(id='link2') # 返回所有 id 属性 ==link2 的标签
- soup.find_all(re.compile("^b")) # 使用正则查找标签以 b 开头的元素
- soup.find_all(href=re.compile("elsie")) # 使用正则, 返回所有 href 属性包含 elsie 的标签
- soup.find_all(id="link1", href=re.compile('elsie')) # id=link1 且 href 包含 elsie 的标签
- # select 方法 - CSS 选择器
- # 注意 select 方法提取的元素均是列表形式, 获取文本时注意加 index
- soup.select('p') # 根据标签名查找所有 p 元素, 等于 soup.find_all('p')
- soup.select('.sister') # 通过 CSS 属性查找 class=sister 的标签
- soup.select('#link1') # 通过 id 查找所有 id=#link1 的元素
- soup.select('p #link1') # 组合查找 id=#link11 的 p 元素
- soup.select("head> title") # 查找 head 标签的子元素 title
- soup.select('a[class="sister"]') # 查找所有属性为 sister 的 a 标签
- soup.select('a[href="http://example.com/elsie"]') #查找 href=xxx 的 a 标签元素
- soup.select('p')[0].get_text() # 获取首个 p 元素的文本
- soup.select('a[href*=".com/el"]')[0].attrs['href'] #获取 xxx.com 的 href
除了 find()和 find_all()之外, 还有一些常用的方法可用来搜索父子和兄弟节点:
- find_parent()
- find_parents()
- find_next_sibling()
- find_next_siblings()
- find_previous_sibling()
- find_previous_siblings()
- find_next()
- find_previous()
- find_all_next()
- find_all_previous()
请注意 select 方法和 find 方法有如下区别, 使用时请注意:
find 方法返回的是单个元素, find_all 方法返回的是一个元素列表, 而 select 方法永远返回的是元素列表. 如果你使用了 select 方法查找到了单个元素, 别忘了先加列表索引 [0], 然后才可以调用 get_text() 方法获取文本.
find 方法还支持方法参数查询, 比 select 方法更强大, 如下所示:
- def has_class_no_id(tag):
- return tag.has_attr("class") and not tag.has_attr("id")
- soup.find_all(has_class_no_id) # 支持方法参数
来源: http://www.bubuko.com/infodetail-3327032.html