2017-11-10 8 views
-2

테이블의 크기를 알려주는 컬럼에 데이터가 항상 있기 때문에 목록 길이로 round-col을 사용합니다. 모든 필드가 일치해야하므로 데이터를 고칩니다.하지만 루프가 '데이터 없음'에 도달하면 목록 인덱스가 범위를 벗어나거나 'TypeError :'NoneType '개체가 스크립트 가능하지 않습니다.Python/Scrapy 핸들 테이블 데이터 누락, 범위를 벗어난리스트 인덱스

from scrapy.selector import Selector 
from scrapy.spiders import Spider 
from bigcrawler.items import BigcrawlerItem 

class CrawlbotSpider(Spider): 
    name = 'bigcrawler' 
    allowed_domains = ['www.matchstat.com'] 
    start_urls = ['https://matchstat.com/tennis/all-upcoming-matches'] 

    custom_settings = { 
    'FEED_FORMAT': 'csv' , 
    'FEED_URI': 'test.csv' 
    } 
def parse(self ,response): 

    hxs = Selector(response) 
    item = BigcrawlerItem() 

    round_col = hxs.xpath(".//tr[contains(@class, 'match')]/td[contains(@class, 'round')]/text()").extract() 
    event_col = hxs.xpath(".//tr[contains(@class, 'match')]/td[contains(@class, 'event-name')]/a/text()").extract() 
    player1_col = hxs.xpath(".//tr[contains(@class, 'match')]/td[contains(@class, 'player-name')][1]/a/text()").extract() 
    player2_col = hxs.xpath(".//tr[contains(@class, 'match')]/td[contains(@class, 'player-name')][2]/a/text()").extract() 
    odds1_col = hxs.xpath(".//tr[contains(@class, 'match highlight')]/td[contains(@class, 'odds-td odds-0')]/a[contains(@class, 'btn btn-default virtual btn-xs btn-outcome odds')][1]/text()").extract_first() 
    odds2_col = hxs.xpath(".//tr[contains(@class, 'match highlight')]/td[contains(@class, 'odds-td odds-1')]/a[contains(@class, 'btn btn-default virtual btn-xs btn-outcome odds')][2]/text()").extract_first() 
    h2h_col = hxs.xpath(".//tr[contains(@class, 'match')]/td[contains(@class, 'h2h')]/a[contains(@class, 'h2h')]/text()").extract_first() 


    for x in range(0,len(round_col)): 
     item['round'] = round_col[x].strip() 
     item['event1'] = event_col[x].strip() 
     item['player_1'] = player1_col[x].strip() 
     item['player_2'] = player2_col[x].strip() 
     item['player_1_odds'] = odds1_col[x].strip() 
     item['player_2_odds'] = odds2_col[x].strip() 
     item['h_2_h'] = h2h_col[x].strip() 
     yield item 

목록이 모양이 바뀌면 데이터가 쓸모가 없습니다. len 루프를 유지하는 요소에 도달하지 않으면 "없음"을 삽입하도록 루프를 어떻게 수정합니까?

내가 취할 수있는 또 다른 방법이 있습니까? 감사합니다. .

+0

하나의 옵션은'X <렌 (odds_1_col)와 odds1_col [X] .strip() 또는 None'으로이 쓰기하지만 난 아마 클래스로 ...이 다시 작성해야한다고 생각합니다. –

답변

0

를 대신 안부를 기반으로 구축을 위해 노력의

# -*- coding: utf-8 -*- 
import scrapy 

# This should go to items.py 
from scrapy.loader import ItemLoader 
from scrapy.loader.processors import TakeFirst, MapCompose 
from operator import methodcaller 


class MatchStatItem(scrapy.Item): 
    round = scrapy.Field() 
    event1 = scrapy.Field() 
    player_1 = scrapy.Field() 
    player_2 = scrapy.Field() 
    player_1_odds = scrapy.Field() 
    player_2_odds = scrapy.Field() 
    h_2_h = scrapy.Field() 


