利用scrapy和MongoDB來開發一個爬蟲

來源:互聯網
上載者:User

標籤:

今天我們利用scrapy架構來抓取Stack Overflow裡面最新的問題(問題標題和網址),並且將這些問題儲存到MongoDb當中,直接提供給客戶進行查詢。

安裝

在進行今天的任務之前我們需要安裝二個架構,分別是Scrapy (1.1.0)和pymongo (3.2.2).

scrapy

如果你啟動並執行的系統是osx或者linux,可以直接通過pip進行安裝,而windows需要另外安裝一些依賴,因為電腦的原因不對此進行講解。

$ pip install Scrapy

一旦安裝完成之後你可以直接在python shell當中輸入下面的命令,倘若沒有出現錯誤的話,說明已安裝完成

>>> import scrapy
>>>

安裝PyMongo和mongodb

因為系統是osx的,所以直接通過下面的語句就可以安裝。

brew install mongodb

運行mongodb同樣特別的簡單,只需要在終端下面輸入下面的文法:

mongod --dbpath=.

--dbpath是指定資料庫存放的路徑,運行之後會在該路徑下面產生一些檔案
?

下一步我們就需要安裝PyMongo,同樣採用pip的方式

$ pip install pymongo

Scrapy 項目

我們來建立一個新的scrapy的項目,在終端輸入下面的文法

$ scrapy startproject stack

?
一旦上面的命令完成之後,scrapy會直接建立相應的檔案,這些檔案包含了基本的資訊,便於你來修改相應的內容。
?

定義資料

items.py檔案用於我們定義需要抓取對象的儲存的“容器“
有關StackItem()預定義時並讓其繼承於scrapy.Item

# -*- coding: utf-8 -*-# Define here the models for your scraped items## See documentation in:# http://doc.scrapy.org/en/latest/topics/items.htmlimport scrapyclass StackItem(scrapy.Item):    # define the fields for your item here like:    # name = scrapy.Field()    pass

這裡我們需要在裡面添加兩個欄位,分別用來存放抓取到的標題以及連結

from scrapy.item import Item,Fieldclass StackItem(Item):    # define the fields for your item here like:    title=Field()    url=Field()
建立爬蟲

我們需要在spider檔案夾下面建立一個stack_spider.py的檔案,這個裡麵包容我們爬蟲進行抓取時的行為。就是告訴爬蟲我們需要抓取哪些內容以及內容的來源。

from scrapy import Spiderfrom scrapy.selector import Selectorfrom stack.items import StackItemclass StackSpider(Spider):    name="stack"    allowed_domains=['stackoverflow.com']    start_urls = [        "http://stackoverflow.com/questions?pagesize=50&sort=newest",    ]
  • name 是定義爬蟲的名稱
  • allowed_domains 指定爬蟲進行爬取的域地址
  • start_urls 定義爬蟲需要抓取的網頁的url地址
XPath 選擇

scrapy使用XPath來進行匹配相應的資料的來源,html是一種標記的文法,裡面定義了很多的標籤和屬性,比如說我們定義一個下面的這樣的一個標籤,這裡我們就可以通過'//div[@class="content"]'來找到這個標記,找到之後我們可以取出其中的屬性或者它的子節點

<div class='content'>

下面我們通過chrome來講解如果找到xpath的路徑 ,在進行操作之前我們需要開啟開發人員工具,可以點擊功能表列上面的視圖->開發人員->開發人員工具來打進入開發人員模式,或者可以根據快捷捷來進行開啟。
?

開啟之後我們在需要的內容上面點擊右擊會彈出一個菜單,這裡我們可以選擇檢查來找到當前的內容在html相應的位置
?
這裡chrome會自動協助我們找到相應的位置,通過下面的分析,我們知道標題的路徑是包含在一個下面的h3標記當中。
?

現在我們來更新相應的stack_spider.py指令碼

from scrapy import Spiderfrom scrapy.selector import Selectorfrom stack.items import StackItemclass StackSpider(Spider):    name="stack"    allowed_domains=['stackoverflow.com']    start_urls = [        "http://stackoverflow.com/questions?pagesize=50&sort=newest",    ]    def parse(self,response):        questions=Selector(response).xpath('//div[@class="summary"]/h3')        
提取資料

