0. 基本環境說明
- 本文截圖及執行環境均在MAC OS X 10.9.5上實現,但基本步驟與win 7環境上相同(其實我是先在win7折騰了一把,然後為了寫這篇教程,又在OS X 上面重新搞了一遍)
- scrapy版本為1.0
- 參考文獻以及下載連結:
1. 建立步驟
通過上一篇內容我們已經將scrapy環境配置完畢,下面我們來實現一個demo來爬取南京郵電大學新聞頁面的內容。
1. 建立一個新工程
1 |
scrapy startproject njupt #其中njupt是專案名稱,可以按照個人喜好來定義 |
輸入以上命令之後,就會看見命令列執行的目錄下多了一個名為njupt
的目錄,目錄的結構如下:
1 2 3 4 5 6 7 8 9 |
|---- njupt | |---- njupt | |---- __init__.py | |---- items.py #用來儲存爬下來的資料結構(字典形式) | |---- pipelines.py #用來對爬出來的item進行後續處理,如存入資料庫等 | |---- settings.py #爬蟲配置檔案 | |---- spiders #此目錄用來存放建立的新爬蟲檔案(爬蟲主體) | |---- __init__.py | |---- scrapy.cfg #專案配置檔案 |
至此,工程建立完畢。
2. 設定 items
本文以抓取南郵新聞為例,需要儲存三種資訊:
- 南郵新聞標題
- 南郵新聞時間
- 南郵新聞的詳細連結
items內部程式碼如下:
1 2 3 4 5 6 7 8 9 |
# -*- coding: utf-8 -*- import scrapy class NjuptItem(scrapy.Item): #NjuptItem 為自動生成的類名 news_title = scrapy.Field() #南郵新聞標題 news_date = scrapy.Field() #南郵新聞時間 news_url = scrapy.Field() #南郵新聞的詳細連結 |
至於為什麼每一句都用scrapy.Field()
,這個等請關注我的後續教程,現在只要記住按照以上的格式來新增新的要提取的屬性就可以了~。
3. 編寫 spider
spider是爬蟲的主體,負責處理requset response 以及url等內容,處理完之後交給pipelines進行進一步處理。
設定完items之後,就在spiders目錄下新建一個njuptSpider.py
檔案,內容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
# -*- coding: utf-8 -*- import scrapy from njupt.items import NjuptItem import logging class njuptSpider(scrapy.Spider): name = "njupt" allowed_domains = ["njupt.edu.cn"] start_urls = [ "http://news.njupt.edu.cn/s/222/t/1100/p/1/c/6866/i/1/list.htm", ] def parse(self, response): news_page_num = 14 page_num = 386 if response.status == 200: for i in range(2,page_num+1): for j in range(1,news_page_num+1): item = NjuptItem() item['news_url'],item['news_title'],item['news_date'] = response.xpath( "//div[@id='newslist']/table[1]/tr["+str(j)+"]//a/font/text()" "|//div[@id='newslist']/table[1]/tr["+str(j)+"]//td[@class='postTime']/text()" "|//div[@id='newslist']/table[1]/tr["+str(j)+"]//a/@href").extract() yield item next_page_url = "http://news.njupt.edu.cn/s/222/t/1100/p/1/c/6866/i/"+str(i)+"/list.htm" yield scrapy.Request(next_page_url,callback=self.parse_news) def parse_news(self, response): news_page_num = 14 if response.status == 200: for j in range(1,news_page_num+1): item = NjuptItem() item['news_url'],item['news_title'],item['news_date'] = response.xpath( "//div[@id='newslist']/table[1]/tr["+str(j)+"]//a/font/text()" "|//div[@id='newslist']/table[1]/tr["+str(j)+"]//td[@class='postTime']/text()" "|//div[@id='newslist']/table[1]/tr["+str(j)+"]//a/@href").extract() yield item |
其中
name
為爬蟲名稱,在後面啟動爬蟲的命令當中會用到。allowed_domains
為允許爬蟲爬取的域名範圍(如果連線到範圍以外的就不爬取)start_urls
表明爬蟲首次啟動之後訪問的第一個Url,其結果會被自動返回給parse
函式。4.parse
函式為scrapy框架中定義的置函式,用來處理請求start_urls
之後返回的response
,由我們實現news_page_num = 14
和page_num = 386
別表示每頁的新聞數目,和一共有多少頁,本來也可以通過xpath爬取下來的,但是我實在是對我們學校的網站製作無語了,html各種混合,於是我就偷懶手動輸入了。- 之後通過
item = NjuptItem()
來使用我們之前定義的item,用來儲存新聞的url、標題、日期。(這裡面有一個小技巧就是通過|
來接連xpath可以一次返回多個想要抓取的xpath) - 通過
yield item
來將儲存下來的item
交由後續的pipelines
處理 - 之後通過生成
next_page_url
來通過scrapy.Request
抓取下一頁的新聞資訊 scrapy.Request
的兩個引數,一個是請求的URL另外一個是回撥函式用於處理這個request
的response
,這裡我們的回撥函式是parse_news
parse_news
裡面的步驟和parse
差不多,當然你也可以改造一下parse
然後直接將其當做回撥函式,這樣的話一個函式就ok了
4. 編寫 pipelines
初次編寫可以直接編輯njupt
目錄下的pipelines.py
檔案。pipelines主要用於資料的進一步處理,比如型別轉換、儲存入資料庫、寫到本地等。
本爬蟲pipelines如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
import json class NjuptPipeline(object): def __init__(self): self.file = open('njupt.txt',mode='wb') def process_item(self, item, spider): self.file.write(item['news_title'].encode("GBK")) self.file.write("\n") self.file.write(item['news_date'].encode("GBK")) self.file.write("\n") self.file.write(item['news_url'].encode("GBK")) self.file.write("\n") return item |
其實pipelines
是在每次spider
中yield item
之後呼叫,用於處理每一個單獨的item
。上面程式碼就是實現了在本地新建一個njupt.txt
檔案用於儲存爬取下來的內容。
5. 編寫 settings.py
settings.py
檔案用於儲存爬蟲的配置,有很多種配置,由於是入門教程,不需要配置很多,我們這裡就新增一下剛才編寫的pipelines就行了。檔案內容如下。
1 2 3 4 5 6 7 8 9 |
BOT_NAME = 'njupt' SPIDER_MODULES = ['njupt.spiders'] NEWSPIDER_MODULE = 'njupt.spiders' ITEM_PIPELINES = { 'njupt.pipelines.NjuptPipeline':1, } |
6. 啟動爬蟲與檢視結果
以上步驟全部完成之後,我們就啟動命令列,然後切換執行目錄到njupt
的spider
目錄下,通過以下命令啟動爬蟲
1 |
scrapy crawl njupt |
經過一段時間的風狂爬取,爬蟲結束。會報一些統計資訊
最後讓我們來檢視一下爬取成果
至此,大功告成~