奇怪的csv输出和丢失的请求

2024-09-29 09:25:16 发布

您现在位置:Python中文网/ 问答频道 /正文

如果您能帮助我改进代码并解决以下两个问题,那就太好了:

  • 进程['DE101096','AT231']开始时的一个id被忽略
  • 当爬行与刮蹭机器人-o结果.csv结果为csv,格式如下:

交易id交易日期交易id交易id交易id

DE101096 2011-02-21 11:05:23.312
DE101096 2011-02-21 11:05:23.312氧燃料分析
DE101096 2011-02-21 11:05:23.312 Anlagenkonto Oxyfuelanlage N-Ionalkonto–Ausgabe

很明显,我希望只有一行具有transactionID、transactionDate、acq_id和tra_id。我知道这个问题显然取决于我的代码,该代码将transactionID、transactionDate传递给由于两个后续请求而重复的项。然而,我找不到任何接近预期产量的解决方案。在

我如何解决上述问题,以及如何使我的蜘蛛更有效。我也尝试了一种基于规则的方法,但是没有成功。在

我很高兴所有的投入!在

import csv

from scrapy.contrib.spiders import CrawlSpider
from scrapy.selector import Selector
from scrapy.contrib.linkextractors import LinkExtractor
from scrapy.http import FormRequest, Request

from etsbot.items import TransactionItem
from etsbot.middlewares import RandomProxy

class EuetsbotdetSpider(CrawlSpider):
    name = 'euetsbotdet'
    allowed_domains = ['ec.europa.eu']
    start_urls = [
        'http://ec.europa.eu/environment/ets/transaction.do'
    ]

    def parse(self, response):
    #self.data = csv.DictReader(open('/home/...t/items.csv','r'))
    #self.tids = []
    #for self.row in self.data:
    #    self.tids.append(self.row['transactionID'])
    self.tids = ['DE101096','AT231']

    for self.id in self.tids:
        return FormRequest.from_response(
            response,
            formname='transactions_maxlength',
            formdata={'transactionID':self.id},
            clickdata={'name': 'search'},callback=self.parseLinks
            )

def parseLinks(self,response):
    lex = LinkExtractor(allow=('http://ec.europa.eu/environment/ets/singleTransaction.do',),unique=True)
    for l in lex.extract_links(response):
        yield Request(l.url,method='GET',callback=self.parseDetail,)                

def parseDetail(self,response):
    sel  = Selector(response)
    item = TransactionItem()
    item['transactionID']   = sel.xpath('//table/tr/td/input[@name="transactionID"]/@value').extract()
    item['transactionDate'] = sel.xpath('//table/tr/td/input[@name="transactionDate"]/@value').extract()

    lext  = LinkExtractor(unique=True,restrict_xpaths = ('//*[@id="tblTransactionBlocksInformation"]/tr/td[6]/a[@class="resultlink"]'),)        
    for l in lext.extract_links(response):
        yield Request(l.url,method='GET',meta={'item':item},callback=self.parseAccounttr)

    lexa  = LinkExtractor(unique=True,restrict_xpaths = ('//*[@id="tblTransactionBlocksInformation"]/tr/td[7]/a[@class="resultlink"]'),)        
    for l in lexa.extract_links(response):
        yield Request(l.url,method='GET',meta={'item':item},callback=self.parseAccountac)
        yield item         

def parseAccounttr(self,response):
    sel   = Selector(response)
    item  = response.meta['item']
    item['tra_id'] = sel.xpath('//*[@id="tblAccountInfoReadonly"]/tr/td/input[@name="identifierInReg"]/@value').extract()
    yield item  

def parseAccountac(self,response):
    sel = Selector(response)
    item = response.meta['item']
    item['acq_id'] = sel.xpath('//*[@id="tblAccountInfoReadonly"]/tr/td/input[@name="identifierInReg"]/@value').extract()
    yield item

编辑:

在paultrmbth的精彩评论的帮助下,我重写了我的代码。我没有像我在上面的代码中那样将下载分成两组,而是在一个流中进行所有的下载。这意味着当我爬的时候蜘蛛网.py-o对于每个transactionID/transactionDate,我有两行,第一行是“卖方”,第二行是“买方”。显然,这些信息应该放在一行。我现在的想法是在后处理中自动更正这一点,即通过transactionID/transactionDate将每个奇数项与后续的偶数项合并(我希望这是清楚的)。但我该怎么做呢?在

^{pr2}$

Tags: 代码namefromimportselfidresponseextract
2条回答

我还没有测试过这段代码,但问题是,您在scrape的不同部分生成了3次该项(这就是为什么每个部分只包含您要查找的字段的子集)。你只需要在末尾有一个“收益项目”。我重写了代码,你可以在http://pastebin.com/dxsHZ7fZ找到它。在

关于第一点,当你写下:

for self.id in self.tids:
    return FormRequest.from_response(
        response,
        formname='transactions_maxlength',
        formdata={'transactionID':self.id},
        clickdata={'name': 'search'},callback=self.parseLinks
        )

循环在第一次迭代时停止,因为您使用了return。在

将其更改为“yield循环”:

^{pr2}$

关于第二点,正如@EricValente所说,如果您希望每个事务ID有一个CSV行,那么您只需要为每个事务ID生成/返回一个条目

您可以开始在parseDetail中构建该项,并像您所做的那样将该项传递到meta中,但随后需要跟踪有多少请求未完成,以便在处理完每个响应后知道何时返回该项。 这可能是相当棘手的正确做法。例如,您必须捕获请求失败。 你可以试试scrapy-inline-requests,这很方便。在

另一个选择是在第一次抓取之后按事务ID进行后处理和分组,因此您可以手工构建CSV。在

另一个选择是不要对parseAccounttr()parseAccountac()执行这些额外的请求:据我所知,在2个事务id中,tr[6]和{}中链接的文本值与您在后续回调中获取的identifierInReg属性具有相同的值

相关问题 更多 >