Python 爬蟲利器二之 Beautiful Soup 的用法

      網友投稿 985 2022-05-29

      上一節我們介紹了正則表達式,它的內容其實還是蠻多的,如果一個正則匹配稍有差池,那可能程序就處在永久的循環之中,而且有的小伙伴們也對寫正則表達式的寫法用得不熟練,沒關系,我們還有一個更強大的工具,叫 Beautiful Soup,有了它我們可以很方便地提取出 HTML 或 XML 標簽中的內容,實在是方便,這一節就讓我們一起來感受一下 Beautiful Soup 的強大吧。

      1. Beautiful Soup 的簡介

      簡單來說,Beautiful Soup 是 python 的一個庫,最主要的功能是從網頁抓取數據。官方解釋如下:

      Beautiful Soup 提供一些簡單的、python 式的函數用來處理導航、搜索、修改分析樹等功能。它是一個工具箱,通過解析文檔為用戶提供需要抓取的數據,因為簡單,所以不需要多少代碼就可以寫出一個完整的應用程序。 Beautiful Soup 自動將輸入文檔轉換為 Unicode 編碼,輸出文檔轉換為 utf-8 編碼。你不需要考慮編碼方式,除非文檔沒有指定一個編碼方式,這時,Beautiful Soup 就不能自動識別編碼方式了。然后,你僅僅需要說明一下原始編碼方式就可以了。 Beautiful Soup 已成為和 lxml、html6lib 一樣出色的 python 解釋器,為用戶靈活地提供不同的解析策略或強勁的速度。

      廢話不多說,我們來試一下吧~

      2. Beautiful Soup 安裝

      Beautiful Soup 3 目前已經停止開發,推薦在現在的項目中使用 Beautiful Soup 4,不過它已經被移植到 BS4 了,也就是說導入時我們需要 import bs4 。所以這里我們用的版本是 Beautiful Soup 4.3.2 (簡稱 BS4),另外據說 BS4 對 Python3 的支持不夠好,不過我用的是 Python2.7.7,如果有小伙伴用的是 Python3 版本,可以考慮下載 BS3 版本。 可以利用 pip 或者 easy_install 來安裝,以下兩種方法均可

      1

      easy_install beautifulsoup4

      1

      pip install beautifulsoup4

      如果想安裝最新的版本,請直接下載安裝包來手動安裝,也是十分方便的方法。在這里我安裝的是 Beautiful Soup 4.3.2 Beautiful Soup 3.2.1Beautiful Soup 4.3.2 下載完成之后解壓 運行下面的命令即可完成安裝

      1

      sudo python setup.py install

      然后需要安裝 lxml

      1

      easy_install lxml

      1

      pip install lxml

      另一個可供選擇的解析器是純 Python 實現的 html5lib , html5lib 的解析方式與瀏覽器相同,可以選擇下列方法來安裝 html5lib:

      1

      easy_install html5lib

      1

      pip install html5lib

      Beautiful Soup 支持 Python 標準庫中的 HTML 解析器,還支持一些第三方的解析器,如果我們不安裝它,則 Python 會使用 Python 默認的解析器,lxml 解析器更加強大,速度更快,推薦安裝。

      解析器

      使用方法

      優勢

      劣勢

      Python 標準庫

      BeautifulSoup(markup, “html.parser”)

      Python 的內置標準庫

      執行速度適中

      文檔容錯能力強

      Python 2.7.3 or 3.2.2) 前 的版本中文檔容錯能力差

      lxml HTML 解析器

      BeautifulSoup(markup, “lxml”)

      速度快

      文檔容錯能力強

      Python 爬蟲利器二之 Beautiful Soup 的用法

      需要安裝 C 語言庫

      lxml XML 解析器

      BeautifulSoup(markup, [“lxml”, “xml”])BeautifulSoup(markup, “xml”)

      速度快

      唯一支持 XML 的解析器

      需要安裝 C 語言庫

      html5lib

      BeautifulSoup(markup, “html5lib”)

      最好的容錯性

      以瀏覽器的方式解析文檔

      生成 HTML5 格式的文檔

      速度慢

      不依賴外部擴展

      3. 開啟 Beautiful Soup 之旅

      在這里先分享官方文檔鏈接,不過內容是有些多,也不夠條理,在此本文章做一下整理方便大家參考。 官方文檔

      4. 創建 Beautiful Soup 對象

      首先必須要導入 bs4 庫

      1

      from bs4 import BeautifulSoup

      我們創建一個字符串,后面的例子我們便會用它來演示

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      html = """

      The Dormouse's story

      The Dormouse's story

      Once upon a time there were three little sisters; and their names were

      ,

      Lacie and

      Tillie;

      and they lived at the bottom of a well.

      ...

      """

      創建 beautifulsoup 對象

      1

      soup = BeautifulSoup(html)

      另外,我們還可以用本地 HTML 文件來創建對象,例如

      1

      soup = BeautifulSoup(open('index.html'))

      上面這句代碼便是將本地 index.html 文件打開,用它來創建 soup 對象 下面我們來打印一下 soup 對象的內容,格式化輸出

      1

      print soup.prettify()

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      </p><p>The Dormouse's story</p><p>

      The Dormouse's story

      Once upon a time there were three little sisters; and their names were

      ,

      Lacie

      and

      Tillie

      ;

      and they lived at the bottom of a well.

      ...

      以上便是輸出結果,格式化打印出了它的內容,這個函數經常用到,小伙伴們要記好咯。

      5. 四大對象種類

      Beautiful Soup 將復雜 HTML 文檔轉換成一個復雜的樹形結構,每個節點都是 Python 對象,所有對象可以歸納為 4 種:

      Tag

      NavigableString

      BeautifulSoup

      Comment

      下面我們進行一一介紹

      (1)Tag

      Tag 是什么?通俗點講就是 HTML 中的一個個標簽,例如

      1

      The Dormouse's story

      1

      Elsie

      上面的 title a 等等 HTML 標簽加上里面包括的內容就是 Tag,下面我們來感受一下怎樣用 Beautiful Soup 來方便地獲取 Tags 下面每一段代碼中注釋部分即為運行結果

      1

      2

      print soup.title

      #The Dormouse's story

      1

      2

      print soup.head

      #The Dormouse's story

      1

      2

      print soup.a

      #

      1

      2

      print soup.p

      #

      The Dormouse's story

      我們可以利用 soup 加標簽名輕松地獲取這些標簽的內容,是不是感覺比正則表達式方便多了?不過有一點是,它查找的是在所有內容中的第一個符合要求的標簽,如果要查詢所有的標簽,我們在后面進行介紹。 我們可以驗證一下這些對象的類型

      1

      2

      print type(soup.a)

      #

      對于 Tag,它有兩個重要的屬性,是 name 和 attrs,下面我們分別來感受一下 name

      1

      2

      3

      4

      print soup.name

      print soup.head.name

      #[document]

      #head

      soup 對象本身比較特殊,它的 name 即為 [document],對于其他內部標簽,輸出的值便為標簽本身的名稱。 attrs

      1

      2

      print soup.p.attrs

      #{'class': ['title'], 'name': 'dromouse'}

      在這里,我們把 p 標簽的所有屬性打印輸出了出來,得到的類型是一個字典。 如果我們想要單獨獲取某個屬性,可以這樣,例如我們獲取它的 class 叫什么

      1

      2

      print soup.p['class']

      #['title']

      還可以這樣,利用 get 方法,傳入屬性的名稱,二者是等價的

      1

      2

      print soup.p.get('class')

      #['title']

      我們可以對這些屬性和內容等等進行修改,例如

      1

      2

      3

      soup.p['class']="newClass"

      print soup.p

      #

      The Dormouse's story

      還可以對這個屬性進行刪除,例如

      1

      2

      3

      del soup.p['class']

      print soup.p

      #

      The Dormouse's story

      不過,對于修改刪除的操作,不是我們的主要用途,在此不做詳細介紹了,如果有需要,請查看前面提供的官方文檔

      (2)NavigableString

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

      1

      2

      print soup.p.string

      #The Dormouse's story

      這樣我們就輕松獲取到了標簽里面的內容,想想如果用正則表達式要多麻煩。它的類型是一個 NavigableString,翻譯過來叫 可以遍歷的字符串,不過我們最好還是稱它英文名字吧。 來檢查一下它的類型

      1

      2

      print type(soup.p.string)

      #

      (3)BeautifulSoup

      BeautifulSoup 對象表示的是一個文檔的全部內容。大部分時候,可以把它當作 Tag 對象,是一個特殊的 Tag,我們可以分別獲取它的類型,名稱,以及屬性來感受一下

      1

      2

      3

      4

      5

      6

      print type(soup.name)

      #

      print soup.name

      # [document]

      print soup.attrs

      #{} 空字典

      (4)Comment

      Comment 對象是一個特殊類型的 NavigableString 對象,其實輸出的內容仍然不包括注釋符號,但是如果不好好處理它,可能會對我們的文本處理造成意想不到的麻煩。 我們找一個帶注釋的標簽

      1

      2

      3

      print soup.a

      print soup.a.string

      print type(soup.a.string)

      運行結果如下

      1

      2

      3

      Elsie

      a 標簽里的內容實際上是注釋,但是如果我們利用 .string 來輸出它的內容,我們發現它已經把注釋符號去掉了,所以這可能會給我們帶來不必要的麻煩。 另外我們打印輸出下它的類型,發現它是一個 Comment 類型,所以,我們在使用前最好做一下判斷,判斷代碼如下

      1

      2

      if type(soup.a.string)==bs4.element.Comment:

      print soup.a.string

      上面的代碼中,我們首先判斷了它的類型,是否為 Comment 類型,然后再進行其他操作,如打印輸出。

      6. 遍歷文檔樹

      (1)直接子節點

      要點:.contents .children 屬性

      .contents tag 的 .content 屬性可以將 tag 的子節點以列表的方式輸出

      1

      2

      print soup.head.contents

      #[The Dormouse's story]

      輸出方式為列表,我們可以用列表索引來獲取它的某一個元素

      1

      2

      print soup.head.contents[0]

      #The Dormouse's story

      .children 它返回的不是一個 list,不過我們可以通過遍歷獲取所有子節點。 我們打印輸出 .children 看一下,可以發現它是一個 list 生成器對象

      1

      2

      print soup.head.children

      #

      我們怎樣獲得里面的內容呢?很簡單,遍歷一下就好了,代碼及結果如下

      1

      2

      for child in soup.body.children:

      print child

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      The Dormouse's story

      Once upon a time there were three little sisters; and their names were

      ,

      Lacie and

      Tillie;

      and they lived at the bottom of a well.

      ...

      (2)所有子孫節點

      知識點:.descendants 屬性

      .descendants .contents 和 .children 屬性僅包含 tag 的直接子節點,.descendants 屬性可以對所有 tag 的子孫節點進行遞歸循環,和 children 類似,我們也需要遍歷獲取其中的內容。

      1

      2

      for child in soup.descendants:

      print child

      運行結果如下,可以發現,所有的節點都被打印出來了,先生最外層的 HTML 標簽,其次從 head 標簽一個個剝離,以此類推。

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      38

      39

      40

      41

      42

      43

      44

      45

      46

      47

      48

      49

      50

      51

      52

      53

      54

      The Dormouse's story

      The Dormouse's story

      Once upon a time there were three little sisters; and their names were

      ,

      Lacie and

      Tillie;

      and they lived at the bottom of a well.

      ...

      The Dormouse's story

      The Dormouse's story

      The Dormouse's story

      The Dormouse's story

      Once upon a time there were three little sisters; and their names were

      ,

      Lacie and

      Tillie;

      and they lived at the bottom of a well.

      ...

      The Dormouse's story

      The Dormouse's story

      The Dormouse's story

      Once upon a time there were three little sisters; and their names were

      ,

      Lacie and

      Tillie;

      and they lived at the bottom of a well.

      Once upon a time there were three little sisters; and their names were

      Elsie

      ,

      Lacie

      Lacie

      and

      Tillie

      Tillie

      ;

      and they lived at the bottom of a well.

      ...

      ...

      (3)節點內容

      知識點:.string 屬性

      如果 tag 只有一個 NavigableString 類型子節點,那么這個 tag 可以使用 .string 得到子節點。如果一個 tag 僅有一個子節點,那么這個 tag 也可以使用 .string 方法,輸出結果與當前唯一子節點的 .string 結果相同。 通俗點說就是:如果一個標簽里面沒有標簽了,那么 .string 就會返回標簽里面的內容。如果標簽里面只有唯一的一個標簽了,那么 .string 也會返回最里面的內容。例如

      1

      2

      3

      4

      print soup.head.string

      #The Dormouse's story

      print soup.title.string

      #The Dormouse's story

      如果 tag 包含了多個子節點,tag 就無法確定,string 方法應該調用哪個子節點的內容,.string 的輸出結果是 None

      1

      2

      print soup.html.string

      # None

      (4)多個內容

      知識點: .strings .stripped_strings 屬性

      .strings 獲取多個內容,不過需要遍歷獲取,比如下面的例子

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      for string in soup.strings:

      print(repr(string))

      # u"The Dormouse's story"

      # u'\n\n'

      # u"The Dormouse's story"

      # u'\n\n'

      # u'Once upon a time there were three little sisters; and their names were\n'

      # u'Elsie'

      # u',\n'

      # u'Lacie'

      # u' and\n'

      # u'Tillie'

      # u';\nand they lived at the bottom of a well.'

      # u'\n\n'

      # u'...'

      # u'\n'

      .stripped_strings 輸出的字符串中可能包含了很多空格或空行,使用 .stripped_strings 可以去除多余空白內容

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      for string in soup.stripped_strings:

      print(repr(string))

      # u"The Dormouse's story"

      # u"The Dormouse's story"

      # u'Once upon a time there were three little sisters; and their names were'

      # u'Elsie'

      # u','

      # u'Lacie'

      # u'and'

      # u'Tillie'

      # u';\nand they lived at the bottom of a well.'

      # u'...'

      (5)父節點

      知識點: .parent 屬性

      1

      2

      3

      p = soup.p

      print p.parent.name

      #body

      1

      2

      3

      content = soup.head.title.string

      print content.parent.name

      #title

      (6)全部父節點

      知識點:.parents 屬性

      通過元素的 .parents 屬性可以遞歸得到元素的所有父輩節點,例如

      1

      2

      3

      content = soup.head.title.string

      for parent in content.parents:

      print parent.name

      1

      2

      3

      4

      title

      head

      html

      [document]

      (7)兄弟節點

      知識點:.next_sibling .previous_sibling 屬性

      兄弟節點可以理解為和本節點處在統一級的節點,.next_sibling 屬性獲取了該節點的下一個兄弟節點,.previous_sibling 則與之相反,如果節點不存在,則返回 None 注意:實際文檔中的 tag 的 .next_sibling 和 .previous_sibling 屬性通常是字符串或空白,因為空白或者換行也可以被視作一個節點,所以得到的結果可能是空白或者換行

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      print soup.p.next_sibling

      # 實際該處為空白

      print soup.p.prev_sibling

      #None 沒有前一個兄弟節點,返回 None

      print soup.p.next_sibling.next_sibling

      #

      Once upon a time there were three little sisters; and their names were

      #,

      #Lacie and

      #Tillie;

      #and they lived at the bottom of a well.

      #下一個節點的下一個兄弟節點是我們可以看到的節點

      (8)全部兄弟節點

      知識點:.next_siblings .previous_siblings 屬性

      通過 .next_siblings 和 .previous_siblings 屬性可以對當前節點的兄弟節點迭代輸出

      1

      2

      3

      4

      5

      6

      7

      8

      for sibling in soup.a.next_siblings:

      print(repr(sibling))

      # u',\n'

      # Lacie

      # u' and\n'

      # Tillie

      # u'; and they lived at the bottom of a well.'

      # None

      (9)前后節點

      知識點:.next_element .previous_element 屬性

      與 .next_sibling .previous_sibling 不同,它并不是針對于兄弟節點,而是在所有節點,不分層次 比如 head 節點為

      1

      The Dormouse's story

      那么它的下一個節點便是 title,它是不分層次關系的

      1

      2

      print soup.head.next_element

      #The Dormouse's story

      (10)所有前后節點

      知識點:.next_elements .previous_elements 屬性

      通過 .next_elements 和 .previous_elements 的迭代器就可以向前或向后訪問文檔的解析內容,就好像文檔正在被解析一樣

      1

      2

      3

      4

      5

      6

      7

      8

      9

      for element in last_a_tag.next_elements:

      print(repr(element))

      # u'Tillie'

      # u';\nand they lived at the bottom of a well.'

      # u'\n\n'

      #

      ...

      # u'...'

      # u'\n'

      # None

      以上是遍歷文檔樹的基本用法。

      7. 搜索文檔樹

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

      find_all () 方法搜索當前 tag 的所有 tag 子節點,并判斷是否符合過濾器的條件 1)name 參數 name 參數可以查找所有名字為 name 的 tag, 字符串對象會被自動忽略掉 A. 傳字符串 最簡單的過濾器是字符串。在搜索方法中傳入一個字符串參數,Beautiful Soup 會查找與字符串完整匹配的內容,下面的例子用于查找文檔中所有的標簽

      1

      2

      soup.find_all('b')

      # [The Dormouse's story]

      1

      2

      print soup.find_all('a')

      #[, Lacie, Tillie]

      B. 傳正則表達式 如果傳入正則表達式作為參數,Beautiful Soup 會通過正則表達式的 match () 來匹配內容。下面例子中找出所有以 b 開頭的標簽,這表示 和標簽都應該被找到

      1

      2

      3

      4

      5

      import re

      for tag in soup.find_all(re.compile("^b")):

      print(tag.name)

      # body

      # b

      C. 傳列表 如果傳入列表參數,Beautiful Soup 會將與列表中任一元素匹配的內容返回。下面代碼找到文檔中所有標簽和標簽

      1

      2

      3

      4

      5

      soup.find_all(["a", "b"])

      # [The Dormouse's story,

      # Elsie,

      # Lacie,

      # Tillie]

      D. 傳 True True 可以匹配任何值,下面代碼查找到所有的 tag, 但是不會返回字符串節點

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      for tag in soup.find_all(True):

      print(tag.name)

      # html

      # head

      # title

      # body

      # p

      # b

      # p

      # a

      # a

      E. 傳方法 如果沒有合適過濾器,那么還可以定義一個方法,方法只接受一個元素參數 [4] , 如果這個方法返回 True 表示當前元素匹配并且被找到,如果不是則反回 False 下面方法校驗了當前元素,如果包含 class 屬性卻不包含 id 屬性,那么將返回 True:

      1

      2

      def has_class_but_no_id(tag):

      return tag.has_attr('class') and not tag.has_attr('id')

      將這個方法作為參數傳入 find_all () 方法,將得到所有

      標簽:

      1

      2

      3

      4

      soup.find_all(has_class_but_no_id)

      # [

      The Dormouse's story

      ,

      #

      Once upon a time there were...

      ,

      #

      ...

      ]

      2)keyword 參數

      注意:如果一個指定名字的參數不是搜索內置的參數名,搜索時會把該參數當作指定名字 tag 的屬性來搜索,如果包含一個名字為 id 的參數,Beautiful Soup 會搜索每個 tag 的”id” 屬性

      1

      2

      soup.find_all(id='link2')

      # [Lacie]

      如果傳入 href 參數,Beautiful Soup 會搜索每個 tag 的”href” 屬性

      1

      2

      soup.find_all(href=re.compile("elsie"))

      # [Elsie]

      使用多個指定名字的參數可以同時過濾 tag 的多個屬性

      1

      2

      soup.find_all(href=re.compile("elsie"), id='link1')

      # [three]

      在這里我們想用 class 過濾,不過 class 是 python 的關鍵詞,這怎么辦?加個下劃線就可以

      1

      2

      3

      4

      soup.find_all("a", class_="sister")

      # [Elsie,

      # Lacie,

      # Tillie]

      有些 tag 屬性在搜索不能使用,比如 HTML5 中的 data-* 屬性

      1

      2

      3

      data_soup = BeautifulSoup('

      foo!
      ')

      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"})

      # [

      foo!
      ]

      3)text 參數 通過 text 參數可以搜搜文檔中的字符串內容。與 name 參數的可選值一樣,text 參數接受 字符串,正則表達式,列表,True

      1

      2

      3

      4

      5

      6

      7

      8

      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"]

      4)limit 參數 find_all () 方法返回全部的搜索結構,如果文檔樹很大那么搜索會很慢。如果我們不需要全部結果,可以使用 limit 參數限制返回結果的數量。效果與 SQL 中的 limit 關鍵字類似,當搜索到的結果數量達到 limit 的限制時,就停止搜索返回結果。文檔樹中有 3 個 tag 符合搜索條件,但結果只返回了 2 個,因為我們限制了返回數量

      1

      2

      3

      soup.find_all("a", limit=2)

      # [Elsie,

      # Lacie]

      5)recursive 參數 調用 tag 的 find_all () 方法時,Beautiful Soup 會檢索當前 tag 的所有子孫節點,如果只想搜索 tag 的直接子節點,可以使用參數 recursive=False . 一段簡單的文檔:

      1

      2

      3

      4

      5

      6

      7

      </p><p>The Dormouse's story</p><p>

      ...

      是否使用 recursive 參數的搜索結果:

      1

      2

      3

      4

      5

      soup.html.find_all("title")

      # [The Dormouse's story]

      soup.html.find_all("title", recursive=False)

      # []

      (2)find( name , attrs , recursive , text , **kwargs )

      它與 find_all () 方法唯一的區別是 find_all () 方法的返回結果是值包含一個元素的列表,而 find () 方法直接返回結果

      (3)find_parents() find_parent()

      find_all () 和 find () 只搜索當前節點的所有子節點,孫子節點等. find_parents () 和 find_parent () 用來搜索當前節點的父輩節點,搜索方法與普通 tag 的搜索方法相同,搜索文檔搜索文檔包含的內容

      (4)find_next_siblings() find_next_sibling()

      這 2 個方法通過 .next_siblings 屬性對當 tag 的所有后面解析的兄弟 tag 節點進行迭代,find_next_siblings () 方法返回所有符合條件的后面的兄弟節點,find_next_sibling () 只返回符合條件的后面的第一個 tag 節點

      (5)find_previous_siblings() find_previous_sibling()

      這 2 個方法通過 .previous_siblings 屬性對當前 tag 的前面解析的兄弟 tag 節點進行迭代,find_previous_siblings () 方法返回所有符合條件的前面的兄弟節點,find_previous_sibling () 方法返回第一個符合條件的前面的兄弟節點

      (6)find_all_next() find_next()

      這 2 個方法通過 .next_elements 屬性對當前 tag 的之后的 tag 和字符串進行迭代,find_all_next () 方法返回所有符合條件的節點,find_next () 方法返回第一個符合條件的節點

      (7)find_all_previous () 和 find_previous ()

      這 2 個方法通過 .previous_elements 屬性對當前節點前面的 tag 和字符串進行迭代,find_all_previous () 方法返回所有符合條件的節點,find_previous () 方法返回第一個符合條件的節點

      注:以上(2)(3)(4)(5)(6)(7)方法參數用法與 find_all () 完全相同,原理均類似,在此不再贅述。

      8.CSS 選擇器

      我們在寫 CSS 時,標簽名不加任何修飾,類名前加點,id 名前加 #,在這里我們也可以利用類似的方法來篩選元素,用到的方法是 soup.select(),返回類型是 list

      (1)通過標簽名查找

      1

      2

      print soup.select('title')

      #[The Dormouse's story]

      1

      2

      print soup.select('a')

      #[, Lacie, Tillie]

      1

      2

      print soup.select('b')

      #[The Dormouse's story]

      (2)通過類名查找

      1

      2

      print soup.select('.sister')

      #[, Lacie, Tillie]

      (3)通過 id 名查找

      1

      2

      print soup.select('#link1')

      #[]

      (4)組合查找

      組合查找即和寫 class 文件時,標簽名與類名、id 名進行的組合原理是一樣的,例如查找 p 標簽中,id 等于 link1 的內容,二者需要用空格分開

      1

      2

      print soup.select('p #link1')

      #[]

      直接子標簽查找

      1

      2

      print soup.select("head > title")

      #[The Dormouse's story]

      (5)屬性查找

      查找時還可以加入屬性元素,屬性需要用中括號括起來,注意屬性和標簽屬于同一節點,所以中間不能加空格,否則會無法匹配到。

      1

      2

      print soup.select('a[class="sister"]')

      #[, Lacie, Tillie]

      1

      2

      print soup.select('a[href="http://example.com/elsie"]')

      #[]

      同樣,屬性仍然可以與上述查找方式組合,不在同一節點的空格隔開,同一節點的不加空格

      1

      2

      print soup.select('p a[href="http://example.com/elsie"]')

      #[]

      以上的 select 方法返回的結果都是列表形式,可以遍歷形式輸出,然后用 get_text () 方法來獲取它的內容。

      1

      2

      3

      4

      5

      6

      soup = BeautifulSoup(html, 'lxml')

      print type(soup.select('title'))

      print soup.select('title')[0].get_text()

      for title in soup.select('title'):

      print title.get_text()

      好,這就是另一種與 find_all 方法有異曲同工之妙的查找方法,是不是感覺很方便?

      總結

      本篇內容比較多,把 Beautiful Soup 的方法進行了大部分整理和總結,不過這還不算完全,仍然有 Beautiful Soup 的修改刪除功能,不過這些功能用得比較少,只整理了查找提取的方法,希望對大家有幫助!小伙伴們加油! 熟練掌握了 Beautiful Soup,一定會給你帶來太多方便,加油吧!

      HTML Python

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:操作系統學習筆記(十五)~死鎖概念+死鎖預防
      下一篇:uniCloud基礎入門(三)---云數據庫基礎
      相關文章
      亚洲人成电影网站| 亚洲六月丁香六月婷婷色伊人| 亚洲w码欧洲s码免费| 久久久久亚洲Av无码专| 久久精品国产亚洲AV网站| 亚洲国产精品一区第二页| 亚洲日产韩国一二三四区| 亚洲日本va在线视频观看| 亚洲日产无码中文字幕| 亚洲成AV人片在线观看ww| 国产国拍亚洲精品mv在线观看| 亚洲大尺度无码无码专区| 亚洲AV无码久久| 亚洲人成亚洲精品| 中文字幕亚洲综合精品一区| 亚洲人成网站在线播放2019| 亚洲国产日韩视频观看| 亚洲人成人伊人成综合网无码 | 亚洲日韩精品无码专区| 亚洲色偷偷综合亚洲AV伊人蜜桃| 亚洲人成人网毛片在线播放| 在线观看亚洲AV日韩AV| 亚洲精品蜜夜内射| 亚洲成人高清在线| 国产亚洲AV夜间福利香蕉149| 国产亚洲免费的视频看| 亚洲一区二区三区日本久久九| 亚洲的天堂av无码| 亚洲国产综合精品中文第一| 亚洲av无码无线在线观看| 亚洲高清免费视频| 亚洲毛片αv无线播放一区| 亚洲AV日韩AV天堂一区二区三区| 亚洲伦另类中文字幕| 亚洲女人影院想要爱| 亚洲熟女综合色一区二区三区| 日韩国产欧美亚洲v片| 国产精品亚洲综合一区| 久久精品国产亚洲香蕉| 亚洲国产日韩在线| 亚洲精品无码高潮喷水A片软|