class MatchStatItemLoader(ItemLoader): 
    default_item_class = MatchStatItem 
    default_input_processor = MapCompose(methodcaller('strip')) 
    default_output_processor = TakeFirst() 

class MatchStatSpider(scrapy.Spider): 
    name = "matchstat" 
    allowed_domains = ["matchstat.com"] 
    start_urls = ['https://matchstat.com/tennis/all-upcoming-matches'] 

    def parse(self, response): 
     for row in response.css('tr.match'): 
      il = MatchStatItemLoader(selector=row) 
      il.add_css('round', '.round::text') 
      il.add_css('event1', '.event-name a::text') 
      il.add_css('player_1', '.player-name:nth-child(3) a::text') 
      il.add_css('player_2', '.player-name:nth-child(4) a::text') 
      il.add_css('player_1_odds', '.odds-td.odds-0 [payout]::text') 
      il.add_css('player_2_odds', '.odds-td.odds-1 [payout]::text') 
      il.add_css('h_2_h', 'a.h2h::text') 
      yield il.load_item() 

하는 출력이되어야합니다 : umns, 당신은 .extract_first() 또는 .strip()이를보십시오, 내가 여기에 항목 로더를 사용했습니다 여러 피할 수 있도록 행을 통해 루프해야하고, 행 당 항목을 구축 시작 같은 :

{'event1': u'ATP World Tour Finals', 'h_2_h': u'H2H 3-0', 'player_1': u'Roger Federer', 'player_1_odds': u'1.10', 'player_2': u'Jack Sock', 'player_2_odds': u'7.00', 'round': u'RR A'} 
+0

답해 주셔서 고맙습니다.하지만이 코드를 실행할 때 '필드를 지원하지 않습니다 : 선택자'오류가 발생합니다. scider.selector 가져 오기 선택기에서 가져 오기 문을 사용 중이며 계속 오류가 발생합니다. – tomoc4

+0

이상한 버전 치료법을 사용하고 있습니까? (아마도 더 많은 오류 메시지를 표시 할 수 있습니다). – Wilfredo

+0

안녕하세요. 고마워요, 제가 스크립트를 작동 시켰습니다. 내 문제는 csv 항목 수출 업체와 관련이 있습니다. 나는 스쿠버가 기본 설정을 과도하게 혼동하고 있다고 생각합니다. – tomoc4

0

나는 데이터가 아닌 특정 TD 존재 않을 경우, 그것은 당신의 출력 CSV

에서 비어 표시됩니다,이 방법

for match in response.css("table.draw-table.filter-table tr.match): 
    item['round'] = "".join(a.strip() for a in match.css("td.round *::text").extract()) 
    #do the other TDs just like above 
    yield item 

어떤 오류가 발생하지 않습니다 이런 식으로 같은 CSS 선택기를 사용하는 것이 좋습니다

0

더 나은 당신은 (필요에 따라 수정이 코드를 사용하여 구문 분석 방법 본체를 교체하고) 이런 식으로 데이터를 추출하는 경우 :

data = [] 
rows = response.xpath('//tr[contains(@class, "match ")]') 
for i in rows: 
    round_col = i.css("td.round::text").extract_first() 
    event_col = i.css("td.event-name::text").extract_first() 
    players = i.css("td.player-name") 
    player1_col = players[0].css("a::text").extract_first() 
    player2_col = players[0].css("a::text").extract_first() 
    odds1_col = i.css("td.odds-td odds-0 a.btn.btn-default.virtual.btn-xs.btn-outcome.odds::text").extract_first() 
    odds2_col = i.css("td.odds-td odds-1 a.btn.btn-default.virtual.btn-xs.btn-outcome.odds::text").extract_first() 
    h2h_col = i.css("td.h2h a.h2h::text").extract_first()  
    data.append({'round': round_col, 'event': event_col, 'player1': player1_col, 'player2': player2_col, 'odds1':odds1_col, 'odds2':odds2_col, 'h2h':h2h_col}) 

print data 
관련 문제