在一个高层次上-我想我正在尝试使用Scrapy框架像一个刮库。
我的用例是,我有一个网页,其中包含指向我想抓取的会议记录的链接,随着时间的推移,会添加更多指向会议记录的链接。
我的计划是使用一个普通的spider来抓取会议记录的链接,并通过管道/CsvItemExporter
将链接列表传输到CSV。
常规蜘蛛1-网页链接到会议纪要我想刮,出口到csv:
class QuotesSpider(scrapy.Spider):
name = "easthamptontown-links"
custom_settings = {
'ITEM_PIPELINES': {
'themis.pipelines.ThemisPipeline': 400
}
}
def start_requests(self):
urls = [
'http://easthamptontown.iqm2.com/Citizens/Calendar.aspx?From=1/1/1900&To=12/31/9999',
]
for url in urls:
yield scrapy.Request(url=url, callback=self.parse)
def parse(self, response):
rowtops = response.xpath('//div[@class="RowTop"]')
for meeting in rowtops:
yield {
'meeting': meeting.css("a[href*='Detail_Meeting']").get(),
'files': meeting.css("a[href*='FileView']").getall(),
}
管道1
class ThemisPipeline:
def __init__(self):
self.files = {}
@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):
file = open('%s.csv' % spider.name, 'wb')
self.files[spider] = file
self.exporter = CsvItemExporter(file)
self.exporter.start_exporting()
def spider_closed(self, spider):
self.exporter.finish_exporting()
file = self.files.pop(spider)
file.close()
def process_item(self, item, spider):
file_output = {}
_item = ItemAdapter(item).asdict()
if len(_item['files']) > 0:
for filelink in _item['files']:
parser = MyHTMLParser()
parser.feed(filelink)
file_output['filelink'] = parser.lsHref
file_output['filetype'] = parser.lsData
parser.feed(_item['meeting'])
file_output['meetinglink'] = parser.lsHref
file_output['meetingtitle'] = parser.lsTitle
file_output['meetingdate'] = parser.lsData.strip()
self.exporter.export_item(file_output)
else:
DropItem(item)
return item
CsvReader()/list解析将CSV中的链接提供给start_urls
中的第二个常规spider,后者使用这些链接抓取会议记录,并将/CsvItemExporter管道传输到以该链接命名的.txt
文件,例如meeting123.txt
。
我第二次运行第一个scraper时,比较新csv中到原始csv的链接,将新csv中链接的会议纪要(而不是原始csv管道/CsvItemExporter
中的链接)刮到以该链接命名的.txt
文件中,例如meeting124.txt
。
我眼前的问题是,将抓取的minutes链接传递到管道,以minutes链接命名文件比我想象的要困难-框架似乎不适合这个。
常规spider 2-从CSV提供的URL中抓取会议记录:
class ASpider(scrapy.Spider):
name = "town-text"
custom_settings = {
'ITEM_PIPELINES': {
'themis.pipelines.MinutesPipeline': 400
}
}
meetings = csvreader('./town-links.csv')
# don't override start_requests, default scrapy.Request(url=url, callback=self.parse)
start_urls = ['http://http://easthamptontown.iqm2.com/Citizens/' + meeting['filelink'] \
for meeting in meetings \
if 'Zoning' in meeting['meetingtitle'] and \
'Regular Meeting' in meeting['meetingtitle'] and \
meeting['filetype'] == 'Minutes']
def parse(self, response):
for element in response.xpath('//div[@id="Content"]/div/*'):
yield {
'line': element.xpath('.//text()').getall(),
}
管道:
class MinutesPipeline:
def __init__(self):
self.files = {}
@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):
file = open('%s.txt' % spider.name, 'wb')
self.files[spider] = file
self.exporter = CsvItemExporter(file)
self.exporter.start_exporting()
def spider_closed(self, spider):
self.exporter.finish_exporting()
file = self.files.pop(spider)
file.close()
def process_item(self, item, spider):
_item = ItemAdapter(item).asdict()
self.exporter.export_item(_item)
return item
我希望能够将我正在抓取的html
的特定URL meeting['filelink']
,-传递到项目的CSV文件名。我尝试将scrapy.Spider
更改为CrawlSpider
以尝试使用parse_start_url()
,但选择器没有使用CrawlSpider
返回任何数据。
对于Scrapy框架特有的这种用例的设计的任何想法都将受到欢迎。
1条答案
按热度按时间lxkprmvk1#
如果你想使用
url
作为文件名,你所需要做的就是传递url和条目,然后用这个文件名创建一个新文件并导出它。例如:
在parse方法中,向字典中添加一个url字段,并添加
response.url
作为其值。然后在您的管道中: