scrapy爬取豆瓣電影

scrapy爬取豆瓣電影,存儲在MongoDB

本節分享用的Scrapy爬取豆瓣電影Top250的實戰。

本節要實現的內容有:
- 爬取豆瓣電影Top250頁面的,全部字段
- 將抓取到的結果存儲到MongoDB。

實驗環境:
- PyCharm
- Python3.6
- Scrapy
- PyMongo
- MongoDB

創建項目

在你的工作目錄的文件夾下打開命令提示符窗口,輸入:

scrapy startproject dbmoive

創建爬蟲

cd dbmoive
scarpy genspider douban movie.douban.com/top250

如果正確創建,得到的目錄如下所示
目錄結構
- scrapy.cfg文件中主要包含的是項目的相關設置。
- dbmoive文件夾下是用於編寫爬蟲的目錄。
- items.py:定義我們所要爬取的信息的相關屬性。
- middlewares.py:爬蟲中間件,這裏可以用過自定義相關的方法,用來處理爬蟲的響應和請求。
- pipelines.py:當數據被爬蟲爬取下來後,它會被髮送到item pipelines中,每個item pipelines組件(有時稱爲“項目管道”)是一個實現簡單方法的Python類。他們收到一個項目並對其執行操作,還決定該項目是否應該繼續通過管道或被丟棄並且不再被處理。
- settings.py:項目的設置文件。
- douban.py: 項目中,爬蟲的主要邏輯代碼

禁止ROBOTSTXT_OBEY

接下來你需要打開settings.py文件,將ROBOTSTXT_OBEY修改爲False。

ROBOTSTXT_OBEY = False

它默認爲True,就是要遵守robots.txt 的規則,那麼 robots.txt 是個什麼東西呢?
通俗來說, robots.txt 是遵循 Robot 協議的一個文件,它保存在網站的服務器中,它的作用是,告訴搜索引擎爬蟲,本網站哪些目錄下的網頁 不希望 你進行爬取收錄。在Scrapy啓動後,會在第一時間訪問網站的 robots.txt 文件,然後決定該網站的爬取範圍。

當然,我們並不是在做搜索引擎,而且在某些情況下我們想要獲取的內容恰恰是被 robots.txt 所禁止訪問的。所以,某些時候,我們就要將此配置項設置爲 False ,拒絕遵守 Robot協議 !

嘗試最初的爬取

接下來我們什麼代碼也不修改,執行爬取,運行如下命令:

scrapy crawl douban

你會發現爬取結果會出現這樣的一個錯誤:

500 Internal Server Error

訪問知乎得到的狀態碼是500,這說明爬取並沒有成功,其實這是因爲我們沒有加入請求頭,知乎識別User-Agent發現不是瀏覽器,就返回錯誤的響應了。

所以接下來的一步我們需要加入請求headers信息,你可以在Request的參數里加,也可以在spider裏面的custom_settings裏面加,當然最簡單的方法莫過於在全局settings裏面加了。

我們打開settings.py文件,取消DEFAULT_REQUEST_HEADERS的註釋,加入如下的內容:
所以在這裏設置爲False。當然可能本次爬取不一定會被它限制,但是我們一般來說會首先選擇禁止它。

所以接下來的一步我們需要加入請求headers信息,你可以在Request的參數里加,也可以在spider裏面的custom_settings裏面加,當然最簡單的方法莫過於在全局settings裏面加了。

我們打開settings.py文件,取消DEFAULT_REQUEST_HEADERS的註釋,加入如下的內容:

DEFAULT_REQUEST_HEADERS = {
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
    'Accept-Language': 'en',
    'Accept-Encoding' :  'gzip, deflate, br',
    'Cache-Control' :  'max-age=0',
    'Connection' :  'keep-alive',
    'Host' :  'movie.douban.com',
    'Upgrade-Insecure-Requests' :  '1',
    'User-Agent' :  'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36',
}

這個是爲你的請求添加請求頭,如果你沒有設置headers的話,它就會使用這個請求頭請求,添加了User-Agent信息,所以這樣我們的爬蟲就可以僞裝瀏覽器了。

接下來重新運行爬蟲。

scrapy crawl zhihu

這時你就會發現得到的返回狀態碼就正常了。
解決了這個問題,我們接下來就可以分析頁面邏輯來正式實現爬蟲了。

頁面分析

對照圖

使用選取工具選取整個電影的信息,可以發現,所有的信息都是放在單獨的一個li標籤中的,而且在li下還有一個class爲item的div包裹着所有的信息。

定義item

根據前面的分析,我們需要抓取一共十個字段的信息,現在在items.py文件中定義item

