我有一个带有新对象的存储桶,可以根据创建时间随机添加关键字。例如:
'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/..."根据爬网完成的时间使用唯一的密钥名称。路易吉看到了这一点并开始了。
2)" cleaning.py"由luigi在新文件上运行,因此" cleaning.py"的参数(在S3中显示的文件)需要在运行时提供给它。除了传递给下一步之外,结果将保存在S3中。
3)" product_catalog.csv"的最新版本从数据库中提取并使用" cleaning.py"的结果。 in" matching.py"
我意识到这可能没有完全意义。我将根据需要提供编辑,以使其更加清晰。
修改
根据初步答案,我已将此配置为拉动操作,可保存整个过程中的步骤。但现在我很迷茫。应该注意的是,这是我第一次将Python项目捆绑在一起,因此有些事情包括我正在学习的 init .py。像往常一样,在下一个障碍之后立即出现混乱,这是一条令人兴奋的坎坷之路。
以下是我的问题:
1)如何从Scrapy导入蜘蛛我不清楚。我有大约十几个,目标是让luigi管理抓取过程> clean>匹配所有这些。 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
答案 0 :(得分:1)
下面是一个非常粗略的概述。我认为关于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)
答案 1 :(得分:0)
您可以做的是创建一个更大的系统,封装您的抓取和处理。这样您就不必检查s3是否有新对象。我之前没有使用过luigi,但也许你可以将你的scrapy工作变成一项任务,并且当它完成后你会完成你的处理任务。无论如何,我不会想到'检查' s3对于新东西是一个好主意,因为1.你将不得不使用大量的API调用,以及2.你需要编写一堆代码来检查某些东西是否是新的'或不,这可能会变得多毛。