1. 程式人生 > >scrapy爬取資料儲存csv、mysql、mongodb、json

scrapy爬取資料儲存csv、mysql、mongodb、json

目錄

  • 前言

  • Items

  • Pipelines

前言

用Scrapy進行資料的儲存進行一個常用的方法進行解析

Items

item 是我們儲存資料的容器,其類似於 python 中的字典。使用 item 的好處在於: Item 提供了額外保護機制來避免拼寫錯誤導致的未定義欄位錯誤。且看栗子:

import scrapy
class Doubantop250Item(scrapy.Item):
    title = scrapy.Field()  # 電影名字
    star = scrapy.Field()  # 電影評分
quote = scrapy.Field() # 膾炙人口的一句話 movieInfo = scrapy.Field() # 電影的描述資訊,包括導演、主演、電影型別
View Code
 

Pipelines

pipelines.py 一般我們用於儲存資料,其方法的一些介紹如下圖。下面,我會分多種方式來儲存我們的資料,避免你耍流氓。

 

 

儲存到 Json

import json
class JsonPipeline(object):
    file_name = base_dir + '
/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
View Code

 

 

 

儲存到 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 item
View 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,
}