菜鳥爬蟲——獲取安居客二手房信息

前言

因爲需要一些二手房數據,菜鳥開啓了爬蟲之路!不過需要注意的是,在爬取數據時,要遵守《中華人民共和國網絡安全法》以及《規範互聯網信息服務市場秩序若干規定》等相關法律規定(畢竟我們要做一個知法懂法的好公民,不能違法!)。

完整源代碼請點擊這裏是我

瞭解爬蟲

首先需要了解一下爬蟲機制、python的基本語法、爬蟲框架(scrapy等)、爬蟲常用的一些庫、網頁解析工具(正則表達式、XPath等)、反爬蟲機制,進階後可能還要多線程、多進程爬取、以及一些特殊網頁的爬取(登錄問題、動態網頁等)等等… …作爲菜鳥的我,只爲了能夠快速獲取數據,有些內容也沒有深層次的理解,如果大家對於爬蟲非常感興趣,也可以專門去學一學相對應的內容。這裏簡單說一下我的理解:我所理解的爬蟲過程就是模擬瀏覽器發送請求,然後下載網頁代碼,只提取有用的信息,最後放入數據庫或者文件中

爬蟲目錄結構

在安裝好爬蟲需要的一些庫(scrapy)等以後,就可以找爬蟲框架或者github上下載的爬蟲代碼,如下圖所示,是爬蟲目錄的結構,這裏包括了:
spiders文件夾   #放置關於爬蟲部分的內容
_init_.py      #項目初始化文件
items.py      #數據容器文件
middlewares.py  #中間件
pipelines.py     #管道文件
settings.py    #項目的設置文件
scrapy.cfg     #項目運行的配置文件
Scrapy爬蟲文件結構

爬蟲主體代碼

首先先看spiders文件夾裏的ershoufang.py文件 ,這裏的邏輯是這樣的,以我爬取的安居客長春二手房爲例:
——>先點進安居客首頁
——>點擊二手房、房源

——>進入了二手房頁面點擊南關(因爲我是需要分區的房屋信息,所以我是點進去每個區來爬取的),這裏需要注意上方的網址,這也是我們最開始的初始網址,簡單觀察可以發現後面的數字是從p1-50的,代表着頁數,nanguan代表着這個

——>接下來網頁向下翻就是每個我們需要爬取的鏈接入口
——>點進去就是每一個房源信息了。

知道了這個邏輯,代碼就好理解了,我們上代碼!!!

class ershoufangSpider(scrapy.Spider):
    name = "ershoufang"
    allowed_domains = ['anjuke.com']
    # 生成起始網址
    start_urls = []
    for i in range(1,51):
        start_urls.append('https://heb.anjuke.com/sale/hulan/p%d/#filtersort'%i)

    # 採集每個房屋網址鏈接
    def parse(self,response):
        # item = ErshoufangItem()
        selector = Selector(response)
        #url = Selector(respone)
        urls =selector.xpath(".//ul[@class='houselist-mod houselist-mod-new']/li")
        for url in urls:
            detail_url = url.xpath(".//div[@class='house-title']/a/@href").extract()[0]
            # item["url"] = detail_url
            yield scrapy.Request(detail_url,callback = self.parse_item)
            # yield item

    # 採集每個鏈接裏面的房屋信息
    def parse_item(self,response):
        item = ErshoufangItem()

        houses = response.xpath(".//div[@class='wrapper-lf']")
        # for house in houses:
        # houseLoc 房屋位置,houseInfo 房屋具體信息(幾室幾廳等),Community 社區信息(綠化率等)
        # propertyCosts 物業費,totalPrice 房屋總價格
        if houses:
            item['houseLoc'] = houses.xpath(".//p[@class='loc-text']/a/text()").extract(),
            # item['houseEncode'] = house.xpath(".//h4/span[@class='house-encode']/text()").extract()
            item['houseInfo'] = houses.xpath(".//div[@class='houseInfo-content']/text()").extract()
            item['Community'] = houses.xpath(".//div[@class='commap-info-intro']/p/text()").extract()
            item['propertyCosts'] = houses.xpath(".//div[@class='commap-info-intro no-border-rg']/p/text()").extract()
            item['totalPrice'] = houses.xpath(".//span[@class='light info-tag']/em/text()").extract()

這裏應用了XPath來採取信息(應用re正則會是一種更好的選擇,但是本人比較菜,在用爬蟲時覺得XPath很好理解)。我們來說一下XPath,這裏簡單舉一個例子,以房屋信息裏面的housuInfo爲例,對應如下圖部分。先將鼠標放在房屋信息附近,點擊右鍵,在點擊檢查,找到網頁源碼中對應要採集的信息部分(紅色圈中的內容)填進XPath裏,具體也可以再詳細瞭解。


還有一個比較難的問題,就是歷史價格的爬取,歷史價格的數據不在網頁源代碼中,而是通過ajax加載的,按下圖可以找到歷史價格存儲的網址,這裏也需要解析網址(比如長春,網址中就是cc,後面都是一樣的,直到commid=後面的數字是不一樣的)。我們先提取後面的數字,然後再輸入一個headers來模擬網址請求,防止被識別出來,然後獲取歷史數據。

