[英]When a new file arrives in S3, trigger luigi task
我有一个带有新对象的存储桶,其中会根据它们的创建时间随机添加键。 例如:
'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)
实际上,这些是Scrapy爬网的输出。 我想触发一个将这些爬网与我拥有的主.csv产品目录文件(称为“ product_catalog.csv”)匹配的任务,该文件也会定期更新。
现在,我有一些用全局变量编写的Python脚本,每次运行此过程时都会填写这些变量。 这些需要成为导入的属性。
所以这是需要发生的事情:
1)新的csv文件会根据抓取完成的时间显示在“ s3:// my-bucket / mass / ...”中,并具有唯一的键名称。 路易吉(Luigi)看到了这一点,开始了。
2)luigi在新文件上运行“ cleaning.py”,因此需要在运行时向其提供“ cleaning.py”(在S3中显示的文件)参数。 除了传递到下一步之外,结果还保存在S3中。
3)从数据库中获取“ product_catalog.csv”的最新版本,并使用“ matching.py”中的“ cleaning.py”结果
我意识到这可能并不完整。 我将根据需要提供编辑内容,以使其更加清晰。
编辑
根据最初的答案,我将其配置为拉操作,从而节省了执行过程中的步骤。 但是现在我很迷茫。 应该注意的是,这是我第一次将Python项目绑定在一起,因此我在学习诸如init .py之类的东西时会学习到。 与往常一样,成功是一条坎from的激动之路,紧接着又是下一个障碍。
这是我的问题:
1)我不清楚如何从Scrapy导入蜘蛛。 我大约有十二个,目标是让luigi管理所有这些对象的crawl> clean> match的过程。 Scrapy文档说包括:
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
下面是它看起来的非常粗略的轮廓。 我认为与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)
您可以做的是创建一个同时包含爬网和处理功能的大型系统。 这样,您就不必检查s3中是否有新对象。 我以前没有使用过luigi,但是也许您可以将您的拼凑工作变成一项任务,完成后再执行您的处理任务。 无论如何,我认为“检查” s3中的新内容不是一个好主意,因为1.您将不得不使用大量API调用,并且2.您将需要编写一堆代码来检查是否有“新内容”还是不可以,这可能会变得毛茸茸。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.