Я не вижу оснований для того, чтобы делать то, что вы делаете. Вы можете изменить настройку json_filename
, установив аргументы на свой запрос scrapyd schedule.json
. Затем вы можете заставить каждого паука генерировать несколько разные файлы, которые вы объединяете с последующей обработкой или во время запроса. Вы также можете написать файлы JSON, похожие на то, что у вас есть, только установив значение FEED_URI
(example). Если вы одновременно пишете один файл из нескольких процессов (особенно когда вы открываете режим 'wb'
), вы ищете поврежденные данные.
Edit:
Поняв немного лучше, что вам нужно - в этом случае - это scrapyd начиная множественным ползает под управлением различных пауков, где каждый один ползет другой веб-сайт. Потребительский процесс постоянно контролирует один файл.
Есть несколько решений, в том числе:
Относительно легко реализовать и хорошо для очень маленьких предметов только (see here)
- RabbitMQ или каким-либо другой очередями механизма
Отличное решение, но может быть немного переполненным
- База данных, например. SQLite решение на основе
Хороший и простой, но, вероятно, требует кодирования (выборочная потребителя)
- Хороший
inotifywait
основанное или другое решение для мониторинга файловой системы
Ницца и, вероятно, легко реализовать
Последний кажется мне самым привлекательным вариантом. Когда scrapy crawl
заканчивает (spider_closed signal), переместите, скопируйте или создайте ссылку на файл FEED_URL
в каталог, который вы контролируете с помощью сценария, такого как this. mv
или ln
- это атомная операция unix, поэтому вы должны быть в порядке. Возьмите скрипт, чтобы добавить новый файл в файл tmp
, который вы подаете один раз в свою потребительскую программу.
Используя этот способ, вы используете экспортеры фида по умолчанию для записи ваших файлов. Конечное решение настолько просто, что вам не нужен конвейер. Простое расширение должно соответствовать счету.
На extensions.py
в том же каталоге, settings.py
:
from scrapy import signals
from scrapy.exceptions import NotConfigured
class MoveFileOnCloseExtension(object):
def __init__(self, feed_uri):
self.feed_uri = feed_uri
@classmethod
def from_crawler(cls, crawler):
# instantiate the extension object
feed_uri = crawler.settings.get('FEED_URI')
ext = cls(feed_uri)
crawler.signals.connect(ext.spider_closed, signal=signals.spider_closed)
# return the extension object
return ext
def spider_closed(self, spider):
# Move the file to the proper location
# os.rename(self.feed_uri, ... destination path...)
На ваш settings.py
:
EXTENSIONS = {
'myproject.extensions.MoveFileOnCloseExtension': 500,
}
Спасибо за ваш ответ. Я думаю, что я плохо разбираюсь в том, как работают трубопроводы. По моему мнению, пауки генерируют элементы, элементы всех пауков передаются в конвейер, который является глобальным для всех из них и обрабатывает их. Из вашего ответа я предполагаю, что у каждого паука в некотором смысле есть собственный конвейер, и есть несколько конвейеров, работающих с одним и тем же файлом, и это вызывает проблемы. Я прав? , Я делаю это таким образом, потому что есть другой процесс, который делает некоторые вещи с содержимым и принимает только один файл. – silvestrelosada
Фразы не на 100% точны, но то, что вы говорите, правильно. Более конкретно scrapyd проводит несколько процессов скрининга параллельно. Каждый процесс скрининга запускает паук и ваш конвейер. Это означает, что при выполнении этого обхода вы откроете тот же файл для записи из многих процессов, которые приведут к коррупции. «... только принимает один файл». Я уверен, что есть лучший способ сделать это. Можете ли вы запустить scrapyd, получить, например, 100 файлов из него, [concat их к одному] (http://stackoverflow.com/questions/4969641/append-one-file-to-another-in-linux), а затем передать это вашему процессу? Это более распространено. – neverlastn
Знаете ли вы некоторую возможность поместить результат (предметы) всех пауков в один и тот же файл, используя только лоскутное? Спасибо – silvestrelosada