class DoubanItem(Item):
    # 排名
    ranking = Field()
    # 篇名 
    title = Field()
    # 導演和演員
    director = Field()
    # 一句話描述 有的爲空
    desc = Field()
    # 評分
    rating_num = Field()
    # 評價人數
    people_count = Field()
    # 上映時間
    date = Field()
    # 上映國家
    country = Field()
    # 類別
    category = Field()

parse方法

寫完上面的代碼,其實只是抓取一頁的罷了,爲了抓取完整的top250榜單,我們需要讓爬蟲跳轉到下一頁再進行循環抓取,因爲每個頁面的結構是一樣的,所以不用擔心會抓取不到。

這裏不單獨講解XPath和CSS選擇器的使用方法,多看一點資料,自己總結一下。

不知道各位有沒有獲取XPath和CSS好用一點的方法,歡迎分享給我。

    def parse(self, response):
        item = DoubanItem()
        movies = response.xpath('//div[@class="item"]')
        for movie in movies:
            # 名次
            item['ranking'] = movie.xpath('div[@class="pic"]/em/text()').extract()[0]
            # 片名 提取多個片名
            titles = movie.xpath('div[@class="info"]/div[1]/a/span/text()').extract()
            item['title'] = titles
            # 獲取導演信息和演員信息
            info_director = movie.xpath('div[2]/div[2]/p[1]/text()[1]').extract()[0].replace(" ", "").replace("\n", "")
            item['director'] = info_director
            # 上映日期
            date = movie.xpath('div[2]/div[2]/p[1]/text()[2]').extract()[0].replace(" ", "").replace("\n", "").split("/")[0]
            # 製片國家
            country = movie.xpath('div[2]/div[2]/p[1]/text()[2]').extract()[0].replace(" ", "").replace("\n", "").split("/")[1]
            # 影片類型
            category = movie.xpath('div[2]/div[2]/p[1]/text()[2]').extract()[0].replace(" ", "").replace("\n", "").split("/")[2]
            item['date'] = date
            item['country'] = country
            item['category'] = category
            desc = movie.xpath('div[@class="info"]/div[@class="bd"]/p[@class="quote"]/span/text()').extract()
            if len(desc) != 0:  # 判斷info的值是否爲空,不進行這一步有的電影信息並沒有會報錯或數據不全
                item['desc'] = desc
            else:
                item['desc'] = ' '

            # item['desc'] = movie.xpath('div[@class="info"]/div[@class="bd"]/p[@class="quote"]/span[@class="inq"]/text()').extract()[0]
            item['rating_num'] = movie.xpath('div[@class="info"]/div[@class="bd"]/div[@class="star"]/span[@class="rating_num"]/text()').extract()[0]
            item['people_count'] = movie.xpath('div[@class="info"]/div[@class="bd"]/div[@class="star"]/span[4]/text()').extract()[0]
            yield item
# 獲取下一頁
        next_url = response.xpath('//span[@class="next"]/a/@href').extract()
        if next_url:
            next_url = 'https://movie.douban.com/top250' + next_url[0]
            yield Request(next_url, callback=self.parse, dont_filter=True)

那麼到這裏,代碼就寫完了。
然後我們來運行一下這個爬蟲,scrapy框架是通過命令來啓動爬蟲的,
在項目根目錄下打開命令提示符,輸入:

scrapy crawl douban

如果沒有出錯,你會在終端看到一行行滾動的信息。

存儲在Mongo

從官方文檔中拷貝如下代碼到pipeline.py中,只需要修改collection_name,其餘基本不用修改。在存儲MongoDB之前,你需要將正確安裝MongoDB,並且啓動MongoDB

class MongoPipeline(object):

    collection_name = 'douban'

    def __init__(self, mongo_uri, mongo_db):
        self.mongo_uri = mongo_uri
        self.mongo_db = mongo_db

    @classmethod
    def from_crawler(cls, crawler):
        return cls(
            mongo_uri=crawler.settings.get('MONGO_URI'),
            mongo_db=crawler.settings.get('MONGO_DATABASE')
        )

    def open_spider(self, spider):
        self.client = pymongo.MongoClient(self.mongo_uri)
        self.db = self.client[self.mongo_db]

    def close_spider(self, spider):
        self.client.close()

    def process_item(self, item, spider):
        self.db[self.collection_name].insert_one(dict(item))
        return item

另外記得開啓一下Item Pileline。setting.py

ITEM_PIPELINES = {
    'dbmovie.pipelines.MongoPipeline': 400,
}

實驗結果

結果
MongoDB

項目的完整代碼,可以看這裏scrapy爬取豆瓣電影Top250,存儲在MongoDB中

如果不想存儲在MongoDB中,可以使用scrapy支出的命令導出其他格式的文件

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