scrapy爬取豆瓣電影數(shù)據(jù)的方法-創(chuàng)新互聯(lián)

創(chuàng)新互聯(lián)www.cdcxhl.cn八線動(dòng)態(tài)BGP香港云服務(wù)器提供商,新人活動(dòng)買(mǎi)多久送多久,劃算不套路!

創(chuàng)新互聯(lián)建站主要從事成都做網(wǎng)站、成都網(wǎng)站設(shè)計(jì)、網(wǎng)頁(yè)設(shè)計(jì)、企業(yè)做網(wǎng)站、公司建網(wǎng)站等業(yè)務(wù)。立足成都服務(wù)上杭,10多年網(wǎng)站建設(shè)經(jīng)驗(yàn),價(jià)格優(yōu)惠、服務(wù)專業(yè),歡迎來(lái)電咨詢建站服務(wù):028-86922220

小編給大家分享一下scrapy爬取豆瓣電影數(shù)據(jù)的方法,希望大家閱讀完這篇文章后大所收獲,下面讓我們一起去探討方法吧!

1.建立項(xiàng)目

執(zhí)行如下命令建立scrapy爬蟲(chóng)項(xiàng)目

scrapy startproject spider_douban

命令執(zhí)行完成后,建立了spider_douban文件夾,目錄結(jié)構(gòu)如下:

.
├── scrapy.cfg
└── spider_douban
   ├── __init__.py
   ├── items.py
   ├── middlewares.py
   ├── pipelines.py
   ├── settings.py
   └── spiders
       ├── douban_spider.py
       └── __init__.py

2.建立爬蟲(chóng)數(shù)據(jù)模型

打開(kāi) ./spider_douban/items.py 文件,編輯內(nèi)容如下:

import scrapy

class DoubanMovieItem(scrapy.Item):
    # 排名
    ranking = scrapy.Field()
    # 電影名稱
    movie_name = scrapy.Field()
    # 評(píng)分
    score = scrapy.Field()
    # 評(píng)論人數(shù)
    score_num = scrapy.Field()

3.新建爬蟲(chóng)文件

新建 ./spiders/douban_spider.py 文件,編輯內(nèi)容如下:

from scrapy import Request
from scrapy.spiders import Spider
from spider_douban.items import DoubanMovieItem
class DoubanMovieTop250Spider(Spider):
    name = 'douban_movie_top250'
    start_urls = {
        'https://movie.douban.com/top250'
        }
    '''
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36',
    }
    def start_requests(self):
        url = 'https://movie.douban.com/top250'
        yield Request(url, headers=self.headers)
    '''
    def parse(self, response):
        item = DoubanMovieItem()
        movies = response.xpath('//ol[@class="grid_view"]/li')
        print(movies)
        print('=============================================')
        for movie in movies:
            item['ranking'] = movie.xpath(
                './/div[@class="pic"]/em/text()').extract()[0]
            item['movie_name'] = movie.xpath(
                './/div[@class="hd"]/a/span[1]/text()').extract()[0]
            item['score'] = movie.xpath(
                './/div[@class="star"]/span[@class="rating_num"]/text()'
            ).extract()[0]
            item['score_num'] = movie.xpath(
                './/div[@class="star"]/span/text()').re(r'(\d+)人評(píng)價(jià)')[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)

爬蟲(chóng)文件各部分功能記錄

douban_spider.py文件主要有幾部分構(gòu)成。

導(dǎo)入模塊

from scrapy import Request
from scrapy.spiders import Spider
from spider_douban.items import DoubanMovieItem

Request類用于請(qǐng)求要爬取的頁(yè)面數(shù)據(jù)
Spider類是爬蟲(chóng)的基類
DoubanMovieItem是我們第一步建立的爬取數(shù)據(jù)模型

初始設(shè)置

基于spider類定義的爬蟲(chóng)類DoubanMovieTop250Spider中,首先定義爬蟲(chóng)的基本信息:

