Scrapy爬取豆瓣電影Top250

這兩天摸索了下scrapy,剛看文檔的時候覺得有點生無可戀,scrapy框架個人還是覺得比較難懂的,需要學習的地方非常多,之前用beautifulsoup4爬過top250,比scrapy簡單更容易理解!!

Scrapy簡介

Scrapy,Python開發的一個快速、高層次的屏幕抓取和web抓取框架,用于抓取web站點并從頁面中提取結構化的數據。Scrapy用途廣泛,可以用于數據挖掘、監測和自動化測試。 下面對每個組件都做了簡單介紹,數據流如下所描述。


image
  • Scrapy Engine
    引擎負責控制數據流在系統中所有組件中流動,并在相應動作發生時觸發事件。 詳細內容查看下面的數據流(Data Flow)部分
  • 調度器(Scheduler)
    調度器從引擎接受request并將他們入隊,以便之后引擎請求他們時提供給引擎
  • 下載器(Downloader)
    下載器負責獲取頁面數據并提供給引擎,而后提供給spider
  • Spiders
    Spider是Scrapy用戶編寫用于分析response并提取item(即獲取到的item)或額外跟進的URL的類。 每 個spider負責處理一個特定(或一些)網站
  • Item Pipeline
    Item Pipeline負責處理被spider提取出來的item。典型的處理有清理、 驗證及持久化(例如存取到數 據庫中)
  • 下載器中間件(Downloader middlewares)
    下載器中間件是在引擎及下載器之間的特定鉤子(specific hook),處理Downloader傳遞給引擎的 response。 其提供了一個簡便的機制,通過插入自定義代碼來擴展Scrapy功能
  • Spider中間件(Spider middlewares)
    Spider中間件是在引擎及Spider之間的特定鉤子(specific hook),處理spider的輸入(response)和輸出 (items及requests)。 其提供了一個簡便的機制,通過插入自定義代碼來擴展Scrapy功能
  • 數據流(Data flow)
    Scrapy中的數據流由執行引擎控制,其過程如下:

引擎打開一個網站(open a domain),找到處理該網站的Spider并向該spider請求第一個要爬取的 URL(s)。
引擎從Spider中獲取到第一個要爬取的URL并在調度器(Scheduler)以Request調度。
引擎向調度器請求下一個要爬取的URL。
調度器返回下一個要爬取的URL給引擎,引擎將URL通過下載中間件(請求(request)方向)轉發給下載 器(Downloader)。
一旦頁面下載完畢,下載器生成一個該頁面的Response,并將其通過下載中間件(返回(response)方 向)發送給引擎。
引擎從下載器中接收到Response并通過Spider中間件(輸入方向)發送給Spider處理。
Spider處理Response并返回爬取到的Item及(跟進的)新的Request給引擎。
引擎將(Spider返回的)爬取到的Item給Item Pipeline,將(Spider返回的)Request給調度器。
(從第二步)重復直到調度器中沒有更多地request,引擎關閉該網站

scrapy的流程如圖,并且可歸納如下

  • 首先下載器下載request回執的html等的response
  • 然后下載器傳給爬蟲解析
  • 接著爬蟲解析后交給調度器過濾,查重等等
  • 最后交給管道,進行爬取數據的處理

建議大家參考下中文版的Scrapy文檔,看文檔還是比較枯燥的,Scrapy又比較難懂(大神忽略),務必要有耐心!!!!!!

實戰應用

首先下載Scrapy包

pip install scrapy

這樣安裝,windows平臺應該是會報錯的,我當時裝Scrapy時廢了很大勁才弄完。安裝過程中Pycharm或者官網上找不到的模塊可以上這個網址找Unofficial Windows Binaries for Python Extension Packages
Pywin32

接著,我們打開CMD,新建一個爬蟲文件

scrapy startproject douban

image

C:\Users\ssaw\douban>tree /f
C:.
│ scrapy.cfg

└─douban
│ items.py
│ middlewares.py
│ pipelines.py
│ settings.py
init.py

└─spiders
init.py

