【发布时间】:2018-06-18 09:33:42
【问题描述】:
我有以下代码:
class VoteSpider(scrapy.Spider):
name = "test"
def start_requests(self):
self.start_url = [
"http://www.domain.de/URI.html?get=1&getX=2",
"http://www.domain.de/URI.html?get=2&getX=3",
"http://www.domain.de/URI.html?get=3&getX=4",
"http://www.domain.de/URI.html?get=4&getX=5"
]
for url in self.start_url:
self.a = 0
self.url = url
self.page = self.url.split("/")[-1]
self.filename = '%s.csv' % self.page
with open(self.filename, 'w') as f:
f.write('URL:;'+self.url+'\n')
yield scrapy.Request(url=self.url,callback=self.parse,dont_filter = True)
def parse(self, response):
sel = Selector(response)
votes = sel.xpath('//div[contains(@class,"ratings")]/ul')
with open(self.filename, 'a') as f:
for vote in votes:
self.a+=1
f.write(str(self.a)+';'+vote.xpath('./li/text()').extract())
if len(votes.xpath('//a[contains(@class,"next")]/@href').extract()) != 0:
next_page = votes.xpath('//a[contains(@class,"next")]/@href').extract()[0]
if next_page is not None:
yield response.follow(next_page, callback=self.parse, dont_filter=True)
我的问题是,使用此代码,所有内容都将保存在一个文件中,在上面的示例中将是:
URI.html?get=1&getX=2.csv
由于我在多个 URL 上运行循环并为每个 URL 创建一个新文件名,我想知道哪里出了问题。
为什么这段代码没有为每个 URL 创建新文件?
for url in self.start_url:
self.a = 0
self.url = url
self.page = self.url.split("/")[-1]
self.filename = '%s.csv' % self.page
with open(self.filename, 'w') as f:
f.write('URL:;'+self.url+'\n')
有人可以告诉我正确的方法/示例如何保存每个起始 URL 的文件吗?请考虑一下,我还希望将以下页面附加到文件中,直到没有页面可以关注为止。
编辑:
问题不在于没有创建文件。的所有内容
with open(self.filename, 'a') as f:
for vote in votes:
self.a+=1
f.write(str(self.a)+';'+vote.xpath('./li/text()').extract())
保存到一个文件中,而不是保存到 4 个文件中。所有将被保存到第一个可用的 StartURL
EDIT2:
这个主意不错!但从我的例子来看,它不能替换:
file_name = '%s.csv' % response.url.split("/")[-1]
因为 URI 正在更改,并且每个新 URI 都会创建一个新文件。
startURL 1 - "http://www.domain.de/URI.html?get=1&getX=2"
response.url 2 - "http://www.domain.de/URI.html?get=2&getX=2"
response.url 3 - "http://www.domain.de/URI.html?get=3&getX=2"
我只想保存 startURL 中的所有内容。
startURL 1 saved to "http://www.domain.de/URI.html?get=1&getX=2.csv"
response.url 2 saved to "http://www.domain.de/URI.html?get=1&getX=2.csv"
response.url 3 saved to "http://www.domain.de/URI.html?get=1&getX=2.csv"
一个不可靠的解决方案是按条件映射名称,但如果 startURL 数量增加或起始 URL 结构发生变化,则不实用:
if response.url.find("getX=2"):
filename = self.start_url[0].split('/')[-1]
if response.url.find("getX=3"):
filename = self.start_url[1].split('/')[-1]
if response.url.find("getX=4"):
filename = self.start_url[2].split('/')[-1]
...
我不明白为什么self.filename 没有正确传递给self.parse()?是否有一些多重处理,所以self.filename 总是被第一项覆盖?如何在不使用响应对象的情况下转发正确的文件名?
解决方案:
我通过request.meta传递值:
class VoteSpider(scrapy.Spider):
name = "test2"
def start_requests(self):
self.start_url = [
"http://www.domain.de/URI.html?get=1&getX=2",
"http://www.domain.de/URI.html?get=2&getX=3",
"http://www.domain.de/URI.html?get=3&getX=4",
"http://www.domain.de/URI.html?get=4&getX=5"
]
for url in self.start_url:
self.a = 0
self.url = url
self.page = self.url.split("/")[-1]
self.filename = '%s.csv' % self.page
with open(self.filename, 'w') as f:
f.write('URL:;'+self.url+'\n')
request = scrapy.Request(url=self.url,callback=self.parse,dont_filter = True)
request.meta['url'] = url
yield request
def parse(self, response):
sel = Selector(response)
votes = sel.xpath('//div[contains(@class,"ratings")]/ul')
self.file = response.meta['url']
filename = self.file.split("/")[-1]+'.csv'
with open(filename, 'a') as f:
for vote in votes:
self.a+=1
f.write(str(self.a)+';'+votes.xpath('./li/text()').extract()[0])
if len(votes.xpath('//a[contains(@class,"next")]/@href').extract()) != 0:
next_page = votes.xpath('//a[contains(@class,"next")]/@href').extract()[0]
if next_page is not None:
request = response.follow(next_page, callback=self.parse, dont_filter=True)
request.meta['url'] = self.file
yield request
【问题讨论】:
-
我运行这段代码,它生成了四个
.csv文件 -
@zimdero 对!谢谢。我在编辑中指定了问题 - 我为文件创建的标头之后的所有以下数据都保存到一个文件中,而不是超过 4 个文件
-
好的,我现在看看
-
@zimdo 这是一个好主意,但它仍然不适用于我的用例。还有其他想法或解释吗?谢谢!我又编辑了
-
你能给我两个网址吗?试一试
标签: python python-3.x web-scraping scrapy web-crawler