我正在研究scrapy并抓取一个网站并获取所有信息
实际上我有3个不同数据的蜘蛛,我在同一个文件夹中创建了这3个蜘蛛 具有以下结构
scrapy.cfg
myproject/
__init__.py
items.py
pipelines.py
settings.py
spiders/
__init__.py
spider1.py
spider2.py
spider3.py
现在,当我们运行该特定蜘蛛时,我需要通过具有该蜘蛛名称的管道创建一个csv文件,例如
spider1.csv,spider2.csv,spider3.csv and so on
(蜘蛛不受限制,可能更多)>根据蜘蛛和蜘蛛名称的数量,我想创建csv文件
这里我们是否可以在pipeline.py中创建多个管道?如果存在多个蜘蛛,还如何动态创建带有蜘蛛名称的csv文件
这里我有3只蜘蛛,我想一次运行所有3只蜘蛛(使用报废),当我运行所有3只蜘蛛时,应创建3个带有蜘蛛名称的csv文件。 我想安排这个蜘蛛每6个小时运行一次。 如果我的解释出现问题,请纠正我并让我知道如何实现这一目标。
提前致谢
已编辑的代码: 例如,我只为spider1.py
粘贴我的代码spider1.py中的代码:
class firstspider(BaseSpider):
name = "spider1"
domain_name = "www.example.com"
start_urls = [
"www.example.com/headers/page-value"
]
def parse(self, response):
hxs = HtmlXPathSelector(response)
........
.......
item = Spider1Item()
item['field1'] = some_result
item['field2'] = some_result
.....
.....
return item
Pipeline.py代码:
import csv
from csv import DictWriter
class firstspider_pipeline(object):
def __init__(self):
self.brandCategoryCsv = csv.writer(open('../%s.csv' % (spider.name), 'wb'),
delimiter=',', quoting=csv.QUOTE_MINIMAL)
self.brandCategoryCsv.writerow(['field1', 'field2','field3','field4'])
def process_item(self, item, spider):
self.brandCategoryCsv.writerow([item['field1'],
item['field2'],
item['field3'],
item['field4'])
return item
正如我之前所说,当我用蜘蛛名运行上面的蜘蛛时,将动态创建一个带有蜘蛛名称的csv文件.....
但现在如果我运行剩余的蜘蛛如spider2,spider3,spider3
,那么应该生成带有相应蜘蛛名称的csv文件。
上述代码是否足以满足上述功能?
我们是否需要创建另一个管道类来创建另一个csv文件?(是否可以在一个pipeline.py文件中创建多个管道类?)
如果我们在单个pipeline.py文件中创建多个管道类,如何将特定的spider与其相关的管道类匹配
我希望在保存到数据库时实现相同的功能,我的意思是当我运行spider1时,spider1的所有数据都应该保存到数据库中,并将其保存到具有相对蜘蛛名称的表中。 这里针对每个蜘蛛我有不同的sql查询(因此需要编写不同的管道类)
对不起,如果我在任何地方都错了,我希望它能得到很好的解释,如果没有,请告诉我。
答案 0 :(得分:3)
您通常走在正确的轨道上。
但我可以立即指出一些观点:
你可能不需要(=不应该使用)一个班级! Python不是Java。如果你的类只包含2个方法,而第一个是__init__
- 方法,你几乎肯定不需要一个类,但函数会很好。减少杂乱=更好的代码!
SO不适合进行常规代码审核。请尝试使用codereview。 SO-useres是一个友好的(大多数)和有用的人,但他们不喜欢编写你的代码。他们喜欢解释,建议和纠正。 因此,尝试实施您的应用程序,如果您遇到麻烦,您无法解决自己,请再次回来并寻求建议。如上所述,您在概念上走上正轨,只是尝试实现它。
你似乎对课堂概念有误解。至少只要它是python-classes:
就我所见,您不需要BaseSpider类。基类和子类之间有什么区别?派生类不会使你的程序成为OO,或者更好,或者其他什么。搜索Liskovs principle以便大致了解子类何时适合python。 (这有点像反向逻辑,但它是了解你是否应该继承或改变你的方法的最快方法之一。)
在类声明之后立即声明的python类变量与在__init__
方法中初始化的实例变量之间存在明显差异。类变量在类的所有实例之间是 SHARED ,其中实例变量对于各个实例是私有的。你几乎从不想使用类变量,这是一个 Singleton-Pattern ,你想在大多数情况下避免使用它,因为它会导致调试中的麻烦和不满。
因此我会修改你的Spider
- 类,如:
class Spider(object):
def __init__(self, name, url=None):
self.name = name
self.domain_name = url
self.start_urls = [url]
...
crawlers = [Spider('spider %s' %i) for i in xrange(4)] #creates a list of 4 spiders
但也许您正在使用声明式元类方法,但我无法从您发布的代码中看到它。
如果您想并行运行抓取工具,则应考虑threading
- 模块。它适用于与multiprocessing
- 模块相对的连续I / O操作,用于并行计算。
你的概念正好在正确的轨道上。将项目分成小块,每次遇到错误都会返回。
只是不要指望在以下问题上得到完整答案:“我不想重新创建Google,我怎样才能以最好的方式和最短的时间来做到这一点!” ; - )