想作一個地圖熱力圖,發現安居客房產數據有我要的特性。emmm,那就嘗試一次好了~html
老規矩,從爬蟲,從拿到數據開始...數據庫
scrapy startproject anjuke
這命令會建一個叫anjuke的文件夾,裏面會有一些待你配置的文件瀏覽器
先進入建立的項目文件夾裏cookie
cd anjuke
scrapy genspider anju qd.anjuke.com
這命令會建一個叫anju.py的文件,它就是剛剛建立的spiderdom
這時的文件夾結構應該是這樣的:scrapy
item是保存爬取數據的容器,使用方法和字典相似~ide
將item.py修改以下:網站
import scrapy class AnjukeItem(scrapy.Item): # define the fields for your item here like: address = scrapy.Field() name = scrapy.Field() type_ = scrapy.Field() tags = scrapy.Field() price = scrapy.Field() area = scrapy.Field() city = scrapy.Field()
至於item爲何是這樣的能夠看看這張圖片:url
上圖就是下面代碼用xpath獲取divs的那部分,這跟網頁的結構有關~spa
瀏覽器直接按f12審查元素就是這個站的源碼了(有的網站有些內容由js加載時,其實這裏可能不是返回的源碼)。
上圖列出了下面xpath代碼的邏輯~~
# -*- coding: utf-8 -*- import scrapy from anjuke.items import AnjukeItem # 使用item class AnjuSpider(scrapy.Spider): name = 'anju' # spider的名稱,影響不大 allowed_domains = [] # 容許爬取的域,爲空則是容許當前spider爬取全部的域名 start_urls = ['https://cheng.fang.anjuke.com/', 'https://chang.fang.anjuke.com/', 'https://chi.fang.anjuke.com/', 'https://chu.fang.anjuke.com/', 'https://cy.fang.anjuke.com/', 'https://chao.fang.anjuke.com/', 'https://cx.fang.anjuke.com/', 'https://hf.fang.anjuke.com/', 'https://changd.fang.anjuke.com/', 'https://cg.fang.anjuke.com/', 'https://chongz.fang.anjuke.com/', 'https://chss.fang.anjuke.com/', 'https://ba.fang.anjuke.com/', ] def parse(self, response): divs = response.xpath('''//div[@class="key-list imglazyload"]/div''') # 使用xpath從response中獲取須要的html塊 city = response.xpath( '''//span[@class="city"]/text()''').extract_first() # 咱們匹配到的其實只有一個,獲取第一個就好了,這裏若是用.extract()其實會返回一個列表 print(divs) for div in divs: item = AnjukeItem() # 實例化item對象 item['city'] = city # 城市 item['address'] = div.xpath('.//span[@class="list-map"]/text()').extract_first() # 樓盤地址 item['name'] = div.xpath('.//span[@class="items-name"]/text()').extract_first() # 開發商名稱 try: item['type_'] = div.xpath('.//a[@class="huxing"]/span/text()').extract()[:-1] # 房子類型好比兩房一廳這樣子~ except: pass item['tags'] = div.xpath('.//span[@class="tag"]/text()').extract() # 網站給樓盤定的標籤~ price = div.xpath('.//p[contains(@class,"price")]//text()').extract() # 價格 item['price'] = price try: item['area'] = div.xpath('.//a[@class="huxing"]/span/text()').extract()[-1].replace('建築面積:', '') # 房子面積範圍~ except: pass yield item next_ = response.xpath('//a[@class="next-page next-link"]/@href').extract_first() # 獲取下一頁的連接 print('-----next') print(next_) yield response.follow(url=next_, callback=self.parse) # 將下一頁的連接加入爬取隊列~~
上面的start_urls的連接是另外爬的,連接這裏:安居客,所有連接爬下來了,這裏爲了篇幅就列出幾個就行了。
上面代碼item的結構:
由於網站這裏給的價格有最低價、總價、均價,我只想要均價,保留價格的類型後面用時分類方便~
import pymongo class TextPipeline(object): #這個自定義的類是打算用來處理item數據的,後來發現爬到的item數據好像還挺乾淨就沒有寫邏輯了~ def process_item(self, item, spider): print(item) return item class MongoPipeline(object): def __init__(self,mongo_uri,mongo_db): self.mongo_uri = mongo_uri self.mongo_db = mongo_db @classmethod def from_crawler(cls,crawler): #類方法,用於從settins.py中獲取在那邊設置的MONGO_URI和MONGO_DB return cls( mongo_uri = crawler.settings.get('MONGO_URI'), mongo_db = crawler.settings.get('MONGO_DB') ) def open_spider(self,spider): #當spider開啓時這個方法被調用,這裏用來鏈接數據庫 self.client = pymongo.MongoClient(self.mongo_uri) self.db = self.client[self.mongo_db] def process_item(self,item,spider): #實現了item數據插入到數據庫,自動建立與項目名同名,spider同名的表,數據都保存在裏面 name = item.__class__.__name__ self.db[name].insert(dict(item)) return item def close_spider(self,spider): #當spider關閉時這個方法被調用 self.client.close()
這些都在settings.py設置:
首先,站點對user-agent有檢查,發現是爬蟲頭直接跳轉到驗證碼頁面...
emmm,僞造瀏覽器請求頭就行了:
在settings.py加(記得import random):
USER_AGENT_LIST=[ #各瀏覽器的請求頭 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36' "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/4.0 (compatible; MSIE 7.0; Windows NT 5.1; 360SE)", "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/19.0.1055.1 Safari/535.24" ] USER_AGENT = random.choice(USER_AGENT_LIST) #隨機從上面列表中選取請求頭,僞造請求頭~
還有就是禁用cookie,網站會經過用戶的Cookie信息對用戶進行識別與分析,因此要防止目標網站識別咱們的會話信息:
COOKIES_ENABLED = False #關閉cookie
最後就是訪問頻率的控制,站點對一個ip的訪問頻率也有監測,一直很訪問快的話,也是會跳到人機驗證頁面~:
DOWNLOAD_DELAY = random.choice([1,2]) #訪問延時,隨機選1或2~
一、給出的房源少,房源最多的城市也就2000左右,我想這很大程度並不能表明各個城市的平均水平。。
二、爬到的數據也不必定對,可能房地產或網站這邊故意壓低一點房價,以消費者吸引目光~
三、其實最好的辦法是以公司的合做來取到數據,有這樣官方的數據就不用本身去爬了,並且也最準確、最真實啊(有大腿抱得話真的舒服)~
End