目錄
一、Beautiful Soup概述:
安裝:
##二、BeautifulSoup4簡單使用
創建beautifulsoup4物件:
我們可以利用soup 加標籤名輕鬆地取得這些標籤的內容,這些物件的類型是bs4.element.Tag。但是注意,它查找的是在所有內容中的第一個符合要求的標籤。
#既然我們已經得到了標籤的內容,那麼問題來了,我們要想取得標籤內部的文字怎麼辦呢?很簡單,用 .string 即可,例如:
BeautifulSoup物件表示的是一個文件的內容。大部分時候,可以把它當作Tag 對象,是一個特殊的Tag,我們可以分別取得它的類型,名稱,以及屬性,例如:
.has_attr:
find_all(name, attrs, recursive, text, **kwargs):
(2)kwargs参数:
(3)attrs参数:
(4)text参数:
(5)limit参数
2、find()
六、CSS选择器:select()方法
七、综合实例:
八、BeautifulSoup 和lxml(Xpath)对比
首頁 後端開發 Python教學 Python如何使用Beautiful Soup(BS4)函式庫解析HTML和XML

Python如何使用Beautiful Soup(BS4)函式庫解析HTML和XML

May 13, 2023 pm 09:55 PM
python xml html

一、Beautiful Soup概述:

Beautiful Soup支援從HTML或XML檔案中擷取資料的Python函式庫;

它支援Python標準函式庫中的HTML解析器,也支援一些第三方的解析器lxml。

Beautiful Soup會自動將輸入文件轉換為Unicode編碼,輸出文件轉換為utf-8編碼。

安裝:

pip install beautifulsoup4

可選擇安裝解析器

  • pip install lxml

  • pip install html5lib

##pip install html5lib

##二、BeautifulSoup4簡單使用

假設有這樣一個Html,具體內容如下:

<!DOCTYPE html>
<html>
<head>
    <meta content="text/html;charset=utf-8" http-equiv="content-type" />
    <meta content="IE=Edge" http-equiv="X-UA-Compatible" />
    <meta content="always" name="referrer" />
    <link href="https://ss1.bdstatic.com/5eN1bjq8AAUYm2zgoY3K/r/www/cache/bdorz/baidu.min.css" rel="external nofollow"  rel="stylesheet" type="text/css" />
    <title>百度一下,你就知道 </title>
</head>
<body link="#0000cc">
  <div id="wrapper">
    <div id="head">
        <div class="head_wrapper">
          <div id="u1">
            <a class="mnav" href="http://news.baidu.com" rel="external nofollow"  name="tj_trnews">新闻 </a>
            <a class="mnav" href="https://www.hao123.com" rel="external nofollow"  name="tj_trhao123">hao123 </a>
            <a class="mnav" href="http://map.baidu.com" rel="external nofollow"  name="tj_trmap">地图 </a>
            <a class="mnav" href="http://v.baidu.com" rel="external nofollow"  name="tj_trvideo">视频 </a>
            <a class="mnav" href="http://tieba.baidu.com" rel="external nofollow"  rel="external nofollow"  name="tj_trtieba">贴吧 </a>
            <a class="bri" href="//www.baidu.com/more/" rel="external nofollow"  name="tj_briicon" >更多产品 </a>
          </div>
        </div>
    </div>
  </div>
</body>
</html>
登入後複製

創建beautifulsoup4物件:

from bs4 import BeautifulSoup