name:在項(xiàng)目中爬蟲(chóng)的名稱,可以在項(xiàng)目目錄中執(zhí)行scrapy list獲取已經(jīng)定義的爬蟲(chóng)列表
start_urls:是爬取的第一個(gè)頁(yè)面地址
headers:是向web服務(wù)器發(fā)送頁(yè)面請(qǐng)求的時(shí)候附加的user-agent消息,告訴web服務(wù)器是什么類型的瀏覽器或設(shè)備在請(qǐng)求頁(yè)面,對(duì)于不具備簡(jiǎn)單反爬機(jī)制的網(wǎng)站,headers部分可以省略。

為了迷惑web服務(wù)器,一般會(huì)在爬蟲(chóng)發(fā)送web請(qǐng)求的時(shí)候定義user-agent信息,這里有兩種寫(xiě)法。

  • header的第一種定義:    

headers = {
  'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36',
}
   def start_requests(self):
       url = 'https://movie.douban.com/top250'
       yield Request(url, headers=self.headers)

可以看到,這種寫(xiě)法中,start_urls定義沒(méi)有了,轉(zhuǎn)而定義了start_requests函數(shù),開(kāi)始的url寫(xiě)到了函數(shù)里。同時(shí),定義了headers字典,在發(fā)送Request請(qǐng)求的時(shí)候,將headers字典一并發(fā)送。這種寫(xiě)法簡(jiǎn)單直觀,缺點(diǎn)是在一個(gè)爬蟲(chóng)項(xiàng)目執(zhí)行期間,所有請(qǐng)求都是一個(gè)User-Agent屬性。

  • header的第二種定義:  

start_urls = {
       'https://movie.douban.com/top250'
    }

簡(jiǎn)單、直接的定義start_urls屬性,而Request中的header屬性通過(guò)其他方法另外定義,容后再說(shuō)。

parse處理函數(shù)

逐句分解說(shuō)明

1.基于我們定義的DoubanMovieItem類創(chuàng)建item實(shí)例

item = DoubanMovieItem()

2.解析頁(yè)面 - 獲取內(nèi)容框架

scrapy爬取豆瓣電影數(shù)據(jù)的方法

scrapy爬取豆瓣電影數(shù)據(jù)的方法

通過(guò)分析頁(yè)面源碼,我們能夠看到,頁(yè)面中的電影信息是保存在了<ol>標(biāo)簽中,這個(gè)<ol>標(biāo)簽有一個(gè)獨(dú)特的樣式表grid_view,而每一個(gè)單獨(dú)的電影信息保存在了<li>標(biāo)簽中,下面代碼獲取class屬性為grid_view的<ol>標(biāo)簽下的所有<li>標(biāo)簽內(nèi)容。

movies = response.xpath('//ol[@class="grid_view"]/li')

3.解析頁(yè)面 - 獲取分項(xiàng)

在每一個(gè)<li>標(biāo)簽中,還有內(nèi)部結(jié)構(gòu),通過(guò)xpath()解析,將每一項(xiàng)內(nèi)容解析出來(lái),賦值給item實(shí)例中的各個(gè)字段。通過(guò)查看movie.douban.com/top250頁(yè)面的源碼可以很容易找到這個(gè)標(biāo)簽定義的內(nèi)容。如果我們通過(guò)type()函數(shù)查看movies的變量類型,可以發(fā)現(xiàn)他的類型是<class 'scrapy.selector.unified.SelectorList'>。<ol>標(biāo)簽中的每一個(gè)<li>標(biāo)簽都是這個(gè)列表中的一項(xiàng),那么就可以對(duì)movies做迭代。

首先看看<li>標(biāo)簽中的頁(yè)面結(jié)構(gòu):

scrapy爬取豆瓣電影數(shù)據(jù)的方法

可以看到要提取數(shù)據(jù)的各部分所在標(biāo)簽位置:

排名:class屬性為pic的<div>標(biāo)簽下,,<em>標(biāo)簽中...
電影名:class屬性為hd的<div>標(biāo)簽下,<a>標(biāo)簽中的第一個(gè)<span>標(biāo)簽...
評(píng)分:class屬性為star的<div>標(biāo)簽下,class屬性為rating_num的<span>標(biāo)簽中...
評(píng)論人數(shù):class屬性為star的<div>標(biāo)簽下,<span>標(biāo)簽中。由于使用了re正則表達(dá)式,所以沒(méi)有特別指定是哪一個(gè)<span>標(biāo)簽。

