Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/amazon-s3/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 当一个新文件到达S3时,触发luigi任务_Python_Amazon S3_Scrapy_Luigi - Fatal编程技术网

Python 当一个新文件到达S3时,触发luigi任务

Python 当一个新文件到达S3时,触发luigi任务,python,amazon-s3,scrapy,luigi,Python,Amazon S3,Scrapy,Luigi,我有一个水桶,里面有根据创建时间随机添加的键。例如: 's3://my-bucket/mass/%s/%s/%s/%s/%s_%s.csv' % (time.strftime('%Y'), time.strftime('%m'), time.strftime('%d'), time.strftime('%H'), name, the_time) 事实上,这些都是爬行的产物。我想触发一个任务,将这些爬网与我拥有的master.csv产品目录文件(称为“product_catalog.csv”)相

我有一个水桶,里面有根据创建时间随机添加的键。例如:

's3://my-bucket/mass/%s/%s/%s/%s/%s_%s.csv' % (time.strftime('%Y'), time.strftime('%m'), time.strftime('%d'), time.strftime('%H'), name, the_time)
事实上,这些都是爬行的产物。我想触发一个任务,将这些爬网与我拥有的master.csv产品目录文件(称为“product_catalog.csv”)相匹配,该文件也会定期更新

现在,我编写了几个Python脚本,其中包含了全局变量,每次运行这个过程时都会填充这些变量。这些需要成为导入的属性

因此,需要做的是:

1) 新的csv文件显示在“s3://my bucket/mass/…”中,并根据爬网完成的时间使用唯一的密钥名。路易吉看到了这一点,开始了。
2) luigi在新文件上运行“cleaning.py”,因此需要在运行时向其提供“cleaning.py”(在S3中显示的文件)的参数。结果除了被传递到下一步之外,还保存在S3中
3) “product_catalog.csv”的最新版本从数据库中提取,并使用“matching.py”中的“cleaning.py”结果

我意识到这可能没有完全意义。我将提供必要的编辑,使其更加清晰

编辑

根据最初的回答,我已经将其配置为一个pull操作,可以在过程中节省步骤。但现在我迷路了。应该注意的是,这是我第一次将Python项目捆绑在一起,因此在这样做的过程中,我正在学习包括init.py之类的内容。和往常一样,这是一条坎坷的道路,成功带来了兴奋,紧接着是下一个障碍带来的困惑

以下是我的问题:
1) 我不清楚如何从Scrapy进口蜘蛛。我有十几个,目标是让luigi为所有人管理爬网>清理>匹配的过程。粗略的文档说明包括:

class MySpider(scrapy.Spider):
    # Your spider definition
这是什么意思?在控制蜘蛛的脚本中重新编写蜘蛛?这毫无意义,他们的例子也没有帮助

2) 我已经将Scrapy管道配置为导出到S3,但luigi似乎也通过output()实现了这一点。我应该使用哪一种,如何让他们一起玩

3) Luigi说CrawlTask()运行成功,但这是错误的,因为它在几秒钟内完成,爬行通常需要几分钟。也没有与成功对应的输出文件

4) 我在哪里提供S3的凭据

这是我的密码。我已经评论了一些不起作用的东西,而不是我认为更好的东西。但我的感觉是,我想做的事情有一个宏伟的架构,我只是还不明白

import luigi
from luigi.s3 import S3Target, S3Client
import my_matching
from datetime import datetime
import os
import scrapy
from twisted.internet import reactor
from scrapy.crawler import CrawlerProcess
from scrapy.utils.project import get_project_settings
from my_crawlers.my_crawlers.spiders import my_spider

class CrawlTask(luigi.Task):
    crawltime = datetime.now()
    spider = luigi.Parameter()
    #vertical = luigi.Parameter()

    def requires(self):
        pass

    def output(self):
        return luigi.LocalTarget("actual_data_staging/crawl_luigi_test_{}.csv".format(self.crawltime))
        #return S3Target("s3://my-bucket/mass/crawl_luigi_test_{}.csv".format(self.crawltime))

    def run(self):
        os.system("scrapy crawl %s" % self.spider)
        #process = CrawlerProcess(get_project_settings())
        #process.crawl("%s" % self.spider)
        #process.start()

class FetchPC(luigi.Task):
    vertical = luigi.Parameter()

    def output(self):
        if self.vertical == "product1":
            return "actual_data_staging/product1_catalog.csv"
        elif self.vertical == "product2":
            return "actual_data_staging/product2_catalog.csv"

