我正在尝试让我的输出看起来像json格式中的以下内容。
{"loser": "De Schepper K." ,"winner": "Herbert P.", "url":
"https://www.sofascore.com/tennis/2018-02-07"}
但我现在正在为每个失败者项目和获胜者项目获取单独的行。我希望赢家和输家都与网址保持一致。
{"loser": "De Schepper K.", "url":
"https://www.sofascore.com/tennis/2018-02-07"}
{"winner": "Herbert P.", "url":
"https://www.sofascore.com/tennis/2018-02-07"}
{"loser": "Sugita Y.", "url":
"https://www.sofascore.com/tennis/2018-02-07"}
我不确定这是我的选择器是否会导致这种行为,但我想知道如何自定义管道,以便失败者,赢家和日期都在同一个json线上
我之前从未提取过json格式,所以对我来说这是新手。 如何使用自定义管道指定每行上的json键和值?
我也尝试使用csv item exporter来做这件事并且也有奇怪的行为。 REF Scrapy output is showing empty rows per column
这是我的spider.py
import scrapy
from scrapy_splash import SplashRequest
from scrapejs.items import SofascoreItemLoader
from scrapy import Spider
import json
from scrapy.http import Request, FormRequest
class MySpider(scrapy.Spider):
name = "jsscraper"
start_urls = ["https://www.sofascore.com/tennis/2018-02-07"]
def start_requests(self):
for url in self.start_urls:
yield SplashRequest(url=url,
callback=self.parse,
endpoint='render.html',
args={'wait': 1.5})
def parse(self, response):
for row in response.css('.event-team'):
il = SofascoreItemLoader(selector=row)
il.add_css('winner' , '.event-team:nth-
child(2)::text')
il.add_css('loser' , '.event-team:nth-
child(1)::text')
il.add_value('url', response.url)
yield il.load_item()
items.py
import scrapy
from scrapy.loader import ItemLoader
from scrapy.loader.processors import TakeFirst, MapCompose
from operator import methodcaller
from scrapy import Spider, Request, Selector
class SofascoreItem(scrapy.Item):
loser = scrapy.Field()
winner = scrapy.Field()
url = scrapy.Field()
class SofascoreItemLoader(ItemLoader):
default_item_class = SofascoreItem
default_input_processor = MapCompose(methodcaller('strip'))
default_output_processor = TakeFirst()
pipeline.py
import json
import codecs
from collections import OrderedDict
class JsonPipeline(object):
def __init__(self):
self.file = codecs.open('data_utf8.json' , 'w' ,
encoding='utf-8')
def process_item(self , item , spider):
line = json.dumps(OrderedDict(item) , ensure_ascii=False ,
sort_keys=False) + "\n"
self.file.write(line)
return item
def close_spider(self , spider):
self.file.close()
答案 0 :(得分:1)
所以我回顾了你的问题,现在我找到了问题所在:
for row in response.css('.event-team'):
使用上面的行,您将获得许多选择器(或SelectorList)。但是,在每个选择器或行中,您只能获得一个字段:赢家或输家。你无法得到它们。
这就是为什么输出中会有空行的原因。
解决方案:尝试以下行:
for row in response.css('div[class=“cell__section--main s-tennisCell curb-width”]')
答案 1 :(得分:1)
这里的问题是您要循环.event-team
个元素
其中一个元素只能是赢家或输家,所以每个元素都有一个项目。
你应该做的是循环包含两者的元素(.list-event
似乎是一个好的候选者),并从中提取胜负者。
这样,每个事件都有一个循环,因此每个事件有一个项目。