Json 行 (Jsonl) 生成器到 csv 格式

Json lines (Jsonl) generator to csv format

我有一个很大的 Jsonl 文件 (6GB+),我需要将其转换为 .csv 格式。 运行之后:

import json

with open(root_dir + 'filename.json') as json_file:
  for line in json_file:
    data = json.loads(line)
    print(data)

返回了以下格式的多条记录:

{'url': 'https://twitter.com/CHItraders/status/945958273861275648', 'date': '2017-12-27T10:03:22+00:00', 'content': 'Why #crypto currencies like $BTC #Bitcoin are set for global domination - MUST READ! - https :// t.co/C1kEhoLaHr https :// t.co/sZT43PBDrM', 'renderedContent': 'Why #crypto currencies like $BTC #Bitcoin are set for global domination - MUST READ! - BizNews.com biznews.com/wealth-buildin…', 'id': 945958273861275648, 'username': 'CHItraders', 'user': {'username': 'CHItraders', 'displayname': 'CHItraders', 'id': 185663478, 'description': 'Options trader. Market-news. Nothing posted constitutes as advice. Do your own diligence.', 'rawDescription': 'Options trader. Market-news. Nothing posted constitutes as advice. Do your own diligence.', 'descriptionUrls': [], 'verified': False, 'created': '2010-09-01T14:52:28+00:00', 'followersCount': 1196, 'friendsCount': 490, 'statusesCount': 38888, 'favouritesCount': 10316, 'listedCount': 58, 'mediaCount': 539, 'location': 'Chicago, IL', 'protected': False, 'linkUrl': None, 'linkTcourl': None, 'profileImageUrl': 'https://pbs.twimg.com/profile_images/623935252357058560/AaeCRlHB_normal.jpg', 'profileBannerUrl': 'https://pbs.twimg.com/profile_banners/185663478/1437592670'}, 'outlinks': ['http://BizNews.com', 'https://www.biznews.com/wealth-building/2017/12/27/bitcoin-rebecca-mqamelo/#.WkNv2bQ3Awk.twitter'], 'outlinksss': 'http://BizNews.com https://www.biznews.com/wealth-building/2017/12/27/bitcoin-rebecca-mqamelo/#.WkNv2bQ3Awk.twitter', 'tcooutlinks': ['https :// t.co/C1kEhoLaHr', 'https :// t.co/sZT43PBDrM'], 'tcooutlinksss': 'https :// t.co/C1kEhoLaHr https :// t.co/sZT43PBDrM', 'replyCount': 0, 'retweetCount': 0, 'likeCount': 0, 'quoteCount': 0, 'conversationId': 945958273861275648, 'lang': 'en', 'source': '<a href="http://twitter.com" rel="nofollow">Twitter Web Client</a>', 'media': None, 'retweetedTweet': None, 'quotedTweet': None, 'mentionedUsers': None}

由于文件太大,我无法使用转换:

with open(root_dir + 'filename.json', 'r', encoding ='utf-8-sig') as f:
    data = f.readlines()

data = map(lambda x: x.rstrip(), data)
data_json_str = "[" + ','.join(data) + "]"
newdf = pd.read_json(StringIO(data_json_str))
newdf.to_csv(root_dir + 'output.csv')

由于内存错误。我正在尝试使用下面的生成器并将每一行写入 csv,这应该可以解决 MemoryError 问题:

def yield_line_delimited_json(path):
    """
    Read a line-delimited json file yielding each row as a record
    :param str path:
    :rtype: list[object]
    """
    with open(path, 'r') as json_file:
        for line in json_file:
            yield json.loads(line)

new = yield_line_delimited_json(root_dir + 'filename.json')

with open(root_dir + 'output.csv', 'w') as f:
    for x in new:
        f.write(str(x))

但是,数据并没有写入.csv 格式。非常感谢任何关于为什么数据没有写入 csv 文件的建议!

发电机似乎完全多余。

with open(root_dir + 'filename.json') as old, open(root_dir + 'output.csv', 'w') as csvfile:
    new = csv.writer(csvfile)
    for x in old:
        row = json.loads(x)
        new.writerow(row)

如果 JSON 的一行不能简单地生成字符串和数字数组,您仍然需要弄清楚如何将它从 JSON 中的任何结构转换为可以有用地序列化为固定长度的字符串和数字的一维列表。

如果您的 JSON 可以可靠地包含具有一组固定关键字值对的单个词典,也许可以尝试

from csv import DictWriter
import json

with open(jsonfile, 'r') as inp, open(csvfile, 'w') as outp:
    writer = DictWriter(outp, fieldnames=[
            'url', 'date', 'content', 'renderedContent', 'id', 'username',
            # 'user',  # see below
            'outlinks', 'outlinksss', 'tcooutlinks', 'tcooutlinksss',
            'replyCount', 'retweetCount', 'likeCount', 'quoteCount',
            'conversationId', 'lang', 'source', 'media', 'retweetedTweet',
            'quotedTweet', 'mentionedUsers'])
    for line in inp:
        row = json.loads(line)
        writer.writerow(row)

我省略了 user 字段,因为在您的示例中,此键包含一个嵌套结构,如果不进一步修改,就无法轻易将其转换为 CSV。也许您只想将 user.id 提取到一个新字段 user_id 中;或者您可能想将整个 user 结构提升到主记录中附加列的扁平化列表中,例如 user_usernameuser_displaynameuser_id 等?

更详细地说,CSV 基本上是一个二维矩阵,其中每一行都是一维列的集合,对应于数据中的一条记录,其中每一列可以包含一个字符串或一个数字。每行的列数必须完全相同,但您可以将其中一些留空。

JSON 可以简单地转换为 CSV 看起来像

["Adolf", "1945", 10000000]
["Joseph", "1956", 25000000]
["Donald", null, 1000000]

JSON 可以通过某种转换(您必须单独指定,例如上面指定的字典键顺序)转换为 CSV 可能看起来像

{"name": "Adolf", "dod": "1945", "death toll": 10000000}
{"dod": "1956", "name": "Joseph", "death toll": 25000000}
{"death toll": 1000000, "name": "Donald"}

(只是为了让它更有趣,缺少一个字段,字典顺序因一条记录而异。这不是典型的,但绝对在 Python 的有效极端情况范围内不可能自己猜怎么处理。)

大多数现实世界 JSON 比这两个简单示例中的任何一个都复杂得多,以至于我们可以说在一般情况下无法解决该问题。