繁体   English   中英

Python CSV Reader只有JSON的第一个字符

[英]Python CSV Reader Only First Character of JSON

Amazon AWS Data Pipeline提供CSV文件作为MySQL数据库的输出。 在CSV中,有一个包含JSON的字段,我们试图分别使用Python的内置CSV和JSON阅读器提取和解码。 但是,由于生成CSV的方式,JSON不以引号开头,并且CSV解析器仅返回该CSV字段的JSON中的第一个“{”。

我们认为CSV阅读器会看到第一个'{',然后看到一个换行符,它将其解释为CSV行的结尾。 如果JSON包装在引号中,则脚本可以正常工作。 请参阅以下代码:

with open(args.env_vars[0] + '/click_stream_source.csv', 'r') as csvFile:
    csvReader = csv.reader(csvFile, delimiter = ',')
    with open(args.env_vars[1] + '/clickstream_target.csv', 'wb') as csvTarget:
        csvWriter = csv.writer(csvTarget, delimiter = ',')
        for row in csvReader:
            json_data = json.loads(row[5])

CSV示例是:

    495019,,8239,E3728E7D480248AA2EB5D5BB5C467737,67.84.254.6,{
            ""requests"": [
          {
             ""queryString"": null,
             ""time"": ""2013-06-14T11:53:40Z"",
             ""userAgent"": ""Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)"",
             ""requestURI"": ""/xxxxx/xxxx/xxxx.xxxxxxx"",
             ""class"": ""xxxxx"",
             ""params"": {
                ""action"": ""xxxxx"",
                ""controller"": ""xxxx""
             },
             ""isAjaxRequest"": false
          }]}

我们得到一个

ValueError:期待对象......

其中json.loads()方法

我不认为这可以称为CSV,因此CSV模块无济于事。

您可以使用正则表达式将[\\r\\n]\\s+转换为空格。 如果“JSON”是最后一个字段,则可以按列数进行拆分(为了将最后一列转换为有效的JSON所需的转换留作读者的作业)示例:

In [1]: l = """495019,,8239,E3728E7D480248AA2EB5D5BB5C467737,67.84.254.6,{
   ...:             ""requests"": [
   ...:           {
   ...:              ""queryString"": null,
   ...:              ""time"": ""2013-06-14T11:53:40Z"",
   ...:              ""userAgent"": ""Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)"",
   ...:              ""requestURI"": ""/xxxxx/xxxx/xxxx.xxxxxxx"",
   ...:              ""class"": ""xxxxx"",
   ...:              ""params"": {
   ...:                 ""action"": ""xxxxx"",
   ...:                 ""controller"": ""xxxx""
   ...:              },
   ...:              ""isAjaxRequest"": false
   ...:           }]}"""

In [2]: import re

In [3]: l_ = re.sub(r'[\n\r]\s+', ' ', l)

In [4]: l_
Out[4]: '495019,,8239,E3728E7D480248AA2EB5D5BB5C467737,67.84.254.6,{ ""requests"": [ { ""queryString"": null, ""time"": ""2013-06-14T11:53:40Z"", ""userAgent"": ""Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)"", ""requestURI"": ""/xxxxx/xxxx/xxxx.xxxxxxx"", ""class"": ""xxxxx"", ""params"": { ""action"": ""xxxxx"", ""controller"": ""xxxx"" }, ""isAjaxRequest"": false }]}'

In [5]: l_.split(',', 5)
Out[5]:
['495019',
 '',
 '8239',
 'E3728E7D480248AA2EB5D5BB5C467737',
 '67.84.254.6',
 '{ ""requests"": [ { ""queryString"": null, ""time"": ""2013-06-14T11:53:40Z"", ""userAgent"": ""Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)"", ""requestURI"": ""/xxxxx/xxxx/xxxx.xxxxxxx"", ""class"": ""xxxxx"", ""params"": { ""action"": ""xxxxx"", ""controller"": ""xxxx"" }, ""isAjaxRequest"": false }]}']

查看“JSON”内部的分割线是否与记录的末尾不同(例如,一个是\\n而另一个是\\r\\n ,这可以使您的工作更轻松。

这有点hackish - 正确的实现可能应该使用解析器 (正式的EBNF语法应该在10行以下)。

我认为从技术上讲你不能称之为CSV,因为它违反了解析规则,但我并不想迂腐,我试图说这是放弃内置解析工具和老去的原因,制作一个有限状态机。 这是一个快速而肮脏的例子,您可以适应您的目的。

#!/usr/bin/env python
import re
import json

def fix_and_parse(gathered_lines):
    strJson = '{' + "\n".join(gathered_lines)
    strJson = strJson.replace('""', '"')
    return json.loads(strJson)

state = 0
with open('csvFile', 'r') as csvFile:
    gathered_lines = []
    for line in csvFile:
        if re.search('^\d', line):
            if gathered_lines:
                print json.dumps(fix_and_parse(gathered_lines), indent=4)
            state = 0
            gathered_lines = []
        else:
            state = 1
        if state == 1:
            gathered_lines.append(line)
print json.dumps(fix_and_parse(gathered_lines), indent=4)

这里有一些非常有趣的建议,但经过进一步的考虑后,我的团队决定采用更直​​接的解决方案。 不幸的是,对于未来的读者来说,这有点特别针对MySQL / AWS CSV,但我们决定纠正SQL查询本身的问题:

SELECT RANDOM_FIELD, RANDOM_FIELD2, ..., REPLACE(JSON_FIELD,'\n','NEWLINE') FROM DATABASE ....

这解决了换行问题,这确实是问题,而不是CSV。 注意,最初的目标是使用\\\\ n来替换\\ n,但CSV生成器再次删除转义符'\\'。 话虽如此,我真的很喜欢Paulo Scardine的解决方案,它适用于我们玩过的少数测试用例; 如果JSON中的字符串实际上包含换行符(这是我们没有机会与数据库作者讨论的话),似乎可能存在问题。

你既没有有效的csv,也没有有效的json。

您可以使用正则表达式将[\\ r \\ n] \\ s +转换为空格

出于什么目的?

import json

data = '''495019,,8239,E3728E7D480248AA2EB5D5BB5C467737,67.84.254.6,{
            "requests": [
          {
             "queryString": null,
             "time": "2013-06-14T11:53:40Z",
             "userAgent": "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)",
             "requestURI": "/xxxxx/xxxx/xxxx.xxxxxxx",
             "class": "xxxxx",
             "params": {
                "action": "xxxxx",
                "controller": "xxxx"
             },
             "isAjaxRequest": false
          }]}'''

pieces = data.split(',', 5)
print pieces[5]

json_dict = json.loads( pieces[5] )
print json_dict['requests'][0]['time']

--output:--

{
            "requests": [
          {
             "queryString": null,
             "time": "2013-06-14T11:53:40Z",
             "userAgent": "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)",
             "requestURI": "/xxxxx/xxxx/xxxx.xxxxxxx",
             "class": "xxxxx",
             "params": {
                "action": "xxxxx",
                "controller": "xxxx"
             },
             "isAjaxRequest": false
          }]}

2013-06-14T11:53:40Z

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM