2010-07-16 33 views
5

Tôi đang tìm một số mã ví dụ về một đường dẫn SQLite trong Scrapy. Tôi biết không có hỗ trợ xây dựng cho nó, nhưng tôi chắc chắn nó đã được thực hiện. Chỉ có mã thực tế mới có thể giúp tôi, vì tôi chỉ biết đủ Python và Scrapy để hoàn thành nhiệm vụ rất hạn chế của tôi, và cần mã như là một điểm khởi đầu.Có ai có mã ví dụ cho một đường ống dẫn sqlite trong Scrapy không?

+0

Không phải là Scrapy, chạy không đồng bộ, yêu cầu kho dữ liệu không chặn? Trong trường hợp đó SQLite sẽ không hoạt động? – zelusp

+0

Có vẻ như sqlite3 nhanh và đủ thông minh để xử lý đồng thời (lên đến một điểm). [Xem tại đây] (http://stackoverflow.com/questions/4060772/sqlite3-concurrent-access) – zelusp

Trả lời

2

Nếu bạn cảm thấy thoải mái với adbapi xoắn, bạn có thể mất điểm khởi đầu đường ống mysql này: http://github.com/darkrho/scrapy-googledir-mysql/blob/master/googledir/pipelines.py

Và sử dụng dòng này tại __init__:

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

Nếu bạn sử dụng sqlite3, hãy lưu ý các yêu cầu luồng yêu cầu các đối tượng sqlite được sử dụng trong cùng một luồng như tạo – Lionel

9

tôi đã làm một cái gì đó như thế này:

# 
# 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

Đối với bất kỳ ai đang cố gắng giải quyết một vấn đề tương tự, tôi chỉ gặp một Exproter mục Sqlite tốt đẹp cho SQLite: https://github.com/RockyZ/Scrapy-sqlite-item-exporter.

Sau đó nó để thiết lập dự án, bạn có thể sử dụng nó với:

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

Nó cũng có thể được điều chỉnh để được sử dụng như một mục đường ống thay vì khoản xuất khẩu.

4

Dưới đây là một đường ống dẫn sqlite với sqlalchemy. Với sqlalchemy bạn có thể dễ dàng thay đổi cơ sở dữ liệu của bạn nếu cần thiết.

Trong cấu hình cơ sở dữ liệu settings.py add

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

Sau đó, trong pipelines.py thêm dòng sau

# 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 

items.py sẽ trông như thế này

#items.py 
import scrapy 

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

Bạn cũng có thể xem xét để di chuyển class Book vào items.py

Các vấn đề liên quan