[英]the order of Scrapy Crawling URLs with long start_urls list and urls yiels from spider
[英]Separate output file for every url given in start_urls list of spider in scrapy
我想为我在蜘蛛的 start_urls 中设置的每个 url 创建单独的输出文件,或者想以某种方式拆分输出文件开始 url 明智的。
以下是我的蜘蛛的 start_urls
start_urls = ['http://www.dmoz.org/Arts/', 'http://www.dmoz.org/Business/', 'http://www.dmoz.org/Computers/']
我想创建单独的输出文件,如
艺术.xml
业务.xml
计算机.xml
我不知道如何做到这一点。 我正在考虑通过在项目管道类的 spider_opened 方法中实现一些类似的东西来实现这一点,
import re
from scrapy import signals
from scrapy.contrib.exporter import XmlItemExporter
class CleanDataPipeline(object):
def __init__(self):
self.cnt = 0
self.filename = ''
@classmethod
def from_crawler(cls, crawler):
pipeline = cls()
crawler.signals.connect(pipeline.spider_opened, signals.spider_opened)
crawler.signals.connect(pipeline.spider_closed, signals.spider_closed)
return pipeline
def spider_opened(self, spider):
referer_url = response.request.headers.get('referer', None)
if referer_url in spider.start_urls:
catname = re.search(r'/(.*)$', referer_url, re.I)
self.filename = catname.group(1)
file = open('output/' + str(self.cnt) + '_' + self.filename + '.xml', 'w+b')
self.exporter = XmlItemExporter(file)
self.exporter.start_exporting()
def spider_closed(self, spider):
self.exporter.finish_exporting()
#file.close()
def process_item(self, item, spider):
self.cnt = self.cnt + 1
self.spider_closed(spider)
self.spider_opened(spider)
self.exporter.export_item(item)
return item
我试图在 start_urls 列表中找到每个抓取项目的引用 URL。 如果在 start_urls 中找到引用 url,则将使用该引用 url 创建文件名。 但问题是如何访问 spider_opened() 方法中的响应对象。 如果我可以在那里访问它,我可以基于它创建文件。
任何帮助找到执行此操作的方法? 提前致谢!
[编辑]
通过如下更改我的管道代码解决了我的问题。
import re
from scrapy import signals
from scrapy.contrib.exporter import XmlItemExporter
class CleanDataPipeline(object):
def __init__(self):
self.filename = ''
self.exporters = {}
@classmethod
def from_crawler(cls, crawler):
pipeline = cls()
crawler.signals.connect(pipeline.spider_opened, signals.spider_opened)
crawler.signals.connect(pipeline.spider_closed, signals.spider_closed)
return pipeline
def spider_opened(self, spider, fileName = 'default.xml'):
self.filename = fileName
file = open('output/' + self.filename, 'w+b')
exporter = XmlItemExporter(file)
exporter.start_exporting()
self.exporters[fileName] = exporter
def spider_closed(self, spider):
for exporter in self.exporters.itervalues():
exporter.finish_exporting()
def process_item(self, item, spider):
fname = 'default'
catname = re.search(r'http://www.dmoz.org/(.*?)/', str(item['start_url']), re.I)
if catname:
fname = catname.group(1)
self.curFileName = fname + '.xml'
if self.filename == 'default.xml':
if os.path.isfile('output/' + self.filename):
os.rename('output/' + self.filename, 'output/' + self.curFileName)
exporter = self.exporters['default.xml']
del self.exporters['default.xml']
self.exporters[self.curFileName] = exporter
self.filename = self.curFileName
if self.filename != self.curFileName and not self.exporters.get(self.curFileName):
self.spider_opened(spider, self.curFileName)
self.exporters[self.curFileName].export_item(item)
return item
还在蜘蛛中实现了make_requests_from_url
来为每个项目设置 start_url。
def make_requests_from_url(self, url):
request = Request(url, dont_filter=True)
request.meta['start_url'] = url
return request
我会实施更明确的方法(未测试):
在settings.py
配置可能的类别列表:
CATEGORIES = ['Arts', 'Business', 'Computers']
根据设置定义你的start_urls
start_urls = ['http://www.dmoz.org/%s' % category for category in settings.CATEGORIES]
将category
Field
添加到Item
类
在蜘蛛的 parse 方法中,根据当前的response.url
设置category
字段,例如:
def parse(self, response): ... item['category'] = next(category for category in settings.CATEGORIES if category in response.url) ...
在管道中打开所有类别的出口商,并根据item['category']
选择要使用的出口商:
def spider_opened(self, spider): ... self.exporters = {} for category in settings.CATEGORIES: file = open('output/%s.xml' % category, 'w+b') exporter = XmlItemExporter(file) exporter.start_exporting() self.exporters[category] = exporter def spider_closed(self, spider): for exporter in self.exporters.itervalues(): exporter.finish_exporting() def process_item(self, item, spider): self.exporters[item['category']].export_item(item) return item
您可能需要稍微调整一下以使其正常工作,但我希望您明白 - 将类别存储在正在处理的item
中。 根据项目类别值选择要导出到的文件。
希望有帮助。
只要不将其存储在项目本身中,您就无法真正知道凝视 url。 以下解决方案应该适合您:
重新定义make_request_from_url
以随您发出的每个Request
发送起始 url。 您可以将其存储在您的Request
meta
属性中。 使用以下每个Request
绕过此起始 url。
一旦您决定将元素传递给管道,请从response.meta['start_url']
填写该项目的起始 url
希望能帮助到你。 以下链接可能会有所帮助:
http://doc.scrapy.org/en/latest/topics/spiders.html#scrapy.spider.Spider.make_requests_from_url
这是我在项目中不设置类别的情况下为我的项目所做的:
从命令行传递参数,如下所示:
scrapy crawl reviews_spider -a brand_name=apple
接收参数并在 my_spider.py 中设置为蜘蛛参数
def __init__(self, brand_name, *args, **kwargs):
self.brand_name = brand_name
super(ReviewsSpider, self).__init__(*args, **kwargs)
# i am reading start_urls from an external file depending on the passed argument
with open('make_urls.json') as f:
self.start_urls = json.loads(f.read())[self.brand_name]
在pipelines.py
:
class ReviewSummaryItemPipeline(object):
@classmethod
def from_crawler(cls, crawler):
pipeline = cls()
crawler.signals.connect(pipeline.spider_opened, signals.spider_opened)
crawler.signals.connect(pipeline.spider_closed, signals.spider_closed)
return pipeline
def spider_opened(self, spider):
# change the output file name based on argument
self.file = open(f'reviews_summary_{spider.brand_name}.csv', 'w+b')
self.exporter = CsvItemExporter(self.file)
self.exporter.start_exporting()
def spider_closed(self, spider):
self.exporter.finish_exporting()
self.file.close()
def process_item(self, item, spider):
self.exporter.export_item(item)
return item
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.