class MatchTask(luigi.Task):
    crawltime = CrawlTask.crawltime
    vertical = luigi.Parameter()
    spider = luigi.Parameter()

    def requires(self):
        return CrawlTask(spider=self.spider)
        return FetchPC(vertical=self.vertical)

    def output(self):
        return luigi.LocalTarget("actual_data_staging/crawl_luigi_test_matched_{}.csv".format(self.crawltime))
        #return S3Target("s3://my-bucket/mass/crawl_luigi_test_matched_{}.csv".format(CrawlTask.crawltime))

    def run(self):
        if self.vertical == 'product1':
            switch_board(requires.CrawlTask(), requires.FetchPC())
MatchTask引用了我编写的一个python脚本,该脚本将刮取的产品与我的产品目录进行比较。看起来是这样的:

def create_search(value):
...
def clean_column(column):
...
def color_false_positive():
...
def switch_board(scrape, product_catalog):
# this function coordinates the whole script

您可以做的是创建一个更大的系统来封装爬网和处理。这样,您就不必检查s3中的新对象。我以前没有用过luigi,但也许你可以把你的零碎工作变成一个任务,完成后再做你的处理任务。无论如何,我不认为“检查”s3的新内容是一个好主意,因为1。您将不得不使用大量的API调用,以及2。您将需要编写一系列代码来检查某些东西是否是“新的”,这可能会让人感到毛骨悚然。

下面是一个非常粗略的轮廓,说明它的外观。关于luigi作为拉式系统的工作,我认为与您的大纲的主要区别在于,您首先指定您想要的输出,然后触发该输出所依赖的其他任务。因此,与其用爬行结束的时间来命名,不如用你一开始就知道的东西来命名。有可能用另一种方法来做,只是有很多不必要的复杂性

class CrawlTask(luigi.Task):
    crawltime = luigi.DateParameter()

    def requires(self):
        pass

    def get_filename(self):
        return "s3://my-bucket/crawl_{}.csv".format(self.crawltime)

    def output(self):
        return S3Target(self.get_filename())

    def run(self):
        perform_crawl(s3_filename=self.get_filename())


class CleanTask(luigi.Task):
    crawltime = luigi.DateParameter()

    def requires(self):
        return CrawlTask(crawltime=self.crawltime)

    def get_filename(self):
        return "s3://my-bucket/clean_crawl_{}.csv".format(self.crawltime)

    def output(self):
        return S3Target(self.get_filename())

    def run(self):
        perform_clean(input_file=self.input().path, output_filename=self.get_filename())


class MatchTask(luigi.Task):
    crawltime = luigi.DateParameter()

    def requires(self):
        return CleanTask(crawltime=self.crawltime)

    def output(self):
        return ##?? whatever output of this task is

    def run(self):
        perform_match(input_file=self.input().path)

对于这个更大的系统,您有什么建议?所有的东西都是用Python编写的,如果有帮助的话,我正在将它们打包到Docker容器中。你不能使用Luigi任务吗?将数据管道中的每个步骤作为一项任务来实施,并根据需要启动任务。我以前从未用过Luigi——我用芹菜做这个东西,但它也是一个定义和实现任务的系统。至于使用docker,您应该仍然能够使用docker完成所有这一切,但您可能需要使用docker网络,并正确配置容器。容器是动态分配的IP,因此您可能需要某种方法来执行“服务发现”以查找IP。我确信docker有内置的工具来做这件事。我能让scrapy把信号作为任务发送给luigi吗。需要包含scrapy创建的s3密钥的对象吗?然后luigi就可以从s3中检索到密钥。这似乎很愚蠢,但我如何让Python代码片段(crawler和luigi)彼此对话并传递信息呢?再说一遍,我以前从未使用过luigi。如果将scrapy crawler实现为一个任务,您是否能够从该任务返回一条消息,然后启动一个新任务?通过查看文档,我看到了实现此功能的两个可能的候选者
Task.output
以及
@luigi.Task.event_handler
decorator。因此,更好的思考方式是我希望每4小时完成一次最终结果,这将导致luigi触发交付结果的所有需求,而不是每4小时安排一次爬网,并在爬网完成后触发其他进程?那么,我应该在哪里引入实际执行此工作的matching.py和cleaning.py脚本呢?我如何将luigi正在处理的变量(如每个步骤的结果)输入matching.py?本质上,这些不同的.py脚本应该以.csv文件的形式相互传递数据帧,这些文件使用read_csvOh导入,我在其中放置
perform_clean
perform_match
等。我假设您会导入这些脚本,而这些脚本是假的