人生苦短,我用Python
Item管道(Item Pipeline)
- 主要負責處理由蜘蛛從網頁抽取的Item,主要任務是清洗、驗證和儲存資料。
- 當頁面被蜘蛛解析後,將被髮送到Item管道,並經過幾個特定的次序處理資料。
- 每個Item管道的元件都是由一個簡單的方法組成的Python類。
- 它們獲取了Item並執行它們的方法,同時還需要確定是否需要在Item管道中繼續執行下一步或是直接丟棄掉不處理。
Item管道的作用:
- 清理HTML資料
- 驗證抓取的資料(檢查專案是否包含特定欄位)
- 檢查重複(並刪除)--說明:由於效能原因,去重最好在連結中去重,或者利用資料庫主鍵的唯一性去重
- 將抓取的專案儲存在資料庫中
Item管道主要函式:
1. process_item(self, item, spider)
------必須實現
每個Item Pipeline元件都需要呼叫該方法,這個方法必須返回一個Item(或任何繼承物件)物件,或是丟擲DropItem異常,被丟棄的item將不會被之後的Pipeline元件所處理
需傳入的引數:
- item(Item物件):被爬取的Item
- spider(Spider物件):爬取該item的spider
該方法會被每一個item pipeline元件所呼叫,process_item必須返回以下其中的任意一個物件;
- 一個字典dict
- 一個Item物件或者它的子類物件
- 一個Twisted Deferred物件
- 一個DropItem Exception;如果返回此異常,則該item將不會被後續的item pipeline繼續訪問
特別注意:該方法是Item Pipeline必須實現的方法,其他三個方法(open_spider/close_spider/from_crawler)是可選的方法
2.open_spider(self, spider)
—— 非必需,為爬蟲啟動的時候呼叫;
當 spider 被開啟時,這個方法被呼叫。可以實現在爬蟲開啟時需要進行的操作,比如說開啟一個待寫入的檔案,或者連線資料庫等
需要傳入的引數:
- spider (Spider 物件) : 被開啟的 spider
3. close_spider(self, spider)
—— 非必需, 為爬蟲關閉的時候呼叫;
當 spider 被關閉時,這個方法被呼叫。可以實現在爬蟲關閉時需要進行的操作,比如說關閉已經寫好的檔案,或者關閉與資料庫的連線
需要傳入的引數:
- spider (Spider 物件) : 被關閉的 spider
4. from_crawler(cls, crawler)
—— 非必需,也是在啟動的時候呼叫,比 open_spider早。
該類方法用來從 Crawler 中初始化得到一個 pipeline 例項;它必須返回一個新的 pipeline 例項;Crawler 物件提供了訪問所有 Scrapy 核心元件的介面,包括 settings 和 signals
需要傳入的引數:
- crawler (Crawler 物件) : 使用該管道的crawler
專案案例:爬取58同城房屋出租資訊
程式碼如下:
items.py
:定義我們所要爬取的資訊的相關屬性,此例中需要爬取的是name、price、url
# -*- 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 City58Item(scrapy.Item):
# define the fields for your item here like:
name = scrapy.Field()
price=scrapy.Field()
url=scrapy.Field()
pass複製程式碼
city58_demo.py
:主要是用於定義請求連結,並使用pyquery選取目標元素
# -*- coding: utf-8 -*-
import scrapy
from pyquery import PyQuery
from ..items import City58Item
import time
from scrapy.http import Request
class City58DemoSpider(scrapy.Spider):
name = 'city58_demo'
allowed_domains = ['58.com']
start_urls = ['http://sh.58.com/chuzu/']
def parse(self, response):
for index in range(1,4):
url='http://sh.58.com/chuzu/pn{0}'.format(str(index))
print(url)
time.sleep(3)
yield Request(url=url,callback=self.page)
def page(self,response):
jpy = PyQuery(response.text)
li_list=jpy('body > div.mainbox > div.main > div.content > div.listBox > ul > li').items()
for it in li_list:
a_tag = it(' div.des > h2 > a')
item = City58Item()
item['name'] = a_tag.text() # a_tag取出文字
item['url'] = a_tag.attr('href') # 取出href引數
item['price'] = it('div.listliright > div.money > b').text()
yield item # 把Item返回給引擎複製程式碼
pipeline.py
:當item資料被city58_test爬蟲爬取好並返回給引擎以後,引擎會把item交給City58Pipeline這個管道處理。這個pipeline檔案負責開啟MongoDB資料庫,並將資料寫入資料庫:
# -*- 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 json
import pymongo
class City58Pipeline(object):
collection_name = 'scrapy_items'
def __init__(self, mongo_uri, mongo_db):
self.mongo_uri = mongo_uri
self.mongo_db = mongo_db
@classmethod
def from_crawler(cls, crawler):
return cls(
mongo_uri=crawler.settings.get('localhost:27017'),
mongo_db=crawler.settings.get('MONGO_DATABASE', 'items')
)
def open_spider(self,spider):
#self.file=open('58_chuzu.txt','w',encoding='utf8')
self.client=pymongo.MongoClient()
self.db=self.client[self.mongo_db]
print('開啟資料庫了')
def process_item(self, item, spider):
line='{}\n'.format(json.dumps(dict(item)))#把item轉換成字串
#self.file.write(line)
self.db[self.collection_name].insert_one(dict(item))
return item
def close_spider(self,spider):
#self.file.close()
self.client.close()
print('關閉資料庫了')複製程式碼
settings.py
:開啟City58Pipeline這個管道
![Scrapy的專案管道](https://i.iter01.com/images/a1d09c30248b8c469621c5e2ab58558c887f960ca8e838991036d809d33e1f71.jpg)
說明:300相當於一個執行優先順序的序號
執行爬蟲,可以在專案下建立一個檔案:
執行該檔案即可執行爬蟲:
![Scrapy的專案管道](https://i.iter01.com/images/398531aa7f3d25291e9497bb2d0f76123b7de3e62cb3785c3408b3223a9cece7.jpg)
和使用命令列scrapy crawl city58_demo效果是一樣的。
![Scrapy的專案管道](https://i.iter01.com/images/a2972652257903142ff6ef0e1cc491c58a794355381f0853f1d1a08d6631a94b.jpg)
最後執行結果如圖這樣的資料。