使用python3抓取鏈家二手房資料

秋水天發表於2018-04-18

有小夥伴說想拿鏈家二手房資訊做資料分析,讓幫忙抓點資料。並沒有搞過,網上搜了一些資料試了一下,感覺不難可以搞,下面小結一下。

工具

  • python3
  • python的三方庫:
    • BeautifulSoup(用於解析資料)
    • pandas(用於處理資料,儲存成Excel)
    • requests (用於傳送請求)

三方庫庫的安裝也比較簡單,直接使用 pip install 相應的庫名 即可:

pip install pandas
pip install requests
pip install beautifulsoup4
複製程式碼

思路

抓包基本的意思就是用程式碼模擬使用者的請求,然後解析相應的網頁內容,擇取出需要的資訊即可。 簡單看了一下鏈家的網頁結構,是比較整齊的。這種就是深圳二手房列表分頁的連結:

https://sz.lianjia.com/ershoufang/pg1
https://sz.lianjia.com/ershoufang/pg2
...
https://sz.lianjia.com/ershoufang/pg99
https://sz.lianjia.com/ershoufang/pg100
複製程式碼

可以請求一下這個連結,然後解析返回結果,可以抓取到每一個房子詳情頁面的連結。我這邊是通過正則匹配的方式解析的(詳情參考原始碼中catchHouseList函式)。解析的結果大概像這樣子:

https://sz.lianjia.com/ershoufang/105101151981.html
https://sz.lianjia.com/ershoufang/105101102328.html
https://sz.lianjia.com/ershoufang/105100779210.html
https://sz.lianjia.com/ershoufang/105101254525.html
https://sz.lianjia.com/ershoufang/105101201989.html
https://sz.lianjia.com/ershoufang/105101262457.html
複製程式碼

獲取詳情連結之後,再請求這個詳情連結,可以獲得到詳情資訊。把獲取到的詳情資訊通過 BeautifulSoup 解析,就能得到你要的資料。 最後,把這個資料通過 pandas 寫入到Excel中即可(參考appendToXlsx函式)。寫的時候是append的方式。

注意的是因為大部分網站對於連結訪問都有一些限制,諸如訪問太頻繁了,伺服器可能認為這個請求不正常,不會返回正確結果。因此每次請求一個網頁之後,會等一會兒再請求下一個網頁。不至於被伺服器拒絕。

# 我這裡設定為3秒
time.sleep(3)
複製程式碼

原始碼

下面是我的原始碼,應該安裝完相應的三方庫,在python環境執行下面的程式碼即可:


import requests
from bs4 import BeautifulSoup
import sys
import os
import time
import pandas as pd
import numpy as np
from parsel import Selector
import re



headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.106 BIDUBrowser/8.7 Safari/537.36'
    }


def catchHouseList(url):
    resp = requests.get(url, headers=headers, stream=True)
    if resp.status_code == 200:
        reg = re.compile('<li.*?class="clear">.*?<a.*?class="img.*?".*?href="(.*?)"')
        urls = re.findall(reg, resp.text)
        return urls
    return []

def catchHouseDetail(url):
    resp = requests.get(url, headers=headers)
    print(url)
    if resp.status_code == 200:
        info = {}
        soup = BeautifulSoup(resp.text, 'html.parser')
        info['標題'] = soup.select('.main')[0].text
        info['總價'] = soup.select('.total')[0].text
        info['總價單位'] = soup.select('.unit')[0].text
        info['每平方售價'] = soup.select('.unitPriceValue')[0].text
        # p = soup.select('.tax')
        # info['參考總價'] = soup.select('.tax')[0].text
        info['建造時間'] = soup.select('.subInfo')[2].text
        info['小區名稱'] = soup.select('.info')[0].text
        info['所在區域'] = soup.select('.info a')[0].text + ':' + soup.select('.info a')[1].text
        info['鏈家編號'] = str(url)[34:].rsplit('.html')[0]
        info['房屋戶型'] = str(soup.select('.content')[2].select('.label')[0].next_sibling)
        info['所在樓層'] = soup.select('.content')[2].select('.label')[1].next_sibling
        info['建築面積'] = soup.select('.content')[2].select('.label')[2].next_sibling
        info['戶型結構'] = soup.select('.content')[2].select('.label')[3].next_sibling
        info['套內面積'] = soup.select('.content')[2].select('.label')[4].next_sibling
        info['建築型別'] = soup.select('.content')[2].select('.label')[5].next_sibling
        info['房屋朝向'] = soup.select('.content')[2].select('.label')[6].next_sibling
        info['建築結構'] = soup.select('.content')[2].select('.label')[7].next_sibling
        info['裝修情況'] = soup.select('.content')[2].select('.label')[8].next_sibling
        info['梯戶比例'] = soup.select('.content')[2].select('.label')[9].next_sibling
        info['供暖方式'] = soup.select('.content')[2].select('.label')[10].next_sibling
        info['配備電梯'] = soup.select('.content')[2].select('.label')[11].next_sibling
      #  info['產權年限'] = str(soup.select('.content')[2].select('.label')[12].next_sibling)
        return info
    pass

def appendToXlsx(info):
    fileName = './鏈家二手房.xlsx'
    dfNew = pd.DataFrame([info])
    if(os.path.exists(fileName)):
        sheet = pd.read_excel(fileName)
        dfOld = pd.DataFrame(sheet)
        df = pd.concat([dfOld, dfNew])
        df.to_excel(fileName)
    else:
        dfNew.to_excel(fileName)


def catch():
    pages = ['https://sz.lianjia.com/ershoufang/pg{}/'.format(x) for x in range(1, 1001)]
    for page in pages:
        print(page)
        houseListURLs = catchHouseList(page)
        for houseDetailUrl in houseListURLs:
            try:
                info = catchHouseDetail(houseDetailUrl)
                appendToXlsx(info)
            except:
                pass
            time.sleep(3)

    pass

if __name__ == '__main__':
    catch()
    
複製程式碼

瞎墨跡

  • 雖然技術含量並不高,只是涉及到一些三方工具的使用。不過實踐的過程中還是遇到一些問題,諸如對pandas的使用,因為從未接觸過,就折騰了很久。大概很多看起來很簡單的東西,真正弄起來的時候,依舊有預料不到的問題。
  • 其次是抓包這件事,技術上覺得並不奇特(當然有些網站的抓包還是有難度的),但是小夥伴需要這個,也許一件事情並不僅僅從技術上考量其價值。

參考資料

谷歌百度一堆,無法判斷原創性,就懶得貼了。

相關文章