前言
因爲需要一些二手房數據,菜鳥開啓了爬蟲之路!不過需要注意的是,在爬取數據時,要遵守《中華人民共和國網絡安全法》以及《規範互聯網信息服務市場秩序若干規定》等相關法律規定(畢竟我們要做一個知法懂法的好公民,不能違法!)。
完整源代碼請點擊這裏是我!
瞭解爬蟲
首先需要了解一下爬蟲機制、python的基本語法、爬蟲框架(scrapy等)、爬蟲常用的一些庫、網頁解析工具(正則表達式、XPath等)、反爬蟲機制,進階後可能還要多線程、多進程爬取、以及一些特殊網頁的爬取(登錄問題、動態網頁等)等等… …作爲菜鳥的我,只爲了能夠快速獲取數據,有些內容也沒有深層次的理解,如果大家對於爬蟲非常感興趣,也可以專門去學一學相對應的內容。這裏簡單說一下我的理解:我所理解的爬蟲過程就是模擬瀏覽器發送請求,然後下載網頁代碼,只提取有用的信息,最後放入數據庫或者文件中。
爬蟲目錄結構
在安裝好爬蟲需要的一些庫(scrapy)等以後,就可以找爬蟲框架或者github上下載的爬蟲代碼,如下圖所示,是爬蟲目錄的結構,這裏包括了:
spiders文件夾 #放置關於爬蟲部分的內容
_init_.py #項目初始化文件
items.py #數據容器文件
middlewares.py #中間件
pipelines.py #管道文件
settings.py #項目的設置文件
scrapy.cfg #項目運行的配置文件
爬蟲主體代碼
首先先看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
運行結果如下如 :
完整源代碼請點擊這裏是我!
本人也是初學者,而且時間緊任務重,有些內容講述也許存在問題或者不準確的情況,歡迎大家批評指正,相互學習!