本實例主要通過抓取慕課網的課程信息來展示scrapy框架抓取數據的過程。
1、抓取網站情況介紹
抓取網站:http://www.imooc.com/course/list
抓取內容:要抓取的內容是全部的課程名稱,課程簡介,課程URL ,課程圖片URL,課程人數(由於動態渲染暫時沒有獲取到)
網站圖片:



2、建立工程
在命令行模式建立工程
scrapy startproject scrapy_course
建立完成后,用pycharm打開,目錄如下:

scrapy.cfg: 項目的配置文件
scrapytest/: 該項目的python模塊。之后您將在此加入代碼。
scrapytest/items.py: 項目中的item文件.
scrapytest/pipelines.py: 項目中的pipelines文件.
scrapytest/settings.py: 項目的設置文件.
scrapytest/spiders/: 放置spider代碼的目錄.
3、創建一個爬蟲
下面按步驟講解如何編寫一個簡單的爬蟲。
我們要編寫爬蟲,首先是創建一個Spider
我們在scrapy_course/spiders/目錄下創建一個文件MySpider.py
文件包含一個MySpider類,它必須繼承scrapy.Spider類。
同時它必須定義一下三個屬性:
-name: 用於區別Spider。 該名字必須是唯一的,您不可以為不同的Spider設定相同的名字。
-start_urls: 包含了Spider在啟動時進行爬取的url列表。 因此,第一個被獲取到的頁面將是其中之一。 后續的URL則從初始的URL獲取到的數據中提取。
-parse() 是spider的一個方法。 被調用時,每個初始URL完成下載后生成的 Response 對象將會作為唯一的參數傳遞給該函數。 該方法負責解析返回的數據(response data),提取數據(生成item)以及生成需要進一步處理的URL的 Request 對象。
創建完成后MySpider.py的代碼如下

定義爬蟲項目
創建完了Spider文件,先不急着編寫爬取代碼
我們先定義一個容器保存要爬取的數據。
這樣我們就用到了Item
為了定義常用的輸出數據,Scrapy提供了Item類。Item對象是種簡單的容器,保存了爬取到得數據。 其提供了 類似於詞典(dictionary-like)的API以及用於聲明可用字段的簡單語法。
我們在工程目錄下可以看到一個items文件,我們可以更改這個文件或者創建一個新的文件來定義我們的item。
這里,我們在同一層創建一個新的item文件CourseItems.py

根據如上的代碼,我們創建了一個名為courseItem的容器,用來保存、抓取的信息,
title->課程標題, url->課程url, image_url->課程標題圖片, introduction->課程描述, student->學習人數
在創建完item文件后我們可以通過類似於詞典(dictionary-like)的API以及用於聲明可用字段的簡單語法。
常用方法如下
4、編寫Spider代碼
定義了item后我們就能進行爬取部分的工作了。
為了簡單清晰,我們先抓取一個頁面中的信息。
首先我們編寫爬取代碼
我們在上文說過,爬取的部分在MySpider類的parse()方法中進行。
parse()方法負責處理response並返回處理的數據以及(/或)跟進的URL。
該方法及其他的Request回調函數必須返回一個包含 Request 及(或) Item 的可迭代的對象。
我們在之前創建的MySpider.py中編寫如下代碼。
注意和上邊MySpider.py的區別
# -*- coding:utf8-*- import scrapy import sys import time reload(sys) sys.setdefaultencoding('utf-8') from scrapy_course.items import CourseItem from scrapy.selector import Selector sys.stdout = open('output.txt', 'w') pageIndex = 0 class MySpider(scrapy.Spider): #用於區別Spider name = "MySpider" #允許訪問的域 allowed_domains = ['imooc.com'] #爬取的地址 start_urls = ["http://www.imooc.com/course/list"] #爬取方法 def parse(self, response): # 實例一個容器保存爬取的信息 item = CourseItem() # 這部分是爬取部分,使用xpath的方式選擇信息,具體方法根據網頁結構而定 # 先獲取每個課程的div sel = Selector(response) title = sel.xpath('/html/head/title/text()').extract() # 標題 print title[0] # sels = sel.xpath('//div[@class="course-card-content"]') sels = sel.xpath('//a[@class="course-card"]') pictures = sel.xpath('//div[@class="course-card-bk"]') index = 0 global pageIndex pageIndex += 1 print u'%s' % (time.strftime('%Y-%m-%d %H-%M-%S')) print '第' + str(pageIndex)+ '頁 ' print '----------------------------------------------' for box in sels: print ' ' # 獲取div中的課程標題 item['title'] = box.xpath('.//h3[@class="course-card-name"]/text()').extract()[0].strip() print '標題:' + item['title'] # 獲取div中的課程簡介 item['introduction'] = box.xpath('.//p/text()').extract()[0].strip() print '簡介:' + item['introduction'] # 獲取每個div中的課程路徑 item['url'] = 'http://www.imooc.com' + box.xpath('.//@href').extract()[0] print '路徑:' +item['url'] # 獲取div中的學生人數 item['student'] = box.xpath('.//div[@class="course-card-info"]/text()').extract()[0].strip() print item['student'] # 獲取div中的標題圖片地址 item['image_url'] = pictures[index].xpath('.//img/@src').extract()[0] print '圖片地址:' + item['image_url'] index += 1 yield item time.sleep(1) print u'%s' % (time.strftime('%Y-%m-%d %H-%M-%S')) # next =u'下一頁' # url = response.xpath("//a[contains(text(),'" + next + "')]/@href").extract() # if url: # # 將信息組合成下一頁的url # page = 'http://www.imooc.com' + url[0] # # 返回url # yield scrapy.Request(page, callback=self.parse)
使用Pipeline處理數據
當我們成功獲取信息后,要進行信息的驗證、儲存等工作,這里以儲存為例。
當Item在Spider中被收集之后,它將會被傳遞到Pipeline,一些組件會按照一定的順序執行對Item的處理。
Pipeline經常進行一下一些操作:
清理HTML數據
驗證爬取的數據(檢查item包含某些字段)
查重(並丟棄)
目前暫時將爬取結果保存到文本中
這里只進行簡單的將數據儲存在json文件的操作。
pipelines.py代碼如下
# -*- 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.html import codecs import json class ScrapyCoursePipeline(object): def __init__(self): # self.file = open('data.json', 'wb') # self.file = codecs.open( # 'spider.txt', 'w', encoding='utf-8') self.file = codecs.open( 'spider.json', 'w', encoding='utf-8') def process_item(self, item, spider): line = json.dumps(dict(item), ensure_ascii=False) + "\n" self.file.write(line) return item def spider_closed(self, spider): self.file.close()
要使用Pipeline,首先要注冊Pipeline
找到settings.py文件,這個文件時爬蟲的配置文件
在其中添加
ITEM_PIPELINES = { 'scrapy_course.pipelines.ScrapyCoursePipeline':300 }
上面的代碼用於注冊Pipeline,其中scrapy_course.pipelines.ScrapyCoursePipeline為你要注冊的類,右側的’300’為該Pipeline的優先級,范圍1~1000,越小越先執行。
進行完以上操作,我們的一個最基本的爬取操作就完成了
這時我們再運行
5、運行
在命令行下運行scrapy crawl MySpider


如何要把數據存儲到文本文件中,在代碼前面增加以后代碼,
sys.stdout = open('output.txt', 'w'),這樣就會把數據保存到當前項目路徑下的output.txt文件里面
如下:

