2010-07-16 9 views
5

Ich suche nach einem Beispielcode einer SQLite-Pipeline in Scrapy. Ich weiß, dass es dafür keine Unterstützung gibt, aber ich bin mir sicher, dass es getan wurde. Nur wirklicher Code kann mir helfen, da ich nur genug Python und Scrapy kenne, um meine sehr begrenzte Aufgabe zu erledigen, und den Code als Ausgangspunkt brauche.Hat jemand Beispielcode für eine SQLite-Pipeline in Scrapy?

+0

Nicht Scrapy, die asynchron ausgeführt wird, benötigen einen nicht blockierenden Datenspeicher? In welchem ​​Fall würde SQLite nicht funktionieren? – zelusp

+0

Es scheint, dass sqlite3 schnell und intelligent genug ist, um Nebenläufigkeit (bis zu einem Punkt) zu behandeln. [Siehe hier] (http://stackoverflow.com/questions/4060772/sqlite3-concurrent-access) – zelusp

Antwort

2

Wenn Sie mit verdrillt der adbapi wohl fühlen, können Sie als Ausgangspunkt nehmen diese mysql-Pipeline: http://github.com/darkrho/scrapy-googledir-mysql/blob/master/googledir/pipelines.py

Und verwenden Sie diese Zeile am __init__:

self.dbpool = adbapi.ConnectionPool("sqlite3", database="/path/sqlite.db") 
+0

Wenn Sie sqlite3 verwenden, beachten Sie die Threading-Anforderungen, die es erfordern, dass sqlite-Objekte im selben Thread wie die Erstellung verwendet werden – Lionel

9

Ich habe so etwas wie dies:

# 
# Author: Jay Vaughan 
# 
# Pipelines for processing items returned from a scrape. 
# Dont forget to add pipeline to the ITEM_PIPELINES setting 
# See: http://doc.scrapy.org/topics/item-pipeline.html 
# 
from scrapy import log 
from pysqlite2 import dbapi2 as sqlite 

# This pipeline takes the Item and stuffs it into scrapedata.db 
class scrapeDatasqLitePipeline(object): 
    def __init__(self): 
     # Possible we should be doing this in spider_open instead, but okay 
     self.connection = sqlite.connect('./scrapedata.db') 
     self.cursor = self.connection.cursor() 
     self.cursor.execute('CREATE TABLE IF NOT EXISTS myscrapedata ' \ 
        '(id INTEGER PRIMARY KEY, url VARCHAR(80), desc VARCHAR(80))') 

    # Take the item and put it in database - do not allow duplicates 
    def process_item(self, item, spider): 
     self.cursor.execute("select * from myscrapedata where url=?", item['url']) 
     result = self.cursor.fetchone() 
     if result: 
      log.msg("Item already in database: %s" % item, level=log.DEBUG) 
     else: 
      self.cursor.execute(
       "insert into myscrapedata (url, desc) values (?, ?)", 
        (item['url'][0], item['desc'][0]) 

      self.connection.commit() 

      log.msg("Item stored : " % item, level=log.DEBUG) 
     return item 

    def handle_error(self, e): 
     log.err(e) 
1

Für alle, die versuchen, ein ähnliches Problem zu lösen, bin ich gerade auf einen netten Sqlite Item Exproter für SQLite gestoßen: https://github.com/RockyZ/Scrapy-sqlite-item-exporter.

Nachdem es zu einem Projekt-Einstellungen einschließlich, können Sie es mit verwenden:

scrapy crawl <spider name> -o sqlite.db -t sqlite 

Es ist auch als ein Element Pipeline statt Artikel Exporter verwendet werden könnte angepasst.

4

Hier ist eine sqlite-Pipeline mit sqlalchemy. Mit sqlalchemy können Sie Ihre Datenbank bei Bedarf einfach ändern.

In settings.py Add-Datenbankkonfiguration

# settings.py 
# ... 
DATABASE = { 
    'drivername': 'sqlite', 
    # 'host': 'localhost', 
    # 'port': '5432', 
    # 'username': 'YOUR_USERNAME', 
    # 'password': 'YOUR_PASSWORD', 
    'database': 'books.sqlite' 
} 

Dann in pipelines.py fügen Sie den folgenden

# pipelines.py 
import logging 

from scrapy import signals 
from sqlalchemy import Column, Integer, String, DateTime 
from sqlalchemy import create_engine 
from sqlalchemy.engine.url import URL 
from sqlalchemy.ext.declarative import declarative_base 
from sqlalchemy.orm import sessionmaker 
from sqlalchemy.pool import NullPool 

logger = logging.getLogger(__name__) 

DeclarativeBase = declarative_base() 

class Book(DeclarativeBase): 
    __tablename__ = "books" 

    id = Column(Integer, primary_key=True) 
    title = Column('title', String) 
    author = Column('author', String) 
    publisher = Column('publisher', String) 
    url = Column('url', String) 
    scrape_date = Column('scrape_date', DateTime) 

    def __repr__(self): 
     return "<Book({})>".format(self.url) 


class SqlitePipeline(object): 
    def __init__(self, settings): 
     self.database = settings.get('DATABASE') 
     self.sessions = {} 

    @classmethod 
    def from_crawler(cls, crawler): 
     pipeline = cls(crawler.settings) 
     crawler.signals.connect(pipeline.spider_opened, signals.spider_opened) 
     crawler.signals.connect(pipeline.spider_closed, signals.spider_closed) 
     return pipeline 

    def create_engine(self): 
     engine = create_engine(URL(**self.database), poolclass=NullPool, connect_args = {'charset':'utf8'}) 
     return engine 

    def create_tables(self, engine): 
     DeclarativeBase.metadata.create_all(engine, checkfirst=True) 

    def create_session(self, engine): 
     session = sessionmaker(bind=engine)() 
     return session 

    def spider_opened(self, spider): 
     engine = self.create_engine() 
     self.create_tables(engine) 
     session = self.create_session(engine) 
     self.sessions[spider] = session 

    def spider_closed(self, spider): 
     session = self.sessions.pop(spider) 
     session.close() 

    def process_item(self, item, spider): 
     session = self.sessions[spider] 
     book = Book(**item) 
     link_exists = session.query(Book).filter_by(url=item['url']).first() is not None 

     if link_exists: 
      logger.info('Item {} is in db'.format(book)) 
      return item 

     try: 
      session.add(book) 
      session.commit() 
      logger.info('Item {} stored in db'.format(book)) 
     except: 
      logger.info('Failed to add {} to db'.format(book)) 
      session.rollback() 
      raise 

     return item 

und items.py wie diese

#items.py 
import scrapy 

class BookItem(scrapy.Item): 
    title = scrapy.Field() 
    author = scrapy.Field() 
    publisher = scrapy.Field() 
    scrape_date = scrapy.Field() 

aussehen sollten Sie auch class Book bewegen kann prüfen in items.py

Verwandte Themen