回到代碼部分,對(duì)之前定義的movies做迭代,逐項(xiàng)獲取要抓取的數(shù)據(jù)。

for movie in movies:
    item['ranking'] = movie.xpath('.//div[@class="pic"]/em/text()').extract()[0]
    item['movie_name'] = movie.xpath('.//div[@class="hd"]/a/span[1]/text()').extract()[0]
    item['score'] = movie.xpath('.//div[@class="star"]/span[@class="rating_num"]/text()').extract()[0]
    item['score_num'] = movie.xpath('.//div[@class="star"]/span/text()').re(r '(\d+)人評(píng)價(jià)')[0]
yield item

4.Url跳轉(zhuǎn)(翻頁(yè))

如果到此為止,我們可以將https://movie.douban.com/top250頁(yè)面中的第一頁(yè)內(nèi)容爬取到,但只有25項(xiàng)記錄,要爬取全部的250條記錄,就要執(zhí)行下面代碼:

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)

首先通過(guò)xpath解析了頁(yè)面中后頁(yè)的鏈接,并賦值給next_url變量,如果我們當(dāng)前在第一頁(yè),那么解析后頁(yè)的鏈接就是?start=25&filter=。將解析的后頁(yè)鏈接與完整url連接形成完整的地址,再次執(zhí)行Request(),就實(shí)現(xiàn)了對(duì)全部250條記錄的爬取。注意:通過(guò)xpath解析出的結(jié)果是列表,所以在引用的時(shí)候?qū)懗蒼ext_url[0]。

4.處理隨機(jī)Head屬性(隨機(jī)User-Agent)

實(shí)現(xiàn)隨機(jī)的head屬性發(fā)送。主要改兩個(gè)文件:

settings.py

USER_AGENT_LIST = [
    'zspider/0.9-dev http://feedback.redkolibri.com/',
    'Xaldon_WebSpider/2.0.b1',
    'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) Speedy Spider (http://www.entireweb.com/about/search_tech/speedy_spider/)',
    'Mozilla/5.0 (compatible; Speedy Spider; http://www.entireweb.com/about/search_tech/speedy_spider/)',
    'Speedy Spider (Entireweb; Beta/1.3; http://www.entireweb.com/about/search_tech/speedyspider/)',
    'Speedy Spider (Entireweb; Beta/1.2; http://www.entireweb.com/about/search_tech/speedyspider/)',
    'Speedy Spider (Entireweb; Beta/1.1; http://www.entireweb.com/about/search_tech/speedyspider/)',
    'Speedy Spider (Entireweb; Beta/1.0; http://www.entireweb.com/about/search_tech/speedyspider/)',
    'Speedy Spider (Beta/1.0; www.entireweb.com)',
    'Speedy Spider (http://www.entireweb.com/about/search_tech/speedy_spider/)',
    'Speedy Spider (http://www.entireweb.com/about/search_tech/speedyspider/)',
    'Speedy Spider (http://www.entireweb.com)',
    'Sosospider+(+http://help.soso.com/webspider.htm)',
    'sogou spider',
    'Nusearch Spider (www.nusearch.com)',
    'nuSearch Spider (compatible; MSIE 4.01; Windows NT)',
    'lmspider (lmspider@scansoft.com)',
    'lmspider lmspider@scansoft.com',
    'ldspider (http://code.google.com/p/ldspider/wiki/Robots)',
    'iaskspider/2.0(+http://iask.com/help/help_index.html)',
    'iaskspider',
    'hl_ftien_spider_v1.1',
    'hl_ftien_spider',
    'FyberSpider (+http://www.fybersearch.com/fyberspider.php)',
    'FyberSpider',
    'everyfeed-spider/2.0 (http://www.everyfeed.com)',
    'envolk[ITS]spider/1.6 (+http://www.envolk.com/envolkspider.html)',
    'envolk[ITS]spider/1.6 ( http://www.envolk.com/envolkspider.html)',
    'Baiduspider+(+http://www.baidu.com/search/spider_jp.html)',
    'Baiduspider+(+http://www.baidu.com/search/spider.htm)',
    'BaiDuSpider',
    'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0) AddSugarSpiderBot www.idealobserver.com',
    ]
