1. 程式人生 > >python課程設計筆記(五) ----Resuests+BeautifulSoup (爬蟲入門)

python課程設計筆記(五) ----Resuests+BeautifulSoup (爬蟲入門)

官方參考文件(中文版):

requests:http://docs.python-requests.org/zh_CN/latest/user/quickstart.html

beautifulsoup:https://www.crummy.com/software/BeautifulSoup/bs4/doc.zh/

 這篇部落格只是簡單介紹思路,建議直接閱讀上面的官方文件

 

目標

從一個HTML或XML檔案中提取資料,節省人工的時間。我這裡提取一個html頁面(https://www.zxzhijia.com/tuce/f1301_h_m )的所有圖片。

 

需要安裝的:requests 

 beautifulsouplxml解析器

  •  requests 安裝: pip install requests
  • beautifulsoup 安裝:pip install beautifulsoup4
  • lxml解析器安裝:pip install lxml

requests: 獲取某個URL的內容。(這裡只用到了獲取HTML的內容)

Beautiful Soup :從HTML或XML檔案中提取資料。

lxml解析器:beautifulsoup提取資料時用到。

requests獲得的HTML內容要用lxml解析,用BeautifulSoup提取。

 

效果演示:

 爬取的HTML頁面:https://www.zxzhijia.com/tuce/f1301_h_m,要爬取七張裝修案例的圖片,把圖片路徑放入MySQL資料庫

#爬取裝修圖片
import requests
import re  #正則表示式from bs4 import BeautifulSoup


#利用requests獲取html網頁內容
res=requests.get("https://www.zxzhijia.com/tuce/f1301_h_m")
#傳給beautifulsoup,指定用lxml解析器解析
soup = BeautifulSoup(res.text, '
lxml') #獲得指定7個img影象 img_src=soup.find(name='div',class_='waterfall').findAll(name="img",src=re.compile("img"),limit=7) for img in img_src: img=img['src'] #抓取src屬性的屬性值(圖片的href)print(img)

 

 

 

 

詳解beautifulsoup的作用

res=requests.get("https://www.zxzhijia.com/tuce/f1301_h_m")

soup = BeautifulSoup(res.text, 'lxml')

這兩句之後soup裡面就有html的內容了。

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

 

樹形結構很關鍵,比如一段這樣的html,(下面都以這段為例):

<html>

<head>

<title>測試介面</title>

</head>

<body>

<div>

<ul class="c">

    <li class="c">beautifulsoup</li>

    <li><span>span裡面的字</span>span外的字</li>

    <li><a href="#">連結</a></li>

</ul>

</div>

</body>

 

beautifulsoap會生成文件樹,我把它畫出來 了:

(直接從ul開始畫)--就已經這麼麻煩了

一個紅框稱為一個節點!!仔細看字串也是一個節點!!

 

 

 

 

分析文件樹中的節點(紅框框):

  • Tag型別:是最普通的節點,看圖中這些,一個框叫一個Tag物件,不是”a””div”。看最上面的這個Tag物件,它的name(名字)是“ul”,它擁有的attributes(屬性)是“class”,而這個屬性的值為“c”。
  • NavigableString型別:普通字串也一種節點型別。
  •  BeautifulSoup 型別:表示的是一個文件的全部內容。大部分時候,可以把它當作 Tag 物件。就是一個HTML轉換成樹以後最上方的節點,比<html>..</html>還高。
  • Comment型別:註釋,不多講。

 

 

操作和遍歷一個Tag物件的子節點

Beautiful Soup提供了許多操作和遍歷子節點的屬性。

 1 獲取單個Tag物件

獲取單個tag:  tag = soup.tag的名字    ----------這種方法只取當前名字的第一個Tag       

import requests

from bs4 import BeautifulSoup

response=requests.get("http://localhost/test/test.html")

soup = BeautifulSoup(response.text, 'lxml')

 

tag=soup.li

print(tag.name)

#li
print(tag.string)
#beautifulsoup

 

 獲取單個tag物件裡面的子tag物件:   soup.tag名.tag名

 

2 獲取一堆tag物件,用find_all()方法  !!注意,返回的時子節點列表,獲得tag物件或navigatestring物件需要遍歷這個列表

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

搜尋當前tag的所有tag子節點,並判斷是否符合條件,返回的是一堆子節點。

name:tag的名字,可以是字串('a')、正則表示式(瞭解re的使用),列表['a','div'],或者 True(全部) .

attrs={‘屬性名a’,‘屬性值b’} :搜尋子節點中擁有屬性a,且a="b"的。

一般寫法:可以直接寫成 屬性名a=‘屬性值b’   id='aaa'   ,多個時用”,”隔開就可以。

對於css屬性class 需要寫成 _class="名稱",這樣單個多個都可以匹配。 不能寫成class="  ",因為”class"時python保留字會有語法錯誤,寫成attrs 時,如果class=“a b" ,就算只想搜尋a,也必須寫{”class":"a b"}才能搜尋到這個tag,必須要完全匹配,所以不適合這麼寫。

text :tag裡面夾的string內容,soup.find_all(text=["Tillie", "Elsie", "Lacie"])

limit:可以使用 limit 引數限制返回結果的數量。當搜尋到的結果數量達到 limit 的限制時,就停止搜尋返回結果。文件樹中有3個tag符合搜尋條件,但結果只返回了2個,因為我們限制了返回數量:

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

recursive:呼叫tag的 find_all() 方法時,Beautiful Soup會檢索當前tag的所有子孫節點,如果只想搜尋tag的直接子節點,可以使用引數 recursive=False

 

tag=soup.find_all("li")
tag=soup.find_all(re.compile("l"))
tag=soup.find_all(name='li',class_='c')
tag=soup.find_all('li',attrs={'class','c'})
tag=soup.find_all(True)
tag=soup.fine_all('li',limit=2)

 

 

 

find()方法:!!注意,獲得的是一個子節點,就是tag物件或navigatestring物件,可以直接使用.name .string ['屬性名']

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

 

3  獲取tag物件的屬性值和tag物件裡面的字串內容(<div>XXX</div>中的XXX)

屬性值:

  tag['屬性名']

 字串內容:

  .string

一個tag物件中間的字串,可以直接tag.string

如果tag只有一個 NavigableString 型別子節點,那麼這個tag可以使用 .string 得到子節點:tag.string

如果一個tag僅有一個子節點,那麼這個tag也可以使用 .string 方法,輸出結果與當前唯一子節點的 .string 結果相同.

如果tag有超過一個子節點就不能直接.string,只會輸出None

舉例:遍歷find_all()獲得的list:

tags=soup.find_all('li')
for item in tags:
    print(item.string)

#beautifulsoup
#None
#連結

 

4 遍歷一個tag物件的所有子節點

.contents 一個tag物件的所有直接子節點組成的list

迴圈遍歷直接子節點 .children

for child in tag.children:  

  print(child)

 

迴圈遍歷所有子節點 .descendants

for child in tag.descendants:
  print(child)