簡單介紹下這些文件

  • scrapy.cfg: 項目的配置文件
  • douban/: 該項目的python模塊。之后您將在此加入代碼
  • douban/items.py: 項目中的item文件
  • douban/pipelines.py: 項目中的pipelines文件
  • douban/settings.py: 項目的設置文件
  • douban/spiders/:放置spider代碼的目錄

編輯items.py文件

# -*- coding: utf-8 -*-

# Define here the models for your scraped items
#
# See documentation in:
# http://doc.scrapy.org/en/latest/topics/items.html

import scrapy


class DoubanItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    movie_name = scrapy.Field()
    movie_star = scrapy.Field()
    movie_quote = scrapy.Field()
  • 首先,引入Scrapy
  • 接著,創建一個類,繼承自scrapy.item,這個是用來儲存要爬下來的數據的存放容器,類似orm的寫法
  • 我們要記錄的是:電影的名字、電影的評分、電影的引述(quote)

現在,我們在spiders文件夾下創建douban_spider.py
在我們編寫爬蟲之前,先了解一下scrapy的爬取機制,scrapy提取數據有自己的一套機制。它們被稱作選擇器(seletors),因為他們通過特定的 XPath 或者 CSS 表達式來“選擇” HTML文件中的某個部分。
之前我在博客上也總結過一篇使用Xpath模擬登陸GitHub有興趣可以看一下
附上Xpath學習教程Xpath

獲取網頁數據

打開Chrome(F12),查找元素
豆瓣電影TOP250

image

紅框圈出來的分別代表

movie_name = div[@class="hd"]/a/span/
movie_star = div[@class="bd"]/div[@class="star"]/span[@class="rating_num"]
movie_quote = div[@class="bd"]/p[@class="quote"]/span[@class="inq"]

# _*_ coding=utf-8 _*_

from scrapy.spiders import Spider
from scrapy.selector import Selector

class DouBanSpider(Spider):
    name = 'db'
    start_urls = ['https://movie.douban.com/top250']

    def parse(self, response):
        # print(response.body)
        selector = Selector(response)

        # print(selector)
        movies = selector.xpath('//div[@class="info"]')
        for movie in movies:
            movie_name = movie.xpath('div[@class="hd"]/a/span/text()').extract()
            movie_star = movie.xpath('div[@class="bd"]/div[@class="star"]/span[@class="rating_num"]/text()').extract()
            movie_quote = movie.xpath('div[@class="bd"]/p[@class="quote"]/span[@class="inq"]/text()').extract()


            print(movie_name)
            print(movie_star)
            print(movie_quote)

我們打開setting.py,加上U-A

USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36'

在CMD中輸入scrapy crawl db,運行如下:


image

我們還可以在douban文件根目錄創建一個main.py,這樣就可以在Pycharm中運行了

from scrapy import cmdline
cmdline.execute("scrapy crawl db".split())

使用Item

Item對象是自定義的python字典。 您可以使用標準的字典語法來獲取到其每個字段的值。(字段即是我們之前用Field賦值的屬性),Spider將會將爬取到的數據以 Item 對象返回。

item = DoubanItem()

item['movie_name'] = movie_name
item['movie_star'] = movie_star
item['movie_quote'] = movie_quote

好了,現在我們先試著爬取單頁面,查看下結果后,再去爬取多頁面

from scrapy.spiders import Spider
from scrapy.selector import Selector
from douban.items import DoubanItem