DOWNLOADER_MIDDLEWARES = {
    'spider_douban.middlewares.RandomUserAgentMiddleware': 400,
    'scrapy.contrib.downloadermiddleware.useragent.UserAgentMiddleware': None,
}

USER_AGENT_LIST定義了一些瀏覽器user-agent屬性,網(wǎng)上有很多,可以找來(lái)直接加進(jìn)去,需要注意的是有些user-agent信息是移動(dòng)設(shè)備(手機(jī)或平板)的,如果不注意的話,可能請(qǐng)求到的數(shù)據(jù)與你看到的數(shù)據(jù)有較大差異;
DOWNLOADER_MIDDLEWARES定義了下載器中間件,它在發(fā)送頁(yè)面請(qǐng)求數(shù)據(jù)的時(shí)候被調(diào)用。

middlewares.py

from spider_douban.settings import USER_AGENT_LIST
import random

class RandomUserAgentMiddleware():
    def process_request(self, request, spider):
        ua  = random.choice(USER_AGENT_LIST)
        if ua:
            request.headers.setdefault('User-Agent', ua)

在RandomUserAgentMiddleware()中,每次發(fā)送請(qǐng)求數(shù)據(jù),會(huì)在USER_AGENT_LIST中隨機(jī)選擇一條User-Agent記錄。

5.結(jié)果保存

編輯pipelines.py文件:

from scrapy import signals
from scrapy.contrib.exporter import CsvItemExporter

class SpiderDoubanPipeline(CsvItemExporter):
    def __init__(self):
        self.files = {}
    @classmethod
    def from_crawler(cls, crawler):
        print('==========pipeline==========from_crawler==========')
        pipeline = cls()
        crawler.signals.connect(pipeline.spider_opened, signals.spider_opened)
        crawler.signals.connect(pipeline.spider_closed, signals.spider_closed)
        return pipeline
    def spider_opened(self, spider):
        savefile = open('douban_top250_export.csv', 'wb+')
        self.files[spider] = savefile
        print('==========pipeline==========spider_opened==========')
        self.exporter = CsvItemExporter(savefile)
        self.exporter.start_exporting()
    def spider_closed(self, spider):
        print('==========pipeline==========spider_closed==========')
        self.exporter.finish_exporting()
        savefile = self.files.pop(spider)
        savefile.close()
    def process_item(self, item, spider):
        print('==========pipeline==========process_item==========')
        print(type(item))
        self.exporter.export_item(item)
        return item

SpiderDoubanPipeline類是建立項(xiàng)目的時(shí)候自行建立的,為了保存文件,做了修改。

def from_crawler(cls, crawler):

  • 如果存在,則調(diào)用此類方法從Crawler創(chuàng)建pipeline實(shí)例。它必須返回一個(gè)新的pipeline實(shí)例。抓取對(duì)象提供對(duì)所有Scrapy核心組件的訪問(wèn),如settings和signals; 這是pipeline訪問(wèn)它們并將其功能掛接到Scrapy的一種方式。

在此方法中,定義了一個(gè)數(shù)據(jù)收集器(cls)的實(shí)例:‘pipeline’。

signals:Scrapy使用信號(hào)來(lái)通知事情發(fā)生。您可以在您的Scrapy項(xiàng)目中捕捉一些信號(hào)(使用 extension)來(lái)完成額外的工作或添加額外的功能,擴(kuò)展Scrapy。雖然信號(hào)提供了一些參數(shù),不過(guò)處理函數(shù)不用接收所有的參數(shù) - 信號(hào)分發(fā)機(jī)制(singal dispatching mechanism)僅僅提供處理器(handler)接受的參數(shù)。您可以通過(guò) 信號(hào)(Signals) API 來(lái)連接(或發(fā)送您自己的)信號(hào)。