file = open(&#39;./aa.html&#39;, &#39;rb&#39;)
html = file.read()
bs = BeautifulSoup(html, "html.parser")  # 缩进格式

print(bs.prettify())  # 格式化html结构
print(bs.title)  # 
print(bs.title.name)  # 获取title标签的名称 :title
print(bs.title.string)  # 获取title标签的文本内容 :   百度一下,你就知道
print(bs.head)  # 获取head标签的所有内容 :
print(bs.div)  # 获取第一个div标签中的所有内容   :
print(bs.div["id"])  # 获取第一个div标签的id的值      :    wrapper
print(bs.a)  # 获取第一个a标签中的所有内容    :       <a href="http://news.baidu.com/" rel="external nofollow"   target="_blank">新闻 </a>
print(bs.find_all("a"))  # 获取所有的a标签中的所有内容     :   [....]
print(bs.find(id="u1"))  # 获取id="u1"的所有内容 :
for item in bs.find_all("a"):  # 获取所有的a标签,并遍历打印a标签中的href的值    :
    print(item.get("href"))
for item in bs.find_all("a"):  # 获取所有的a标签,并遍历打印a标签的文本值:
    print(item.get_text())
登入後複製

三、BeautifulSoup4四大物件種類

BeautifulSoup4將複雜HTML文件轉換成一個複雜的樹狀結構,每個節點都是Python物件,所有物件可以歸納為4種:Tag 、NavigableString 、BeautifulSoup 、Comment、

1、Tag:標籤Tag通俗點講就是HTML中的一個個標籤,例如:

print(bs.title) # 获取title标签的所有内容
print(bs.head) # 获取head标签的所有内容
print(bs.a) # 获取第一个a标签的所有内容
print(type(bs.a))# 类型
登入後複製

我們可以利用soup 加標籤名輕鬆地取得這些標籤的內容,這些物件的類型是bs4.element.Tag。但是注意,它查找的是在所有內容中的第一個符合要求的標籤。

對於Tag,它有

兩個重要的屬性,是 name 和attrs:

print(bs.name) # [document] #bs 对象本身比较特殊,它的 name 即为 [document]
print(bs.head.name) # head #对于其他内部标签,输出的值便为标签本身的名称
print(bs.a.attrs) # 在这里,我们把 a 标签的所有属性打印输出了出来,得到的类型是一个字典。
print(bs.a[&#39;class&#39;]) ##还可以利用get方法,传入属性的名称,二者是等价的,等价 bs.a.get(&#39;class&#39;)

bs.a[&#39;class&#39;] = "newClass"# 可以对这些属性和内容等等进行修改
print(bs.a) 

del bs.a[&#39;class&#39;] # 还可以对这个属性进行删除
print(bs.a)
登入後複製

2、NavigableString:標籤內部的文字

#既然我們已經得到了標籤的內容,那麼問題來了,我們要想取得標籤內部的文字怎麼辦呢?很簡單,用 .string 即可,例如:

print(bs.title.string)  # 百度一下,你就知道 
print(type(bs.title.string))  #
登入後複製

3、BeautifulSoup:文件的內容

BeautifulSoup物件表示的是一個文件的內容。大部分時候,可以把它當作Tag 對象,是一個特殊的Tag,我們可以分別取得它的類型,名稱,以及屬性,例如:

print(type(bs.name))  # 
print(bs.name)  # [document]
print(bs.attrs)  # {}
登入後複製
    4、Comment:註解
  • Comment 物件是一個特殊類型的NavigableString 對象,其輸出的內容不包括註解符號。

    print(bs.a)
    # 此时不能出现空格和换行符,a标签如下:
    # 
    print(bs.a.string) # 新闻
    print(type(bs.a.string)) #
    登入後複製
    四、遍歷文檔樹所用屬性

  • #.contents:

    取得Tag的所有子節點,回傳一個list

    print(bs.head.contents)     # tag的.contents属性可以将tag的子节点以列表的方式输出:[...]
    print(bs.head.contents[1])  # 用列表索引来获取它的某一个元素:
    登入後複製
    .
  • children:

    取得Tag的所有子節點,回傳一個生成器

    for child in bs.body.children:
        print(child)
    登入後複製
  • .descendants:取得Tag的所有子孫節點

  • #.parent:取得Tag的父節點

  • .parents:遞歸得到父輩元素的所有節點,傳回一個生成器

  • .previous_sibling:取得目前Tag的上一個節點,屬性通常是字串或空白,真實結果是當前標籤與上一個標籤之間的頓號和換行符

  • ##.next_sibling:取得目前Tag的下一個節點,屬性通常是字串或空白,真是結果是目前標籤與下一個標籤之間的頓號與換行符

  • .previous_siblings:取得目前Tag的上面所有的兄弟節點,傳回一個生成器

  • .next_siblings:取得目前Tag的下面所有的兄弟節點,傳回一個生成器

  • .previous_element:取得解析過程中上一個被解析的物件(字串或tag),可能與previous_sibling相同,但通常是不一樣的

  • .next_element:取得解析過程中下一個被解析的物件(字串或tag),可能與next_sibling相同,但通常是不一樣的

  • .previous_elements:傳回一個生成器,可以向前存取文件的解析內容

  • .next_elements:傳回一個生成器,可以向後存取文件的解析內容

  • .strings:如果Tag包含多個字串,即在子孫節點中有內容,可以用此獲取,而後進行遍歷

  • #.stripped_strings:與strings用法一致,只不過可以去除掉那些多餘的空白內容

.has_attr:

判斷Tag是否包含屬性

五、搜尋文檔樹

1、find_all():過濾器

find_all(name, attrs, recursive, text, **kwargs):

find_all過濾器可以用在tag的name中,節點的屬性等。

(1)name參數:

字串過濾

:會尋找與字串完全匹配的內容

a_list = bs.find_all("a")
print(a_list)
登入後複製
正規表示式過濾:

如果傳入的是正規表示式,那麼BeautifulSoup4會透過search()來匹配內容

import re 

t_list = bs.find_all(re.compile("a")) 
for item in t_list: 
   print(item)
登入後複製
列表

:如果傳入一個列表,BeautifulSoup4將會與列表中的任一元素匹配到的節點回傳###
t_list = bs.find_all(["meta","link"])
for item in t_list:
    print(item)
登入後複製
#######方法###:傳入一個方法,根據方法來匹配###
def name_is_exists(tag): 
    return tag.has_attr("name") 
t_list = bs.find_all(name_is_exists) 
for item in t_list: 
    print(item)
登入後複製
(2)kwargs参数:
t_list = bs.find_all(id="head")  # 查询id=head的Tag
t_list = bs.find_all(href=re.compile(http://news.baidu.com))  # 查询href属性包含ss1.bdstatic.com的Tag
t_list = bs.find_all(class_=True) # 查询所有包含class的Tag(注意:class在Python中属于关键字,所以加_以示区别)
for item in t_list: 
    print(item)
登入後複製
(3)attrs参数:

并不是所有的属性都可以使用上面这种方式进行搜索,比如HTML的data-*属性:

t_list = bs.find_all(data-foo="value")
登入後複製

如果执行这段代码,将会报错。我们可以使用attrs参数,定义一个字典来搜索包含特殊属性的tag:

t_list = bs.find_all(attrs={"data-foo":"value"})
for item in t_list:
    print(item)
登入後複製
(4)text参数:

通过text参数可以搜索文档中的字符串内容,与name参数的可选值一样,text参数接受 字符串,正则表达式,列表

t_list = bs.find_all(text="hao123") 
t_list = bs.find_all(text=["hao123", "地图", "贴吧"]) 
t_list = bs.find_all(text=re.compile("\d"))
登入後複製

当我们搜索text中的一些特殊属性时,同样也可以传入一个方法来达到我们的目的:

def length_is_two(text):
    return text and len(text) == 2
t_list = bs.find_all(text=length_is_two)
登入後複製
(5)limit参数

可以传入一个limit参数来限制返回的数量,当搜索出的数据量为5,而设置了limit=2时,此时只会返回前2个数据

t_list = bs.find_all("a",limit=2)
登入後複製

find_all除了上面一些常规的写法,还可以对其进行一些简写:

# 下面两者是相等的
t_list = bs.find_all("a") 
t_list = bs("a") 

# 下面两者是相等的
t_list = bs.a.find_all(text="新闻") 
t_list = bs.a(text="新闻")
登入後複製

2、find()

find()将返回符合条件的第一个Tag,有时我们只需要或一个Tag时,我们就可以用到find()方法了。当然了,也可以使用find_all()方法,传入一个limit=1,然后再取出第一个值也是可以的,不过未免繁琐。

t_list = bs.find_all("title",limit=1) # 返回只有一个结果的列表
t = bs.find("title") # 返回唯一值
t = bs.find("abc") # 如果没有找到,则返回None
登入後複製

从结果可以看出find_all,尽管传入了limit=1,但是返回值仍然为一个列表,当我们只需要取一个值时,远不如find方法方便。但是如果未搜索到值时,将返回一个None。

在上面介绍BeautifulSoup4的时候,我们知道可以通过bs.div来获取第一个div标签,如果我们需要获取第一个div下的第一个div,我们可以这样:

t = bs.div.div
# 等价于
t = bs.find("div").find("div")
登入後複製

六、CSS选择器:select()方法

BeautifulSoup支持部分的CSS选择器,在Tag获取BeautifulSoup对象的.select()方法中传入字符串参数,即可使用CSS选择器的语法找到Tag:

print(bs.select(&#39;title&#39;))  # 1、通过标签名查找               
print(bs.select(&#39;a&#39;))                                
print(bs.select(&#39;.mnav&#39;))  # 2、通过类名查找                
print(bs.select(&#39;#u1&#39;))  # 3、通过id查找                  
print(bs.select(&#39;div .bri&#39;))  # 4、组合查找               
print(bs.select(&#39;a[class="bri"]&#39;))  # 5、属性查找         
print(bs.select(&#39;a[href="http://tieba.baidu.com" rel="external nofollow"  rel="external nofollow" ]&#39;)) 
print(bs.select("head > title"))  # 6、直接子标签查找        
print(bs.select(".mnav ~ .bri"))  # 7、兄弟节点标签查找       
print(bs.select(&#39;title&#39;)[0].get_text())  # 8、获取内容
登入後複製

七、综合实例:

from bs4 import BeautifulSoup
import requests,re
req_obj = requests.get(&#39;https://www.baidu.com&#39;)
soup = BeautifulSoup(req_obj.text,&#39;lxml&#39;)

&#39;&#39;&#39;标签查找&#39;&#39;&#39;
print(soup.title)              #只是查找出第一个
print(soup.find(&#39;title&#39;))      #效果和上面一样
print(soup.find_all(&#39;div&#39;))    #查出所有的div标签

&#39;&#39;&#39;获取标签里的属性&#39;&#39;&#39;
tag = soup.div
print(tag[&#39;class&#39;])   #多属性的话,会返回一个列表
print(tag[&#39;id&#39;])      #查找标签的id属性
print(tag.attrs)      #查找标签所有的属性,返回一个字典(属性名:属性值)

&#39;&#39;&#39;标签包的字符串&#39;&#39;&#39;
tag = soup.title
print(tag.string)                 #获取标签里的字符串
tag.string.replace_with("哈哈")    #字符串不能直接编辑,可以替换

&#39;&#39;&#39;子节点的操作&#39;&#39;&#39;
tag = soup.head
print(tag.title)     #获取head标签后再获取它包含的子标签

&#39;&#39;&#39;contents 和 .children&#39;&#39;&#39;
tag = soup.body
print(tag.contents)        #将标签的子节点以列表返回
print([child for child in tag.children])      #输出和上面一样


&#39;&#39;&#39;descendants&#39;&#39;&#39;
tag = soup.body
[print(child_tag) for child_tag in tag.descendants]    #获取所有子节点和子子节点

&#39;&#39;&#39;strings和.stripped_strings&#39;&#39;&#39;
tag = soup.body
[print(str) for str in tag.strings]             #输出所有所有文本内容
[print(str) for str in tag.stripped_strings]    #输出所有所有文本内容,去除空格或空行

&#39;&#39;&#39;.parent和.parents&#39;&#39;&#39;
tag = soup.title
print(tag.parent)                 #输出便签的父标签
[print(parent) for parent in tag.parents]  #输出所有的父标签

&#39;&#39;&#39;.next_siblings 和 .previous_siblings
    查出所有的兄弟节点
&#39;&#39;&#39;

&#39;&#39;&#39;.next_element 和 .previous_element
    下一个兄弟节点
&#39;&#39;&#39;

&#39;&#39;&#39;find_all的keyword 参数&#39;&#39;&#39;
soup.find_all(id=&#39;link2&#39;)                   #查找所有包含 id 属性的标签
soup.find_all(href=re.compile("elsie"))     #href 参数,Beautiful Soup会搜索每个标签的href属性:
soup.find_all(id=True)                       #找出所有的有id属性的标签
soup.find_all(href=re.compile("elsie"), id=&#39;link1&#39;)         #也可以组合查找
soup.find_all(attrs={"属性名": "属性值"})  #也可以通过字典的方式查找
登入後複製

八、BeautifulSoup 和lxml(Xpath)对比

# test.py
# -*- coding: utf-8 -*-
import requests
from bs4 import BeautifulSoup, SoupStrainer
import traceback
import json
from lxml import etree
import re
import time

def getHtmlText(url):
    try:
        r = requests.get(url, headers=headers)
        r.raise_for_status()
        if r.encoding == &#39;ISO-8859-1&#39;:
            r.encoding = r.apparent_encoding
        return r.text
    except:
        traceback.print_exc()

# ----------使用BeautifulSoup解析------------------------
def parseWithBeautifulSoup(html_text):
    soup = BeautifulSoup(html_text, &#39;lxml&#39;) 
    content = []
    for mulu in soup.find_all(class_=&#39;mulu&#39;): # 先找到所有的 div class=mulu 标记
        # 找到div_h3 标记
        h3 = mulu.find(&#39;h3&#39;)
        if h3 != None:
            h3_title = h3.string # 获取标题
            lst = []
            for a in mulu.select(&#39;div.box a&#39;):
                href = a.get(&#39;href&#39;) # 找到 href 属性
                box_title = a.get(&#39;title&#39;)  # 找到 title 属性
                pattern = re.compile(r&#39;\s*\[(.*)\]\s+(.*)&#39;) # (re) 匹配括号内的表达式,也表示一个组
                match = pattern.search(box_title)
                if match != None:
                    date = match.group(1)
                    real_title = match.group(2)
                    lst.append({&#39;href&#39;:href,&#39;title&#39;:real_title,&#39;date&#39;:date})
            content.append({&#39;title&#39;:h3_title,&#39;content&#39;:lst})
    with open(&#39;dmbj_bs.json&#39;, &#39;w&#39;) as fp:
        json.dump(content, fp=fp, indent=4)

# ----------使用Xpath解析------------------------
def parseWithXpath(html_text):
    html = etree.HTML(html_text)
    content = []
    for div_mulu in html.xpath(&#39;.//*[@class="mulu"]&#39;): # 先找到所有的 div class=mulu 标记
        # 找到所有的 div_h3 标记
        div_h3 = div_mulu.xpath(&#39;./div[@class="mulu-title"]/center/h3/text()&#39;)
        if len(div_h3) > 0:
            h3_title = div_h3[0] # 获取标题
            a_s = div_mulu.xpath(&#39;./div[@class="box"]/ul/li/a&#39;)
            lst = []
            for a in a_s:
                href = a.xpath(&#39;./@href&#39;)[0] # 找到 href 属性
                box_title = a.xpath(&#39;./@title&#39;)[0] # 找到 title 属性
                pattern = re.compile(r&#39;\s*\[(.*)\]\s+(.*)&#39;) # (re) 匹配括号内的表达式,也表示一个组
                match = pattern.search(box_title)
                if match != None:
                    date = match.group(1)
                    real_title = match.group(2)
                    lst.append({&#39;href&#39;:href,&#39;title&#39;:real_title,&#39;date&#39;:date})
            content.append({&#39;title&#39;:h3_title,&#39;content&#39;:lst})
    with open(&#39;dmbj_xp.json&#39;, &#39;w&#39;) as fp:
        json.dump(content, fp=fp, indent=4)

def main():
    html_text = getHtmlText(&#39;http://www.seputu.com&#39;)
    print(len(html_text))
    start = time.clock()
    parseWithBeautifulSoup(html_text)
    print(&#39;BSoup cost:&#39;, time.clock()-start)
    start = time.clock()
    parseWithXpath(html_text)
    print(&#39;Xpath cost:&#39;, time.clock()-start)

if __name__ == &#39;__main__&#39;:
    user_agent = &#39;Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.117 Safari/537.36&#39;
    headers={&#39;User-Agent&#39;: user_agent}
    main()
登入後複製

以上是Python如何使用Beautiful Soup(BS4)函式庫解析HTML和XML的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

PHP和Python:解釋了不同的範例 PHP和Python:解釋了不同的範例 Apr 18, 2025 am 12:26 AM

PHP主要是過程式編程,但也支持面向對象編程(OOP);Python支持多種範式,包括OOP、函數式和過程式編程。 PHP適合web開發,Python適用於多種應用,如數據分析和機器學習。

HTML:結構,CSS:樣式,JavaScript:行為 HTML:結構,CSS:樣式,JavaScript:行為 Apr 18, 2025 am 12:09 AM

HTML、CSS和JavaScript在Web開發中的作用分別是:1.HTML定義網頁結構,2.CSS控製網頁樣式,3.JavaScript添加動態行為。它們共同構建了現代網站的框架、美觀和交互性。

在PHP和Python之間進行選擇:指南 在PHP和Python之間進行選擇:指南 Apr 18, 2025 am 12:24 AM

PHP適合網頁開發和快速原型開發,Python適用於數據科學和機器學習。 1.PHP用於動態網頁開發,語法簡單,適合快速開發。 2.Python語法簡潔,適用於多領域,庫生態系統強大。

Python vs. JavaScript:學習曲線和易用性 Python vs. JavaScript:學習曲線和易用性 Apr 16, 2025 am 12:12 AM

Python更適合初學者,學習曲線平緩,語法簡潔;JavaScript適合前端開發,學習曲線較陡,語法靈活。 1.Python語法直觀,適用於數據科學和後端開發。 2.JavaScript靈活,廣泛用於前端和服務器端編程。

HTML的未來:網絡設計的發展和趨勢 HTML的未來:網絡設計的發展和趨勢 Apr 17, 2025 am 12:12 AM

HTML的未來充滿了無限可能。 1)新功能和標準將包括更多的語義化標籤和WebComponents的普及。 2)網頁設計趨勢將繼續向響應式和無障礙設計發展。 3)性能優化將通過響應式圖片加載和延遲加載技術提升用戶體驗。

PHP和Python:深入了解他們的歷史 PHP和Python:深入了解他們的歷史 Apr 18, 2025 am 12:25 AM

PHP起源於1994年,由RasmusLerdorf開發,最初用於跟踪網站訪問者,逐漸演變為服務器端腳本語言,廣泛應用於網頁開發。 Python由GuidovanRossum於1980年代末開發,1991年首次發布,強調代碼可讀性和簡潔性,適用於科學計算、數據分析等領域。

notepad 怎麼運行python notepad 怎麼運行python Apr 16, 2025 pm 07:33 PM

在 Notepad 中運行 Python 代碼需要安裝 Python 可執行文件和 NppExec 插件。安裝 Python 並為其添加 PATH 後,在 NppExec 插件中配置命令為“python”、參數為“{CURRENT_DIRECTORY}{FILE_NAME}”,即可在 Notepad 中通過快捷鍵“F6”運行 Python 代碼。

vscode在哪寫代碼 vscode在哪寫代碼 Apr 15, 2025 pm 09:54 PM

在 Visual Studio Code(VSCode)中編寫代碼簡單易行,只需安裝 VSCode、創建項目、選擇語言、創建文件、編寫代碼、保存並運行即可。 VSCode 的優點包括跨平台、免費開源、強大功能、擴展豐富,以及輕量快速。

See all articles