我这里有一个scrapy代码输出一个json文件。然后我使用jupyter notebook将json文件导入数据帧以清理数据。但是,我真正想做的是能够运行scrapy spider并将数据输出为已经清理过的CSV,而不是将已删除的数据保存为json文件并进入jupyter笔记本来清理它。无论如何要连接这两个过程?下面是我的蜘蛛代码:
import scrapy
import pandas as pd
import json
import datetime
from seatgeek.items import SeatgeekItem
class seatgeekSpider(scrapy.Spider):
name = "seatgeek_spider"
#showname = input("Enter Show name (lower case please): ")
#showname = showname.replace(' ', '-')
start_urls = ["https://seatgeek.com/come-from-away-tickets?page={}".format(i) for i in range (1,35)]
custom_settings = {
'DOWNLOAD_DELAY': 3,
'CONCURRENT_REQUESTS_PER_DOMAIN': 3,
'HTTPCACHE_ENABLED': True,
'FEED_FORMAT': 'json',
'FEED_URI': 'test.json'
}
def parse(self, response):
for href in response.xpath('//a[@class="event-listing-title"]/@href').extract():
item = SeatgeekItem()
item['performance'] = href.split('/')[-3]
item["eventId"] = href.split('/')[-1]
yield scrapy.Request(
url = 'https://seatgeek.com/listings?id=' + item['eventId'] + '&aid=11955&client_id=MTY2MnwxMzgzMzIwMTU4',
callback=self.parse_ticketinv,
meta={'item': item})
def parse_ticketinv(self, response):
jsonresponse = json.loads(response.body_as_unicode())
item = response.meta['item']
for i in jsonresponse["listings"]:
item["sectionName"] = i["s"]
item["zoneName"] = i["s"].split(' ')[0]
item["currentPrice"] = i["p"]
item["listingPrice"] = i["p"]
item["row"] = i["r"]
item["seatNumbers"] = ""
item['listingId'] = i["id"]
item['quantity'] = i["q"]
item['vendor'] = "SeatGeek"
yield item
这是我清理数据的代码:
import json
import pandas as pd
import datetime
path = r'C:\Users\...\Desktop\Code\seatgeek\test.json'
with open(path) as f:
data = json.load(f)
df = pd.DataFrame(data)
df = df[df.performance.str.contains('gerald')]
df['performance'] = df['performance'].map(lambda x: x.lstrip('gerald-schoenfeld-theatre-').rstrip('-pm'))
df['performance'] = df['performance'].apply(lambda x: datetime.datetime.strptime(x,'%Y-%m-%d-%H'))
df['datePulled'] = pd.to_datetime('today')
filename = input('Enter filename: ')
df.to_csv(filename + '.csv', mode='a', index=False)
修改
Per @stranac的帮助,我用下面的代码更新了我的管道。但是出于某种原因,我似乎丢失/我不想删除的一些行。好像我评论item['performance'] = datetime.datetime.strptime(item['performance'][26:],'%Y-%m-%d-%H-%p')
,它会正常工作。
def process_item(self, item, spider):
if 'gerald' not in item['performance']:
raise DropItem
item['performance'] = datetime.datetime.strptime(item['performance'][26:],'%Y-%m-%d-%H-%p')
item['datePulled'] = datetime.datetime.now()
return item
答案 0 :(得分:1)
最简单的方法是编写自己的item pipeline,并在process_item()
中对每个项目进行清理,而不是使用pandas一次完成所有操作。
class YourPipeline(object):
def process_item(self, item, spider):
if 'gerald' not in item['performance']:
raise DropItem
# do your cleanup
return item
旁注:lstrip和rstrip不做你的想法,在这种情况下恰好会产生正确的结果。
编辑:
您获得的错误是由同一项目从parse_ticketinv
多次产生的。
这会导致已修改的项目(item['performance']
被datetime
对象替换)再次通过管道,从而导致TypeError
。
解决问题的最简单方法是在每个循环中创建一个新项目,或者产生项目副本:
def parse_ticketinv(self, response):
# for whatever:
# do stuff
yield item.copy()