connect:鏈接一個(gè)接收器函數(shù)(receiver function) 到一個(gè)信號(hào)(signal)。signal可以是任何對(duì)象,雖然Scrapy提供了一些預(yù)先定義好的信號(hào)。

def spider_opened(self, spider):

  • 當(dāng)spider開(kāi)始爬取時(shí)發(fā)送該信號(hào)。該信號(hào)一般用來(lái)分配spider的資源,不過(guò)其也能做任何事。該信號(hào)支持返回deferreds。

此方法中,創(chuàng)建了一個(gè)文件對(duì)象實(shí)例:savefile。

CsvItemExporter(savefile):輸出 csv 文件格式. 如果添加 fields_to_export 屬性, 它會(huì)按順序定義CSV的列名.

def spider_closed(self, spider):

  • 當(dāng)某個(gè)spider被關(guān)閉時(shí),該信號(hào)被發(fā)送。該信號(hào)可以用來(lái)釋放每個(gè)spider在 spider_opened 時(shí)占用的資源。該信號(hào)支持返回deferreds。

def process_item(self, item, spider):

  • 每個(gè)item pipeline組件都需要調(diào)用該方法,這個(gè)方法必須返回一個(gè) Item (或任何繼承類)對(duì)象, 或是拋出 DropItem 異常,被丟棄的item將不會(huì)被之后的pipeline組件所處理。

啟用pipeline

為了讓我們定義的pipeline生效,要在settings.py文件中,打開(kāi)ITEM_PIPELINES注釋:

ITEM_PIPELINES = {
    'spider_douban.pipelines.SpiderDoubanPipeline': 300,
}

6.執(zhí)行爬蟲(chóng)

scrapy crawl douban_movie_top250

執(zhí)行爬蟲(chóng)能夠看到爬取到的數(shù)據(jù)。。。

如果之前pipeline部分代碼沒(méi)有寫(xiě),也可以用下面的命令,在爬蟲(chóng)執(zhí)行的時(shí)候直接導(dǎo)出數(shù)據(jù):

scrapy crawl douban_movie_top250 -o douban.csv

增加-o參數(shù),可以將爬取到的數(shù)據(jù)保存到douban.csv文件中。。

7.文件編碼的問(wèn)題

我在linux服務(wù)器執(zhí)行爬蟲(chóng),生成csv文件后,在win7系統(tǒng)中用excel打開(kāi)變成亂碼。在網(wǎng)上找了一些文章,有的文章直接改變linux文件默認(rèn)編碼,但是感覺(jué)這么做會(huì)對(duì)其他項(xiàng)目產(chǎn)生影響。最后選擇一個(gè)相對(duì)簡(jiǎn)單的方式。按這幾步執(zhí)行就可以:

  1. 不要直接用excel打開(kāi)csv文件。先打開(kāi)excel,建立空白工作表。

  2. 選擇數(shù)據(jù)選項(xiàng)卡,打開(kāi)獲取外部數(shù)據(jù)中的自文本。

  3. 在導(dǎo)入文本文件對(duì)話框中選擇要導(dǎo)入的csv文件。

  4. 在文本導(dǎo)入向?qū)?- 第1步中,設(shè)置文件原始格式為65001 : Unicode (UTF-8)

  5. 繼續(xù)下一步選擇逗號(hào)分隔,就可以導(dǎo)入正常文本了。

看完了這篇文章,相信你對(duì)scrapy爬取豆瓣電影數(shù)據(jù)的方法有了一定的了解,想了解更多相關(guān)知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)-成都網(wǎng)站建設(shè)公司行業(yè)資訊頻道,感謝各位的閱讀!

分享標(biāo)題:scrapy爬取豆瓣電影數(shù)據(jù)的方法-創(chuàng)新互聯(lián)
標(biāo)題鏈接:http://muchs.cn/article10/poigo.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供Google、外貿(mào)建站、做網(wǎng)站、App設(shè)計(jì)云服務(wù)器、品牌網(wǎng)站建設(shè)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

網(wǎng)站托管運(yùn)營(yíng)