Вот как я сделал это, вы можете сделать это в промежуточном программном обеспечении следующим образом:
## MiddleWare
class DBMiddleware(object):
def __init__(self, db_settings):
self.db_setting = db_settings
@classmethod
def from_crawler(cls, crawler):
db_settings = crawler.settings.getdict("DB_SETTINGS")
if not db_settings: # if we don't define db config in settings
raise NotConfigured
s = cls(db_settings)
crawler.signals.connect(s.spider_opened, signal=signals.spider_opened)
crawler.signals.connect(s.spider_closed, signal=signals.spider_closed)
return s
def spider_opened(self, spider):
spider.connection = psycopg2.connect(database=self.db_setting['database'],
user=self.db_setting['user'],
password=self.db_setting['password'],
host=self.db_setting['host'],
port=self.db_setting['port'])
def spider_closed(self, spider):
spider.connection.close()
, затем вы можете добавить это к пауку, чтобы получить доступ к только что созданному соединению
## Spider
class MainSpider(scrapy.Spider):
name = 'main_spider'
start_urls = ['www.example.com']
def __init__(self):
pass
@classmethod
def from_crawler(cls, crawler):
s = cls()
crawler.signals.connect(s.spider_opened, signal=signals.spider_opened)
crawler.signals.connect(s.spider_closed, signal=signals.spider_closed)
return s
def spider_opened(self, spider):
pass
def parse(self, response):
cursor = self.connection.cursor()
sql = "SELECT * FROM companies"
cursor.execute(sql)
result = cursor.fetchall()
for element in result:
loader = ItemLoader(item=Item_profile(), selector=element)
loader.add_value('name', element[0])
items = loader.load_item()
yield items
def spider_closed(self, spider):
pass
это работает нормально, если вы просто хотите иметь доступ к соединению БД в методе spider pars, но мне нужно было открыть соединение до метода разбора, чтобы я мог получать ссылки из БД и crwal каждый из них по отдельности, поэтому мне нужно было соединение в методе ## Spider spider_opened (), но последовательность активации методов выглядит следующим образом:
1: #Spider __init__()
2: #Spider spider_opened()
3: #Middleware spider_opened() -->> connection is created here
4: #Spider parse()
5: #Spider spider_closed()
6: #Middleware spider_closed()
, и это логично, поскольку согласно документации Основная функция Промежуточного программного обеспечения заключается в том, чтобы сидеть между двигателем и пауком, нам нужен модуль, который создается при запуске scrap, и это будет Extension . Поэтому я создал файл с именем extentions.py
в каталоге root вместе с промежуточным программным обеспечением, конвейерами и т. Д. c. и добавил тот же код, что и в промежуточном программном обеспечении:
from scrapy import signals
from scrapy.exceptions import NotConfigured
import psycopg2
class DBExtension(object):
def __init__(self, db_settings):
self.db_setting = db_settings
pass
@classmethod
def from_crawler(cls, crawler):
db_settings = crawler.settings.getdict("DB_SETTINGS")
if not db_settings:
raise NotConfigured
s = cls(db_settings)
crawler.signals.connect(s.spider_opened, signal=signals.spider_opened)
crawler.signals.connect(s.spider_closed, signal=signals.spider_closed)
return (s)
def spider_opened(self, spider):
spider.connection = psycopg2.connect(database=self.db_setting['database'],
user=self.db_setting['user'],
password=self.db_setting['password'],
host=self.db_setting['host'],
port=self.db_setting['port'])
def spider_closed(self, spider):
spider.connection.close()
, затем я активировал это расширение в settings.py
EXTENSIONS = {
'ProjectName.extensions.DBExtension': 400
}
, и теперь у вас есть доступ к этому соединению в # Spider spider_opened () с self.connection
и может загружать информацию из базы данных до начала сканирования. Я не знаю, есть ли более оптимальный способ обойти это, но сейчас это сработает для меня.