python爬蟲入門筆記:用scrapy爬豆瓣

本文希望達到以下目標:

  1. 簡要介紹Scarpy
  2. 使用Scarpy抓取豆瓣電影

我們正式講scrapy框架爬蟲,並用豆瓣來試試手,url:http://movie.douban.com/top250

首先先要回答一個問題。

問:把網站裝進爬蟲裏,總共分幾步?

答案很簡單,四步:

  • 新建項目 (Project):新建一個新的爬蟲項目
  • 明確目標(Items):明確你想要抓取的目標
  • 製作爬蟲(Spider):製作爬蟲開始爬取網頁
  • 存儲內容(Pipeline):設計管道存儲爬取內容


好的,基本流程既然確定了,那接下來就一步一步的完成就可以了。


1.新建項目(Project)

在空目錄下按住Shift鍵右擊,選擇“在此處打開命令窗口”,輸入一下命令:

<span style="font-size:14px;">scrapy startproject douban</span>
其中,douban爲項目名稱。

可以看到將會創建一個douban文件夾,目錄結構如下:

douban/
    scrapy.cfg
    douban/
        __init__.py
        items.py
        pipelines.py
        settings.py
        spiders/
            __init__.py
            ...</span>

我們用pycharm打開該項目,具體看一下:


下面來簡單介紹一下各個文件的作用:

  • scrapy.cfg:項目的配置文件
  • douban/:項目的Python模塊,將會從這裏引用代碼
  • douban/items.py:項目的items文件
  • douban/pipelines.py:項目的pipelines文件
  • douban/settings.py:項目的設置文件
  • douban/spiders/:存儲爬蟲的目錄                                                    

2.明確目標(Item)

在Scrapy中,items是用來加載抓取內容的容器,提供了一些額外的保護減少錯誤。

一般來說,item可以用scrapy.item.Item類來創建,並且用scrapy.item.Field對象來定義屬性。

接下來,我們開始來構建item模型(model)。

首先,我們想要的內容有:

  • 電影名稱(name)
  • 電影描述(movieInfo)
  • 電影評分(star)
  • 格言(quote)


修改douban目錄下的items.py文件,在原本的class後面添加我們自己的class。

因爲要抓豆瓣網站的內容,所以我們可以將其命名爲DoubanItem:

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

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

from scrapy import Item, Field

