scrapy爬取資料儲存csv、mysql、mongodb、json
阿新 • • 發佈:2019-01-14
目錄
-
前言
-
Items
-
Pipelines
前言
用Scrapy進行資料的儲存進行一個常用的方法進行解析
Items
item 是我們儲存資料的容器,其類似於 python 中的字典。使用 item 的好處在於: Item 提供了額外保護機制來避免拼寫錯誤導致的未定義欄位錯誤。且看栗子:
import scrapy class Doubantop250Item(scrapy.Item): title = scrapy.Field() # 電影名字 star = scrapy.Field() # 電影評分View Codequote = scrapy.Field() # 膾炙人口的一句話 movieInfo = scrapy.Field() # 電影的描述資訊,包括導演、主演、電影型別
Pipelines
pipelines.py 一般我們用於儲存資料,其方法的一些介紹如下圖。下面,我會分多種方式來儲存我們的資料,避免你耍流氓。
儲存到 Json
import json class JsonPipeline(object): file_name = base_dir + 'View Code/doubanTop250/data.json' # json 檔案路徑 def process_item(self, item, spider): file = open(self.file_name, 'r', encoding='utf-8') load_data = json.load(file) load_data.append({"title": item["title"].strip()}) # 追加資料 file = open(self.file_name, 'w', encoding='utf-8') json.dump(load_data, file, ensure_ascii=False) # 儲存資料 file.close() return item
儲存到 CSV
def appendDta2Csv(self, file_name, new_headers, new_data): with open(file_name,'r') as f: f_csv = csv.reader(f) try:# 如何有原始檔沒有 headers ,將呼叫傳進來的 headers headers = next(f_csv) except: headers = new_headers old_data = list(f_csv) old_data.append(new_data) # 追加新的資料 with open(file_name, 'w') as f2:# 儲存資料 f_csv = csv.writer(f2) f_csv.writerow(headers) f_csv.writerows(old_data) f2.close() f.close() def process_item(self, item, spider): self.appendDta2Csv(self.file_name, ["title"], [item["title"].strip()]) return itemView Code
儲存到 MongoDB
from pymongo import MongoClient import os base_dir = os.getcwd() class MongoPipeline(object): # 實現儲存到mongo資料庫的類, collection = 'douban' # mongo 資料庫的 collection 名字 def __init__(self, mongo_uri, db_name, db_user, db_pass): self.mongo_uri = mongo_uri self.db_name = db_name self.db_user = db_user self.db_pass = db_pass @classmethod def from_crawler(cls, crawler): # scrapy 為我們訪問settings提供了這樣的一個方法,這裡, # 我們需要從 settings.py 檔案中,取得資料庫的URI和資料庫名稱 return cls( mongo_uri=crawler.settings.get('MONGO_URI'), db_name=crawler.settings.get('DB_NAME'), db_user=crawler.settings.get('DB_USER'), db_pass=crawler.settings.get('DB_PASS')) def open_spider(self, spider): # 爬蟲啟動時呼叫,連線到資料庫 self.client = MongoClient(self.mongo_uri) self.zfdb = self.client[self.db_name] self.zfdb.authenticate(self.db_user, self.db_pass) def close_spider(self, spider): # 爬蟲關閉時呼叫,關閉資料庫連線 self.client.close() def process_item(self, item, spider): self.zfdb[self.collection].insert({"title": item["title"].strip()}) return item
儲存到 MySQL
from sqlalchemy import create_engine, Column, Integer, String, BIGINT, ForeignKey, UniqueConstraint, Index, and_, \ or_, inspect from sqlalchemy.orm import sessionmaker, relationship, contains_eager class MysqlPipeline(object): MYSQL_URI = 'mysql+pymysql://username:[email protected]:3306/db_name' # echo 為 True 將會輸出 SQL 原生語句 engine = create_engine(MYSQL_URI, echo=True) from sqlalchemy.ext.declarative import declarative_base Base = declarative_base() # 建立單表 class Movie(Base): __tablename__ = 'movies' id = Column(BIGINT, primary_key=True, autoincrement=True) title = Column(String(200)) # 初始化資料庫 def init_db(self): self.Base.metadata.create_all(self.engine) # 刪除資料庫 def drop_db(self): self.Base.metadata.drop_all(self.engine) def open_spider(self, spider): # 爬蟲啟動時呼叫,連線到資料庫 self.init_db() Session = sessionmaker(bind=self.engine) self.session = Session() def process_item(self, item, spider): new_movie = self.Movie(title=item["title"].strip()) self.session.add(new_movie) self.session.commit() return item
在寫好相關的 pipeline 之後,需要在 settings.py 中啟用相關的 pipeline,後面的數字為呼叫的優先順序,數字是0-1000,你可以自定義。你可以所有格式都儲存,也可以註釋掉其他,值保留一個。
ITEM_PIPELINES = { 'doubanTop250.pipelines.MongoPipeline': 300, 'doubanTop250.pipelines.MysqlPipeline': 301, 'doubanTop250.pipelines.CsvPipeline': 302, 'doubanTop250.pipelines.JsonPipeline': 303, }