當前位置:
首頁 > 知識 > 詳解Python爬取房天下的推薦新樓盤

詳解Python爬取房天下的推薦新樓盤

點擊上方「

Python開發

」,選擇「置頂公眾號」


關鍵時刻,第一時間送達!






最近一直在關注Python寫爬蟲相關的知識,嘗試了採用requests + Beautiful Soup來爬取房天下(原搜房網)的推薦新樓盤。

不用不知道,一用發現有驚喜也有驚嚇,本文就一同記錄下驚喜和踩的一些亂碼的坑。


首先,覺得Beautiful Soup解析網頁更加符合人類的常規思維,比使用正則表達式(Python中的re庫)更容易理解。 同時關於requests遇到了中文字元和特殊字元解碼的問題。本文都將給於深入的解說。


軟體環境


Python: 3.6.0


PyCharm: Community 2017.2


庫1 : requests


庫2 : beautiful soup


Requests知識概要

Requests 是用Python語言編寫,基於 urllib,採用 Apache2 Licensed 開源協議的 HTTP 庫。它比 urllib 更加方便,可以節約我們大量的工作,完全滿足 HTTP 測試需求。


完全支持Python3哦


1、安裝requests


可以採用pip安裝requests,具體代碼是:

pip install requests

2、簡單例子


下面例子中是幾個常用的屬性,text可以特到html的源代碼,encoding默認為ISO-8859-1,此編碼針對英文沒有問題,如果我們的網頁中帶有中文,將會引起亂碼的問題。後面有解決方案。

import

requests
response = requests.get(

"http://sh.fang.com/"

)

#獲取一個Http請求


print(response.encoding)          

#當前編碼,默認為 ISO-8859-1


print(response.apparent_encoding)

#當前網頁的內容的實際編碼


print(response.content)  

#content返回的是bytes型的原始數據


print(response.text)    

#text返回的是處理過的Unicode型的數據


Beautiful Soup簡要知識


1、Beautiful Soup 




Beautiful Soup

是一個非常流行的 Python 模塊。 該模塊可以解析網頁, 並提供定位 內 容的便捷介面 。 如果你還沒有安裝該模塊,可以使用下面的命令


安裝其最新版本:

pip install beautifulsoup4

使用 Beautiful Soup 的第一步是將下載的 HTML 內容解析為 Soup 文檔 。




2、如何引用bs

from

bs4

import

BeautifulSoup

3、一個簡單例子

from

bs4

import

BeautifulSoup

html =

"<ul class="country"><li>中國</li><li>美國</li></ul>"

# 解析html然後得到一個soup文檔


soup = BeautifulSoup(html,

"html.parser"

)
html = soup.prettify()
ul = soup.find(

"ul"

,attrs={

"class"

:

"country"

})

#下面代碼只返回一個匹配的元素


print(ul.find(

"li"

))    

# returns the first match element

#下面代碼返回又有匹配的元素


for

countryname

in

ul.find_all(

"li"

):
   print(countryname)

實戰爬取房天下推薦新樓盤


1、在Chrome中打開sh.fang.com地址,按F12觀察新盤推薦tab的網頁源代碼結構


主要結構是: 頂層為一個名為ti011的div,下面有四個class為tenrtd的div用於四個樓盤的現實。每個樓盤下面有一個class = 「text1」的div存儲了樓盤名稱,另一個class = 「text2」的存儲了樓盤的價格。


2. 第一版代碼完成如下,但是發現有一個中文亂碼的問題

from

bs4

import

BeautifulSoup

import

requests
rep = requests.get(

"http://sh.fang.com/"

)
html = rep.text
soup = BeautifulSoup(html,

"html.parser"

)

#獲取頂層 新盤推薦 的整個div


div = soup.find(

"div"

,attrs={

"id"

:

"ti011"

})

#獲取四個樓盤的div,更具他們的class = "tenrtd"


for

house

in

div.find_all(

"div"

, attrs={

"class"

:

"tenrtd"

}):

   

# 根據class="text1"獲取存儲樓盤標題的div


   titleDiv = house.find(

"div"

, attrs={

"class"

:

"text1"

})
   title = titleDiv.find(

"a"

).text
   

# 根據class="text2"獲取存儲樓盤價格的div


   priceDiv = house.find(

"div"

, attrs={

"class"

:

"text2"

})
   price = priceDiv.find(

"b"

).text
   print(title,

" "

, price)

輸入的結果盡然是, Why?

?D?eo£ì?í?    

48000

?a/?O
?aòêòY?·à?í?    

43057

?a/?O
?D1ú1é1è′′?íSOHO     ????′y?¨
D??÷ìá?×è?3?    

14000

?a/?O

3. 研究中文亂碼問題


中文亂碼也算是requests常見的一個問題,為什麼會這樣的呢,看他自己的文檔描述



Encodings


When you receive a response, Requests makes a guess at the encoding to use for decoding the response 


when you access the Response.text attribute. Requests will first check for an encoding in the HTTP 


header, and if none is present, will use chardet to attempt to guess the encoding.


 


The only time Requests will not do this is if no explicit charset is present in the HTTP headersand 


the Content-Type header contains text. In this situation, RFC 2616 specifies that the default charset 


must be ISO-8859-1. Requests follows the specification in this case. If you require a different encoding, 


you can manually set the Response.encoding property, or use the rawResponse.content.


其實重要的也就是如果沒有在requests裡面制定encoding的話,那麼其實默認採用的就用ISO-8859-1這個編碼去解碼response.content裡面的位元組數據。ISO-8859-1針對英文是沒有問題的,但是針對中文就不行了。