class DoubanItem(Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    title = Field()
    movieInfo = Field()
    star = Field()
    quote = Field()

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

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

from scrapy import Item, Field

class DoubanItem(Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    title = Field()
    movieInfo = Field()
    star = Field()
    quote = Field()

3.製作爬蟲(Spider)

製作爬蟲,總體分兩步:先爬再取。

也就是說,首先你要獲取整個網頁的所有內容,然後再取出其中對你有用的部分。

3.1爬

Spider是用戶自己編寫的類,用來從一個域(或域組)中抓取信息。

他們定義了用於下載的URL列表、跟蹤鏈接的方案、解析網頁內容的方式,以此來提取items。

要建立一個Spider,你必須用scrapy.spider.BaseSpider創建一個子類,並確定三個強制的屬性:

  • name:爬蟲的識別名稱,必須是唯一的,在不同的爬蟲中你必須定義不同的名字。
  • start_urls:爬取的URL列表。爬蟲從這裏開始抓取數據,所以,第一次下載的數據將會從這些urls開始。其他子URL將會從這些起始URL中繼承性生成。
  • parse():解析的方法,調用的時候傳入從每一個URL傳回的Response對象作爲唯一參數,負責解析並匹配抓取的數據(解析爲item),跟蹤更多的URL。
下面我們來寫第一隻爬蟲,命名爲doubanspider.py,保存在douban\spiders目錄下。


# -*- coding: utf-8 -*-
from scrapy.spiders import CrawlSpider

class Douban(CrawlSpider):
    name = "douban"
    start_urls = ['http://movie.douban.com/top250']

    def parse(self,response):
        print response.body
# -*- coding: utf-8 -*-
from scrapy.spiders import CrawlSpider

class Douban(CrawlSpider):
    name = "douban"
    start_urls = ['http://movie.douban.com/top250']

    def parse(self,response):
        print response.body


然後運行一下看看,在douban目錄下按住shift右擊,在此處打開命令窗口,輸入:

scrapy crawl douban

運行結果如圖:


最後一句INFO: Closing spider (finished)表明爬蟲已經成功運行並且自行關閉了。

其實,我們可以創建main.py,保存在douban目錄下,
from scrapy import cmdline
cmdline.execute("scrapy crawl douban".split())
from scrapy import cmdline
cmdline.execute("scrapy crawl douban".split())

在pycharm裏運行main.py,可以得到相同的結果。
但是很不幸我們會看到  DEBUG: Ignoring response <403 http://movie.douban.com/top250>: HTTP status code is not handled or not allowed   怎麼回事呢,被屏蔽了,我們來僞裝一下,在settings.py里加上USER_AGENT:

USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_3) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.54 Safari/536.5'

運行看一下結果:
3.1取
這裏我們還是使用Xpath來解析,相關知識可以看Xpath那一節,這裏不細說,只是講一下大概思路:
F12審查元素,我們看一下頁面代碼


我們可以看到每一部電影的信息都在一個<li>...<li>裏,打開後可以找到我們想要的全部信息,看一下代碼:

selector = Selector(response)
Movies = selector.xpath('//div[@class="info"]')
for eachMoive in Movies:
     title = eachMoive.xpath('div[@class="hd"]/a/span/text()').extract()
     movieInfo = eachMoive.xpath('div[@class="bd"]/p/text()').extract()
     star = eachMoive.xpath('div[@class="bd"]/div[@class="star"]/span[@class="rating_num"]/text()').extract()[0]
     quote = eachMoive.xpath('div[@class="bd"]/p[@class="quote"]/span/text()').extract()

這裏面有兩個小問題,大家自己做時可以發現,title包括兩個,而quote有的電影沒有,所以我們調整一下,完整代碼如下:

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

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

class Douban(CrawlSpider):
    name = "douban"
    start_urls = ['http://movie.douban.com/top250']

    def parse(self,response):
        #print response.body
        item = DoubanItem()
        selector = Selector(response)
        #print selector
        Movies = selector.xpath('//div[@class="info"]')
        #print Movies
        for eachMoive in Movies:
            title = eachMoive.xpath('div[@class="hd"]/a/span/text()').extract()
            # 把兩個名稱合起來
            fullTitle = ''
            for each in title:
                fullTitle += each
            movieInfo = eachMoive.xpath('div[@class="bd"]/p/text()').extract()
            star = eachMoive.xpath('div[@class="bd"]/div[@class="star"]/span[@class="rating_num"]/text()').extract()[0]
            quote = eachMoive.xpath('div[@class="bd"]/p[@class="quote"]/span/text()').extract()
            # quote可能爲空,因此需要先進行判斷
            if quote:
                quote = quote[0]
            else:
                quote = ''
            print fullTitle
            print movieInfo
            print star
            print quote

運行看一下結果:



因爲我們要爬取所有的電影,所以我們需要自動抓取下一頁的內容,我們來找一下下一頁的URL:


我們把它抓出來補成完整的URL,就可以循環抓取了,
這裏我們要引入Request,   from scrapy.http import Request
代碼如下:
nextLink = selector.xpath('//span[@class="next"]/link/@href').extract()
# 第10頁是最後一頁,沒有下一頁的鏈接
if nextLink:
    nextLink = nextLink[0]
    print nextLink
    url = 'http://movie.douban.com/top250'
    yield Request(self.url + nextLink, callback=self.parse)




這樣我們就可以把所有的電影都爬取下來了,完整代碼如下:

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

from scrapy.spiders import CrawlSpider
from scrapy.selector import Selector
from douban.items import DoubanItem
from scrapy.http import Request

class Douban(CrawlSpider):
    name = "douban"
    start_urls = ['http://movie.douban.com/top250']

    url = 'http://movie.douban.com/top250'

    def parse(self,response):
        #print response.body
        item = DoubanItem()
        selector = Selector(response)
        #print selector
        Movies = selector.xpath('//div[@class="info"]')
        #print Movies
        for eachMoive in Movies:
            title = eachMoive.xpath('div[@class="hd"]/a/span/text()').extract()
            # 把兩個名稱合起來
            fullTitle = ''
            for each in title:
                fullTitle += each
            movieInfo = eachMoive.xpath('div[@class="bd"]/p/text()').extract()
            star = eachMoive.xpath('div[@class="bd"]/div[@class="star"]/span[@class="rating_num"]/text()').extract()[0]
            quote = eachMoive.xpath('div[@class="bd"]/p[@class="quote"]/span/text()').extract()
            # quote可能爲空,因此需要先進行判斷
            if quote:
                quote = quote[0]
            else:
                quote = ''
            #print fullTitle
            #print movieInfo
            #print star
            #print quote
            item['title'] = fullTitle
            item['movieInfo'] = ';'.join(movieInfo)
            item['star'] = star
            item['quote'] = quote
            yield item
            nextLink = selector.xpath('//span[@class="next"]/link/@href').extract()
            # 第10頁是最後一頁,沒有下一頁的鏈接
            if nextLink:
                nextLink = nextLink[0]
                print nextLink
                yield Request(self.url + nextLink, callback=self.parse)

4.存儲內容(Pipeline)

保存信息的最簡單的方法是通過Feed exports,主要有四種:JSON,JSON lines,CSV,XML。

我們將結果用最常用的JSON導出,命令如下:


scrapy crawl douban -o items.json -t json

-o 後面是導出文件名,-t 後面是導出類型。

然後來看一下導出的結果,用文本編輯器打開json文件即可


看的不是很舒服,要是能直接看到內容就好了,我們試試保存成CSV,然後用EXCEL打開即可。

scrapy crawl douban -o items.csv -t csv


這麼看就順眼多了,還有保存的文件在這裏,不要找不到哦!



其實呢,我們可以直接在settings.py文件中設置輸出的位置和文件類型,如下:

FEED_URI = u'file:///E:/douban/douban.csv'
FEED_FORMAT = 'CSV'

在pycharm中運行main.py,就可以看到所有的電影信息啦,是不是很EASY!




如果你想用抓取的items做更復雜的事情,你可以寫一個 Item Pipeline(條目管道)。

後面我們也會有涉及的,敬請期待!

小夥伴們,自己動手試試吧!



相關學習文章:

1、簡書《Python爬蟲(六)--Scrapy框架學習》http://www.jianshu.com/p/078ad2067419

2、汪海實驗室http://blog.csdn.net/pleasecallmewhy/article/details/19642329

3、極客學院《scrapy初探》http://www.jikexueyuan.com/course/1287.html


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