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?
Trả lời
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")
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
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)
Đố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.
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
và 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
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
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