1. 程式人生 > >python3 scrapy_redis 分散式爬取房天下存mongodb

python3 scrapy_redis 分散式爬取房天下存mongodb

(一)scrapy_redis 簡單介紹

scrapy_redis基於scrapy框架的基礎上集成了redis,通過了redis實現了去重,多臺伺服器進行分散式的爬取資料。

(二)scrapy_redis 簡單配置

(1)settings.py 檔案中加入兩行程式碼:

#啟用Redis排程儲存請求佇列
SCHEDULER = "scrapy_redis.scheduler.Scheduler"

#確保所有的爬蟲通過Redis去重
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"

image.png

(2)spider檔案中把scrapy.Spider改為RedisSpider; 加入redis_key

image.png

以上就是scrapy_redis在scrapy框架中的簡單配置,更多的配置內容,請檢視以往部落格介紹

(三)房天下爬蟲程式碼的編寫

(一)獲取的內容是優選房源

image.png

因為這個頁面是下滑重新整理的,並沒有點選下一頁的操作,而是動態JS進行載入的,我們可以使用審查元素中的網路,檢視介面請求資訊

image.png

其中的一個連結:

我們可以看到 page=3 只要我們操控這個變數就完全可以了。

但是:當我們開啟上面的連結的時候,出現一堆的亂碼:

image.png

(二)我們在parse()方法中使用decode 方法解碼一下,就可以顯示正常了。

    def parse(self,response)
:
print(response.body.decode('utf-8'))
敲黑板!!!

因為這裡用了分散式,我使用的方法是一臺專門爬url,就是列表頁的url,另外一臺專門進行列表頁url的解析工作。

基於現在的情況,我現在只有一臺電腦,所以我進行了兩個爬蟲進行執行,一個進行url的爬取,一個進行頁面的解析工作。

(1)url爬取:

image.png

(2)頁面解析:
image.png

(1)爬取url的spider程式碼:

# -*- coding: utf-8 -*-
# @Time    : 2018/4/30 14:14
# @Author  : 蛇崽
# @Email   : [email protected]
# @File : fangtianxia.py(房天下) import scrapy import redis from scrapy_redis.spiders import RedisSpider from zhilianspider.settings import REDIS_HOST,REDIS_PWD class FangtianxiaSpider(RedisSpider): name = 'fangtianxia' allowed_domains = ['m.fang.com'] """ 44684 p:16 index 3192 """ # start_urls = ['https://m.fang.com/zf/?purpose=%D7%A1%D5%AC&jhtype=zf&city=%B1%B1%BE%A9&renttype=cz&c=zf&a=ajaxGetList&city=bj&r=0.7782449595236586&page=1'] base_url = 'https://m.fang.com/zf/?purpose=%D7%A1%D5%AC&jhtype=zf&city=%B1%B1%BE%A9&renttype=cz&c=zf&a=ajaxGetList&city=bj&r=0.7782449595236586&page=' # 獲取到redis pool = redis.ConnectionPool(host=REDIS_HOST, port=6379, db=0, password=REDIS_PWD) redis = redis.StrictRedis(connection_pool=pool) for index in range(1,3192): star_url = base_url+str(index) redis.lpush('fangtianxia:start_urls',star_url) redis_key = 'fangtianxia:start_urls' def parse(self,response): #print(response.body.decode('utf-8')) url = response.xpath("//*[@class='tongjihref']/@href").extract() for v_url in url: print(v_url) n_v_url = 'https:'+v_url print('nvurl ',n_v_url) self.redis.rpush('fangtianxia:house_urls',n_v_url)

(2)解析頁面的程式碼

# -*- coding: utf-8 -*-
# @Time    : 2018/4/30 14:14
# @Author  : 蛇崽
# @Email   : 643435675@QQ.com
# @File    : fangtianxia.py(房天下)
import scrapy
import redis
from scrapy_redis.spiders import RedisSpider

from zhilianspider.items import FanItem
from zhilianspider.settings import REDIS_HOST,REDIS_PWD


class FangtianxiaSpider(RedisSpider):

    name = 'fangtianxia_down'

    allowed_domains = ['m.fang.com']

    redis_key = 'fangtianxia:house_urls'

    # start_urls = ['https://m.fang.com/zf/bj/JHAGT_404572021_11444434x1010063105_163711602.html']

    def parse(self,response):
        item = FanItem()
        item["title"] = response.xpath('//*[@class="xqCaption mb8"]/h1/text()')[0].extract()
        item["area"] = response.xpath('//*[@class="xqCaption mb8"]/p/a[2]/text()')[0].extract()
        item["location"] = response.xpath('//*[@class="xqCaption mb8"]/p/a[3]/text()')[0].extract()
        item["housing_estate"] = response.xpath('//*[@class="xqCaption mb8"]/p/a[1]/text()')[0].extract()
        item["rent"] = response.xpath('//*[@class="f18 red-df"]/text()')[0].extract()
        item["rent_type"] = response.xpath('//*[@class="f12 gray-8"]/text()')[0].extract()
        item["floor_area"] = response.xpath('//*[@class="flextable"]/li[3]/p/text()')[0].extract()
        item["house_type"] = response.xpath('//*[@class="flextable"]/li[2]/p/text()')[0].extract()
        item["floor"] = response.xpath('//*[@class="flextable"]/li[4]/p/text()')[0].extract()
        item["orientations"] = response.xpath('//*[@class="flextable"]/li[5]/p/text()')[0].extract()
        item["decoration"] = response.xpath('//*[@class="flextable"]/li[6]/p/text()')[0].extract()
        item["house_info"] = response.xpath('//*[@class="xqIntro"]/p/text()')[0].extract()
        item["house_tags"] = ",".join(response.xpath('//*[@class="stag"]/span/text()').extract())
        yield item

(三)items.py程式碼:

class FanItem(scrapy.Item):
    # 標題
    title = scrapy.Field()
    # 區(朝陽)
    area = scrapy.Field()
    # 區域 (勁鬆)
    location = scrapy.Field()
    # 小區 (勁鬆五區)
    housing_estate = scrapy.Field()
    # 租金
    rent = scrapy.Field()
    # 建築面積
    floor_area = scrapy.Field()
    # 戶型
    house_type = scrapy.Field()
    # 樓層
    floor = scrapy.Field()
    # 朝向
    orientations = scrapy.Field()
    # 裝修
    decoration = scrapy.Field()
    # 房源描述
    house_info = scrapy.Field()
    # 標籤
    house_tags = scrapy.Field()
    # 租房型別(押一付三etc)
    rent_type = scrapy.Field()

(四)資料展示

現在的資料還沒有爬完,到現在redis的詳情url已經是60萬的資料了,怕要是撐爆了。
image.png

mongo資料庫裡面的資料是3萬左右:

image.png

總結一下:scrapy_redis 中的url爬取,這是用這個框架以來第一次用的這種方式,或許這種方式更支援分散式操作,一個爬url,多個通過url進行頁面的解析操作,比較解析頁面是比較費時的。

其餘程式碼都是跟前面爬取智聯招聘的程式碼都差不多一樣的,這裡就不貼出來了,完整的程式碼我會上傳上來。