# 採集房屋歷史單價
house_comid = response.xpath('/html').re(r'comid=.*?&')
if house_comid:
    comid = house_comid[0].split('=')[-1][:-1]
    house_price_url = 'https://cc.anjuke.com/v3/ajax/prop/pricetrend/?commid=' + comid
    # 這裏cc對應的是城市,記得要與起始網址的城市保持一致

    headers = {
            'accept': 'application/json, text/javascript, */*; q=0.01',
            'accept-encoding': 'gzip, deflate, br',
            'accept-language': 'zh-CN,zh;q=0.9',
            'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36',
            "x-requested-with": 'XMLHttpRequest'
        }
    response = requests.get(house_price_url, headers=headers)
    item['houseHistoryPrice'] = response.json().get('community')

items.py

這個文件代碼如下:

class ErshoufangItem(scrapy.Item):
    # define the fields for your item here like:
    houseLoc = scrapy.Field()
    # houseEncode = scrapy.Field()
    houseInfo = scrapy.Field()
    propertyCosts = scrapy.Field()
    Community = scrapy.Field()
    totalPrice = scrapy.Field()
    houseHistoryPrice = scrapy.Field()
    # url = scrapy.Field()
    pass

可以看到我們在爬蟲中應用到了哪些item,這裏就定義哪些

反反爬蟲策略

簡單說一下我用的反反爬蟲策略:
1. 比較簡單的是添加隨機的user-agent頭(網絡上也有很多)

def process_request(self, request, spider):
    ua = random.choice(self.user_agent_list)
    if ua:
        # print ua, '-----------------yyyyyyyyyyyyyyyyyyyyyyyyy'
        request.headers.setdefault('User-Agent', ua)

        # the default user_agent_list composes chrome,I E,firefox,Mozilla,opera,netscape

# for more user agent strings,you can find it in http://www.useragentstring.com/pages/useragentstring.php

user_agent_list = [ \
    'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50', \
    'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50', \
    'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0;', 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)', \
    'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)', 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)', \
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:2.0.1) Gecko/20100101 Firefox/4.0.1', \
    'Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1', \
    'Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; en) Presto/2.8.131 Version/11.11', \
    'Opera/9.80 (Windows NT 6.1; U; en) Presto/2.8.131 Version/11.11', \
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_0) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11', \
    'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Maxthon 2.0)', 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; TencentTraveler 4.0)', \
    'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)', \
    'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; The World)', \
    'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; SE 2.X MetaSr 1.0; SE 2.X MetaSr 1.0; .NET CLR 2.0.50727; SE 2.X MetaSr 1.0)', \
    'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; 360SE)', \
    'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Avant Browser)', \
    'Mozilla/5.0 (hp-tablet; Linux; hpwOS/3.0.0; U; en-US) AppleWebKit/534.6 (KHTML, like Gecko) wOSBrowser/233.70 Safari/534.6 TouchPad/1.0', \
    "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1", \
    "Mozilla/5.0 (X11; CrOS i686 2268.111.0) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.57 Safari/536.11", \
    "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1092.0 Safari/536.6", \
    "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1090.0 Safari/536.6", \
    "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/19.77.34.5 Safari/537.1", \
    "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.9 Safari/536.5", \
    "Mozilla/5.0 (Windows NT 6.0) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.36 Safari/536.5", \
    "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3", \
    "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3", \
    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_0) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3", \
    "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1062.0 Safari/536.3", \
    "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1062.0 Safari/536.3", \
    "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3", \
    "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3", \
    "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3", \
    "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.0 Safari/536.3", \
    "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.24 (KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24", \
    "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/535.24 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/535.24", \
    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36"
]

2. 設置延遲時間,也就是別那麼快獲取信息

num=[55,60,50,48]
DOWNLOAD_DELAY = random.choice(num)

注意:安居客的反爬蟲太厲害了,如果在沒有代理Ip的情況下,建議不要把延遲速度調的太快,太快會封ip,或者出新驗證的頻率過高,影響爬蟲。

3. 變換ip(可以找一些ip代理來變換)

# """ 阿布雲代理配置"""
proxy_server = "http://http-cla.abuyun.com:9030"
proxy_user = "..."
proxy_pass = "..."
proxy_auth = "Basic " + base64.urlsafe_b64encode(bytes((proxy_user + ":" + proxy_pass), "ascii")).decode("utf8")

""" 啓用限速設置 """
# 如果沒有設置延遲,也可以這裏設置
AUTOTHROTTLE_ENABLED = True
AUTOTHROTTLE_START_DELAY = 0.5  # 初始下載延遲
DOWNLOAD_DELAY = 0.2  # 每次請求間隔時間

class ABYProxyMiddleware(object):
    """ 阿布雲代理中間件 """

    def process_request(self, request, spider):
        request.meta["proxy"] = proxy_server
        request.headers["Proxy-Authorization"] = proxy_auth

我用的是阿布雲代理經典版,可以買按小時計算的,1元/時,我爬的數據不多,按小時來買就足夠了,不是廣告!!!!
如果需要可以看看別的代理~

運行爬蟲

執行指令:

scrapy crawl ershoufang -o file_name.csv

運行結果如下如 :

完整源代碼請點擊這裏是我
本人也是初學者,而且時間緊任務重,有些內容講述也許存在問題或者不準確的情況,歡迎大家批評指正,相互學習!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章