class DouBanSpider(Spider):
    name = 'db'
    start_urls = ['https://movie.douban.com/top250']

    def parse(self, response):
        # print(response.body)
        selector = Selector(response)

        # print(selector)
        movies = selector.xpath('//div[@class="info"]')
        for movie in movies:
            movie_name = movie.xpath('div[@class="hd"]/a/span/text()').extract()
            movie_star = movie.xpath('div[@class="bd"]/div[@class="star"]/span[@class="rating_num"]/text()').extract()
            movie_quote = movie.xpath('div[@class="bd"]/p[@class="quote"]/span[@class="inq"]/text()').extract()

            #print(movie_name)
            #print(movie_star)
            #print(movie_quote)

            item = DoubanItem()

            item['movie_name'] = movie_name
            item['movie_star'] = movie_star
            item['movie_quote'] = movie_quote
            yield item
            print(movie_name)
            print(movie_star)
            print(movie_quote)
  • 首先,我們先從scrapy中獲得所需要的通用的 spider和 selector
  • 接著,我們使用Item將爬取的數據返回
  • 創建了一個DouBanSpider,繼承了 scrapy.Spider 類, 且定義以下三個屬性:
  1. name: 用于區別Spider。 該名字必須是唯一的,您不可以為不同的Spider設定相同的名字
  2. start_urls: 包含了Spider在啟動時進行爬取的url列表。 因此,第一個被獲取到的頁面將是其中之一, 后續的URL則從初始的URL獲取到的數據中提取。
  3. parse() 是spider的一個方法。 被調用時,每個初始URL完成下載后生成的 Response 對象將會作為唯一的參數傳遞給該函數。 該方法負責解析返回的數據(response data),提取數據(生成item)以及生成需要進一步處理的URL的 Request 對象
  • seletor的方法返回后一定要用它的 extract()方法,來返回一個列表 ;extract()文檔的定義:串行化并將匹配到的節點返回一個unicode字符串列表。 結尾是編碼內容的百分比
  • 接著,我們把得到的數據保存在Item中
  • 最后,我們使用Feed exports來保存數據
  • 這里使用了yield生成器函數,生成器函數和迭代器有密切關系,也并不是很容易理解,這一點需要多多學習
#看一個yield函數的示例
#函數在每次循環時都會產生一個值,之后將其返回給它的調用者
#函數不斷的生成數字的平方

def gensquares(N):
    for i in range(N):
        yield i ** 2
        
for i in gensquares(5):
    print(i, end=' ')

0 1 4 9 16 

好了,spider暫時寫完了,我們試著運行下

scrapy crawl db -o douban.json -t json

-o 后面是導出文件名,-t 后面是導出類型。
然后來看一下導出的結果,Pycharm打開json文件即可


image

打印出來的內容需要編碼
我們換種方式,把文件格式保存為CSV,使用EXCEL打開

scrapy crawl db -o douban.csv -t csv

image

用excel打開后假如是一堆亂碼,就使用記事本打開,把它“另存為”時,編碼選擇ANSI


image

好了,現在我們添加多頁面鏈接,完整地把TOP250爬取下來
我們從Elements中找到翻頁lianjie


image
next_page =response.selector.xpath('//span[@class="next"]/link/@href').extract()
if next_page:
    next_page = next_page[0]
    print(next_page)
    yield Request(self.url + next_page, callback=self.parse)

CMD輸入scrapy crawl db -o douban.csv -t csv ,開始運行


image

學習Scrapy需要反復查看文檔、資料,這是個簡單的學習總結,這兩天準備再去學習MongoDB數據庫,大家一起加油!!

參考鏈接
參考鏈接
Scrapy文檔
GitHub
簡書
最后,歡迎大家訪問我的博客Treehl的博客

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,882評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,208評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,746評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,666評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,477評論 6 407
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,960評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,047評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,200評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,726評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,617評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,807評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,327評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,049評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,425評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,674評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,432評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,769評論 2 372

推薦閱讀更多精彩內容

  • scrapy學習筆記(有示例版) 我的博客 scrapy學習筆記1.使用scrapy1.1創建工程1.2創建爬蟲模...
    陳思煜閱讀 12,740評論 4 46
  • Scrapy介紹 Scrapy是一個為了爬取網站數據,提取結構性數據而編寫的應用框架。 可以應用在包括數據挖掘,信...
    JasonDing閱讀 122,538評論 15 126
  • 天的那邊,雛陽高照 海的遠邊,酒雨紛紛 綿綿絲雨,悠悠我心 徐徐清風,柔柔撫心 半載未歸,思之如狂 長相思情,轉難入夢
    南國梓桐君閱讀 273評論 0 1
  • 成功的時候,誰都是朋友。但只有母親——她是失敗時的伴侶。 感謝媽媽: 自己活了二十多年,最需要感謝的就是母親。我很...
    宋東珂_閱讀 416評論 0 2
  • 一、釋運氣 運氣,是五運六氣的簡稱。 五運:金、木、水、火、土。(行的東西代表)十天干?陰陽干 六氣:太陽寒水、厥...
    王胖胖搖啊搖閱讀 1,583評論 1 3