解決思路就是換encoding,有一個方案可以看到網頁的實際encoding,如下代碼:它的輸出是 GB2312

print(rep.apparent_encoding)

4.換編碼解決中文字元


經過上面的研究,我們修訂代碼對response設定encoding = "GB2312"

rep.encoding =

"GB2312"


運行後結果如下:



中金海棠灣     48000元/?O
華誼逸品瀾灣     43057元/?O
中國歸谷創客SOHO     價格待定
新西塘孔雀城     14000元/?O


發現代碼顯示的結果中㎡又亂碼了,不應該啊,這又是為什麼呢? 下面接著研究。。。


5. 研究解決特殊字元亂碼問題


引起亂碼的原因估計就是在字符集中找不到特定的字元,比如這個㎡。是不是GB2312這個字符集不夠全面呢?帶著這個疑問去查閱相關的資料關於中文的幾個編碼:




  • GB2312


GB 2312 或 GB 2312-80 是中國國家標準簡體中文字符集,全稱《信息交換用漢字編碼字符集·基本集》,又稱 GB 0,由中國國家標準總局發布,1981 年 5 月 1 日實施。GB 2312 編碼通行於中國大陸;新加坡等地也採用此編碼。中國大陸幾乎所有的中文系統和國際化的軟體都支持 GB 2312。GB 2312 標準共收錄 6763 個漢字,其中一級漢字 3755 個,二級漢字 3008 個;同時收錄了包括拉丁字母、希臘字母、日文平假名及片假名字母、俄語西里爾字母在內的 682 個字元。GB 2312 的出現,基本滿足了漢字的計算機處理需要,它所收錄的漢字已經覆蓋中國大陸99.75% 的使用頻率。

對於人名、古漢語等方面出現的罕用字,GB 2312 不能處理,這導致了後來 GBK 及 GB 18030 漢字字符集的出現。




  • GBK


GBK 即漢字內碼擴展規範,K 為漢語拼音 Kuo Zhan(擴展)中「擴」字的聲母。英文全稱 Chinese Internal Code Specification。GBK 共收入 21886 個漢字和圖形符號,包括:GB 2312 中的全部漢字、非漢字元號。BIG5 中的全部漢字。與 ISO 10646 相應的國家標準 GB 13000 中的其它 CJK 漢字,以上合計 20902 個漢字。其它漢字、部首、符號,共計 984 個。GBK 向下與 GB 2312 完全兼容,向上支持 ISO 10646 國際標準,在前者向後者過渡過程中起到的承上啟下的作用。GBK 採用雙位元組表示,總體編碼範圍為 8140-FEFE 之間,首位元組在 81-FE 之間,尾位元組在 40-FE 之間,剔除 XX7F 一條線




  • GB18030


GB 18030,全稱:國家標準 GB 18030-2005《信息技術中文編碼字符集》,是×××現時最新的內碼字集,是 GB 18030-2000《信息技術信息交換用漢字編碼字符集基本集的擴充》的修訂版。GB 18030 與 GB 2312-1980 和 GBK 兼容,共收錄漢字70244個。與 UTF-8 相同,採用多位元組編碼,每個字可以由 1 個、2 個或 4 個位元組組成。編碼空間龐大,最多可定義 161 萬個字元。支持中國國內少數民族的文字,不需要動用造字區。漢字收錄範圍包含繁體漢字以及日韓漢字


從上文中可以簡要的得出GB 2312 過時標準、GBK 微軟標準、GB 18030 國家標準,兼容性方面:GB 18030 > GBK > GB2312


所以我們決定採用 GB18030來解碼我們的數據,代碼改動如下:

rep.encoding =

"gb18030"


附上完整的代碼

from

bs4

import

BeautifulSoup

import

requests

rep = requests.get(

"http://sh.fang.com/"

)
rep.encoding =

"gb18030"


html = rep.text
soup = BeautifulSoup(html,

"html.parser"

)

#獲取頂層 新盤推薦 的整個div


div = soup.find(

"div"

,attrs={

"id"

:

"ti011"

})

#獲取四個樓盤的div,更具他們的class = "tenrtd"


for

house

in

div.find_all(

"div"

, attrs={

"class"

:

"tenrtd"

}):
   

# 根據class="text1"獲取存儲樓盤標題的div


   titleDiv = house.find(

"div"

, attrs={

"class"

:

"text1"

})
   title = titleDiv.find(

"a"

).text
   

# 根據class="text2"獲取存儲樓盤價格的div


   priceDiv = house.find(

"div"

, attrs={

"class"

:

"text2"

})
   price = priceDiv.find(

"b"

).text
   print(title,

" "

, price)

輸出結果:



中金海棠灣     48000元/㎡
華誼逸品瀾灣     43057元/㎡
中國歸谷創客SOHO     價格待定
新西塘孔雀城     14000元/㎡


總結


問題解決了,關鍵知識點總結:




  • 可以採用requests庫來獲取網頁html;



  • 採用Beautiful Soup基於html構建一個soup文檔,然後用find 或者 find_all方法查詢自己需要的html節點;



  • 根據目標網頁的內容來更改response.encoding從而解決亂碼問題。





  • 來自:

    唐元志



  • http://blog.51cto.com/yuanzhitang/2058281



  • Python開發整理髮布,轉載請聯繫作者獲得授權



【點擊成為程序員大咖】

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 Python開發 的精彩文章:

TAG:Python開發 |