建立抓取的規約之後,我們需要與剛才建立的items實體進行關聯,我們繼續修改stack_spider.py檔案

from scrapy import Spiderfrom scrapy.selector import Selectorfrom stack.items import StackItemclass StackSpider(Spider):    name="stack"    allowed_domains=['stackoverflow.com']    start_urls = [        "http://stackoverflow.com/questions?pagesize=50&sort=newest",    ]    def parse(self,response):        questions=Selector(response).xpath('//div[@class="summary"]/h3')        for question in questions:            item=StackItem()            item['title'] = question.xpath(                'a[@class="question-hyperlink"]/text()').extract()[0]            item['url'] = question.xpath(                'a[@class="question-hyperlink"]/@href').extract()[0]            yield item

通過遍曆所有的符合//div[@class="summary"]/h3的元素,並且從中找到我們真正需要爬取的元素內容

測試

現在我們進行測試,只要在項目的目錄下面運行以下的指令碼就可以進行測試 。

scrapy crawl stack

現在我們需要將爬取到的所有的資訊儲存到一個檔案當中,可以在後面添加二個參數-o和-t

scrapy crawl stack -o items.json -t json

下面是實際儲存的檔案的內容分別包含了title和url
?

將元素存放入MongoDB

這裡我們需要將所有的元素儲存到Mongodb collection當中。
在進行操作之前我們需要在setinngs.py指定相應的pipeline和添加一些資料庫的參數

ITEM_PIPELINES = {   'stack.pipelines.MongoDBPipeline': 300,}MONGODB_SERVER = "localhost"MONGODB_PORT = 27017MONGODB_DB = "stackoverflow"MONGODB_COLLECTION = "questions"
pipeline 管理

在之前的步驟裡面我們分別已經完成了對html的解析,以及指定資料的儲存。但是這時所有的資訊都在記憶體當中,我們需要將這些爬取到資料存放區到資料庫當中,這裡就輪到pipelines.py上場了,這玩意就負責對資料的儲存的。
在上面我們已經定義了資料庫的參數,現在我們終於派上用場了。

import pymongofrom scrapy.conf import settingsfrom scrapy.exceptions import DropItemfrom scrapy import logclass MongoDBPipeline(object):    def __init__(self):        connection=pymongo.MongoClient(            settings['MONGODB_SERVER'],            settings['MONGODB_PORT']        )        db=connection[settings['MONGODB_DB']]        self.collection=db[settings['MONGODB_COLLECTION']]

上面的代碼是我們建立了一個MongoDBPipeline()的類,以及定義初始化函數,用來讀取剛才的參數來建立一個Mongo的串連。

資料處理

下一步我們需要定義一個函數來處理解析的資料

# -*- coding: utf-8 -*-# Define your item pipelines here## Don't forget to add your pipeline to the ITEM_PIPELINES setting# See: http://doc.scrapy.org/en/latest/topics/item-pipeline.htmlimport pymongofrom scrapy.conf import settingsfrom scrapy.exceptions import DropItemfrom scrapy import logclass MongoDBPipeline(object):    def __init__(self):        connection=pymongo.MongoClient(            settings['MONGODB_SERVER'],            settings['MONGODB_PORT']        )        db=connection[settings['MONGODB_DB']]        self.collection=db[settings['MONGODB_COLLECTION']]    def process_item(self,item,spider):        valid=True        for data in item:            if not data:                valid=False                raise DropItem('Missing{0}!'.format(data))        if valid:            self.collection.insert(dict(item))            log.msg('question added to mongodb database!',                    level=log.DEBUG,spider=spider)        return item

上面已經完成了對資料的串連,以及相應資料的儲存

測試

我們同樣在stack目錄當中運行下面的命令

$ scrapy crawl stack

當內容執行完成之後沒有出現任何的錯誤的提示,恭喜你已經將資料正確的存入到mongodb當中。
這裡我們通過Robomongo來訪問資料庫的時候發現建立了一個stackoverflow的資料庫,下面已經成功建立了一個名為questions的Collections.並且已經存入了相應的資料了。
?

利用scrapy和MongoDB來開發一個爬蟲

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.