CrawlSpider爬取鍊家租房網
- 1. 簡單說一說自己爬取後的想法
- 2. crawlspider爬蟲思路和簡單網頁分析
-
- 2.1 目标網頁
- 2.2 網頁分析和爬取的思路
- 3. 主要的爬蟲代碼
- 4. 當請求過多防止ip被ban的方法
-
- 4.1 設定 ROBOTSTXT_OBEY
- 4.2 設定更換請求頭user-agent
- 4.3 設定自己的ip池
- 4.4 設定scrapy架構本身的爬取速度
- 5. 爬取資料庫結果
- 6. 總結
1. 簡單說一說自己爬取後的想法
爬取鍊家網的代碼,方法,可視化,成果展示在csdn上有很多,有很多都是一次性爬取1w+或者2w+的資料,但是其給出的代碼很少涉及反爬的,确實,爬取鍊家網的資料更換user-agent即可爬取,但是當你爬取的資料超過一定量的時候(自己在第一次實踐的時候僅僅隻更換了user-agent為反爬,也沒有設定大量的請求頭random進行更換,我不知道伺服器如何進行識别反爬,自己在第一次爬取的時候當爬取了1500條資料左右的時候,自己ip就被ban了,但剛剛再次進行爬取的時候,這次使用了random更換請求頭user-agent,沒有報錯的爬取了2539條資料,我也不知道為什麼,但是當你二次爬取的時候依然會出現人機驗證的頁面)
,後面傳回的網頁請求(鍊家網共100頁資料)都是失敗的,即當打開網頁連結的時候出現的頁面是人機驗證的頁面,這就是設定的反爬措施,已經讓伺服器識别出來,你的ip被ban的情況。我也是小白,希望大家有什麼好的反爬措施或者相關的博文鍊家可以發送給我,我也想學習學習…爬蟲真的是一個入門低,上限高的東西
2. crawlspider爬蟲思路和簡單網頁分析
2.1 目标網頁
#start_urls = ['https://xa.lianjia.com/zufang/']
# 或
start_urls = ['https://xa.lianjia.com/zufang/pg1/#contentList']
2.2 網頁分析和爬取的思路
以下就是鍊家網的網頁,其是使用get請求,url變換,點選下一頁來加載網頁的資訊,因為使用的是crawlspider進行爬取,不需要觀察url的變換規律,檢視下一頁的網頁連結在哪裡即可
可以看出下一頁的連結都封存在ul标簽當中,很容易構造請求的Rule
具體的請求分析這裡有寫到:
使用CrawlSpider半通用化、架構式、批量請求“鍊家網”西安100頁租房網頁(兩種方法實作rules的跟進和幾個xpath分享)
爬取的思路是通過點選每一頁當中的房源請求連結,進入具體的房源介紹頁面,對頁面中的自己想知道的房子資訊進行爬取(如下圖便是進入具體的房源頁面),網頁的源碼很容易進行分析,這裡便步進行具體的分析,建議使用Xpath進行爬取
3. 主要的爬蟲代碼
spider.py 中的代碼:
class LianjiaSpider(CrawlSpider):
name = 'lianjia'
allowed_domains = ['xa.lianjia.com']
#start_urls = ['https://xa.lianjia.com/zufang/']
# 或
start_urls = ['https://xa.lianjia.com/zufang/pg1/#contentList']
# # 設定爬取的速度
# custom_settings = {
# 'DOWNLOAD_DELAY':2
# }
rules = (
Rule(LinkExtractor(restrict_xpaths='//p[@class="content__list--item--title twoline"]//a'), callback='parse_item'),
#Rule(LinkExtractor(restrict_xpaths='//ul[@style="display:hidden"]//a'))
)
def parse_item(self, response):
item = HouseItem()
item['id'] = response.xpath('//i[@class="house_code"]/text()').extract()
item['time'] = ''.join(response.xpath('//div[@class="content__subtitle"]/text()').extract()).strip()
item['name'] = response.xpath('//p[@class="content__title"]/text()').extract_first()
item['price'] = ''.join(response.xpath('//div[@class="content__aside--title"]/span/text()').extract_first()) + ''.join(response.xpath('//div[@class="content__aside--title"]/text()').extract()).strip().split('\n')[0]
item['method'] = ''.join(response.xpath('//div[@class="content__aside--title"]/text()').extract()).strip().split('\n')
item['rentWay'] = ''.join(response.xpath('//ul[@class="content__aside__list"]//text()').extract()).strip().split('\n')[0]
item['size'] = ''.join(response.xpath('//ul[@class="content__aside__list"]//text()').extract()).strip().split('\n')[1]
item['floor'] = ''.join(response.xpath('//ul[@class="content__aside__list"]//text()').extract()).strip().split('\n')[2]
item['url'] = response.url
#item['domain_id'] = response.xpath('//input[@id="sid"]/@value').get()
#item['name'] = response.xpath('//div[@id="name"]').get()
#item['description'] = response.xpath('//div[@id="description"]').get()
return item
# i = {}
# return i
def parse_start_url(self, response):
for i in range(2,101):
url = 'https://xa.lianjia.com/zufang/pg' + str(i+1) + '/#contentList'
yield scrapy.Request(url)
item.py 中的代碼:
class HouseItem(Item):
# define the fields for your item here like:
# name = scrapy.Field()
id = Field()
time = Field()
price = Field()
rentWay = Field()
size = Field()
floor = Field()
url = Field()
name = Field()
method = Field()
pipeline.py 中關于資料清洗的代碼:
class TextPipeline(object):
def process_item(self, item, spider):
a = item.get('method')
if len(a) > 1:
item['method'] = a[1]
else:
item['method'] = ''
return item
4. 當請求過多防止ip被ban的方法
自己也是小白,以下的方法是自已人為比較有效的方法,有什麼不對的地方或者不足的或者更好的方法請大家評論或私信給出
4.1 設定 ROBOTSTXT_OBEY
這是最簡單的設定反爬的措施,這是scrapy架構中是否遵循robots協定的設定,在setting.py中進行設定,這因該是每一次使用爬蟲必設定的東西:
# Obey robots.txt rules
ROBOTSTXT_OBEY = False
4.2 設定更換請求頭user-agent
這是在向下載下傳器發送請求的時候,截獲請求,改變請求頭的做法,在middlewares.py中進行設定,高效的做法是設定大量的請求頭,使用random進行随機切換,代碼很簡單,但是原理得知道scrapy架構整體運作的原理:
Scrapy項目運作資料流總覽 AND 幾個重要的元件、中間件分析
設定完以下的代碼後,一定要在settings.py中進行相應的開啟
class RandomUserAgentMiddleware():
def __init__(self):
self.user_agenrs = [
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; AcooBrowser; .NET CLR 1.1.4322; .NET CLR 2.0.50727)",
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Acoo Browser; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.0.04506)",
"Mozilla/4.0 (compatible; MSIE 7.0; AOL 9.5; AOLBuild 4337.35; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)",
"Mozilla/5.0 (Windows; U; MSIE 9.0; Windows NT 9.0; en-US)",
"Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 2.0.50727; Media Center PC 6.0)",
"Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 1.0.3705; .NET CLR 1.1.4322)",
"Mozilla/4.0 (compatible; MSIE 7.0b; Windows NT 5.2; .NET CLR 1.1.4322; .NET CLR 2.0.50727; InfoPath.2; .NET CLR 3.0.04506.30)",
"Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN) AppleWebKit/523.15 (KHTML, like Gecko, Safari/419.3) Arora/0.3 (Change: 287 c9dfb30)",
"Mozilla/5.0 (X11; U; Linux; en-US) AppleWebKit/527+ (KHTML, like Gecko, Safari/419.3) Arora/0.6",
"Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.2pre) Gecko/20070215 K-Ninja/2.1.1",
"Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9) Gecko/20080705 Firefox/3.0 Kapiko/3.0",
"Mozilla/5.0 (X11; Linux i686; U;) Gecko/20070322 Kazehakase/0.4.5",
"Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.8) Gecko Fedora/1.9.0.8-1.fc10 Kazehakase/0.5.6",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) AppleWebKit/535.20 (KHTML, like Gecko) Chrome/19.0.1036.7 Safari/535.20",
"Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; fr) Presto/2.9.168 Version/11.52",
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36'
]
def process_request(self,request,spider):
request.headers['User-Agent'] = random.choice(self.user_agenrs)
4.3 設定自己的ip池
這是一個更加進階的反爬措施,用不同的ip進行請求,這個方法更加高效,但其代價也是很大,自己需要購買穩定的ip,因為我自己做了嘗試,自己寫代碼爬取不同的代理網站上免費的ip,其穩定性特别差,根本不可取,網上推薦的免費的ip代理是西刺代理,但最近它封了,網上也有很多爬取其ip的代碼,但我感覺不穩定,哎…
當擷取到有效的ip位址後,進行相應的設定即可使用,同樣也是在middlewares.py中進行設定:
class ProxyMiddleware(object):
def __init__(self):
self.proxy_list = [
'HTTPS://47.104.158.81:80',
'HTTP://47.91.137.211:3128',
'HTTP://123.57.77.187:8118',
'HTTP://112.245.17.202:8080',
'HTTPS://113.121.92.46:9999',
'HTTPS://123.57.61.38:8118',
'HTTP://61.163.32.88:3128',
'HTTP://103.43.17.220:8993',
'HTTPS://175.6.47.165:8080',
'HTTPS://101.200.127.149:3129',
'HTTP://47.114.142.53:80'
]
def process_request(self,request,spider):
ip = random.choice(self.proxy_list)
request.meta['proxy'] = ip
4.4 設定scrapy架構本身的爬取速度
我在查閱資料後知乎這個寫的在理:
爬取速度設定
故,在spider.py中添加如下代碼便可以設定整體架構爬取的速度:
# 設定爬取的速度,爬取一個item的時間
custom_settings = {
'DOWNLOAD_DELAY':2
}
這是最笨最簡單也是最有效的反爬措施,但不足的地方是設定了爬取速度後當爬取大量的資料是,雖然可以通順的爬取,但所耗費的時間是非常長的。自己在實踐後得出,這是設定每一個item的傳回時間,即爬取下載下傳存儲一個item的時間,以鍊家網資訊為例,每一頁網頁有33個租房資訊,100頁公有3300個租房資訊,每個租房資訊為一個item,那麼理論上爬取所有的房源資訊會花費6600秒,共1.8333小時,那麼當爬取大量的資料的時候那個時間…
5. 爬取資料庫結果
一共三頁,資料庫預設每頁最多1000條資料
6. 總結
以上就是自己感覺比叫實用的反爬方法,肯定知道的不多,希望看過的兄弟們可以指出不足的地方,直接評論或者私信給出更好的反爬方法,真心感謝