如何使用 readtext 将多个 JSON 文件加载到 quanteda 语料库中?

How to load multiple JSON files into a quanteda corpus using readtext?

我正在尝试使用 readtext 从新闻网站将大量 JSON 文件加载到 quanteda 语料库中。为了简化这个过程,JSON 文件都在工作目录中。但我也在他们自己的目录中尝试过。

  1. 当使用 c() 创建一个显式定义一小部分文件的变量时,readtext 可以正常工作,并且可以使用 corpus().[=114= 正确创建语料库]
  2. 当尝试使用 list.files() 创建变量以列出所有 +1500 JSON 文件时 readtext 无法按预期工作,出现 return 错误,并且没有创建语料库。

我试图检查两种定义文本集的方法(即 c()list.files())以及 paste0().

的结果
# Load libraries
library(readtext)
library(quanteda)

# Define a set of texts explicitly
a <- c("border_2020_05_10__1589150513.json","border_2020_05_10__1589143358.json","border_2020_05_07__1589170960.json")

# This produces a corpus
extracted_texts <- readtext(a, text_field = "maintext")
my_corpus <- corpus(extracted_texts)
# Define a set of all texts in working directory
b <- list.files(pattern = "*.json", full.names = F)

# This, which I hope to use, produces an error
extracted_texts <- readtext(b, text_field = "maintext")
my_corpus <- corpus(extracted_texts)

extracted_texts <- readtext(b, text_field = "maintext")产生的错误如下

File doesn't contain a single valid JSON object.
Error: This JSON file format is not supported.

这很令人费解,因为使用 a 调用的相同文件不会产生错误。我 validated several of the JSON files which in every case returned VALID (RFC 8259), the IETF standard 为 JSON.

检查 ab 之间的差异:

我真的很困惑为什么 a 有效而 b 无效。

最后,尝试完全模仿 readtext documentation 所采用的程序,还尝试了以下操作:

# XXXX = my username
data_dir <- file.path("C:/Users/XXXX/Documents/R/")

d <- readtext(paste0(data_dir, "/corpus_linguistics/*.json"), text_field = "maintext")

这也return编辑了错误

File doesn't contain a single valid JSON object.
Error: This JSON file format is not supported.

此时我被难住了。提前感谢您对如何前进的任何见解。

解决方案和总结

  1. 不干净的数据: 一些输入 JSON 文件有空 main_text 字段。这些对分析没有用,应该删除。所有文件都包含一个名为 "title_rss" 的 JSON 字段,该字段为空。这可以通过目录级查找和替换为 Notepad ++,或者可能是 R 或 Python 来消除,尽管我仍然缺乏这方面的技能。此外,文件不是 UTF-8 编码,已通过 Codepage Converter.
  2. 解决
  3. 调用目录字符串的方法: readtext How to Use documentation and several third party tutorials中使用了list.files()方法。此方法适用于 *.txt 文件,但由于某些原因,它似乎不适用于这些特定的 JSON 文件。一旦 JSON 文件被正确清理和编码,下面的方法就可以正常工作。如果 data_dir 包装在 list.files() 函数中,则会产生以下错误: Error in list_files(file, ignore_missing, TRUE, verbosity) : File '' does not exist. 我不确定为什么会这样,但是对于这些 JSON 文件,将其保留在外面是有效的。
# Load libraries
library(readtext)
library(quanteda)

# Define a set of texts explicitly
data_dir <- "C:/Users/Nathan/Documents/R/corpus_linguistics/"
extracted_texts <- readtext(paste0(data_dir, "texts_unmodified/*.json"), text_field = "maintext", verbosity = 3)
my_corpus <- corpus(extracted_texts)

使用未修改的文件进行测试,其中一个文件已知有空字段

输入: 5 个文件,其中包含 4 个 w/o 空或空 text_field 和 1 个空文件 text field。此外,所有文件都有西欧 (Windows) 1252 编码。

错误:

Reading texts from C:/Users/Nathan/Documents/R/corpus_linguistics/texts_unmodified/*.json
, using glob pattern
 ... reading (json) file: C:/Users/Nathan/Documents/R/corpus_linguistics/texts_unmodified/border_2014_02_17__1589147645.json
File doesn't contain a single valid JSON object.
 contain a single valid JSON object.
 ... reading (json) file: C:/Users/Nathan/Documents/R/corpus_linguistics/texts_unmodified/border_2014_03_13__1589150325.json
File doesn't contain a single valid JSON object.
Column 14 ['maintext'] of item 1 is length 0. This (and 0 others like it) has been filled with NA (NULL for list columns) to make each item uniform. ... read 5 documents.

结果: 一个由 5 个文档组成的格式正确的语料库。一份文件缺少标记或类型。尽管有错误,但语料库似乎构建正确。可能由于编码问题,某些特殊字符无法正常显示。我无法检查这个。

使用已知没有空字段的已清理文件进行测试

输入文件: 4 个没有空字段或空字段的文件 JSON。在所有情况下,text_field 包含文本并且 title_rss 字段已被删除。每个文件都从西欧 (Windows) 1252 转换为 Unicode UTF-8-65001。

错误:NONE!

结果: 语料库格式正确。

非常感谢两位开发人员提供的详细反馈和有用的线索。非常感谢您的协助。

这里有几种可能性,但最有可能的是:

  1. readtext() 的角度来看,您的一个文件的 JSON 结构不正确。即使从严格的 JSON 格式来看这可能没问题,但如果您的文本字段之一为空,那么这将导致错误。 (请参阅下面的演示和解决方案。)

  2. 虽然 readtext() 可以采用 "glob" pattern match,但 list.files() 可以采用正则表达式。有可能(但不太可能)您在 list.files(pattern = "*.json"... 中选择了您不想要的东西。但这对于 readtext() 来说不是必需的——见下文。

为了演示,让我们将 data_corpus_inaugural 中的每个文档写成单独的 JSON 文件,然后使用 readtext().

读取它们
library("quanteda", warn.conflicts = FALSE)
## Package version: 2.0.1
## Parallel computing: 2 of 8 threads used.
## See https://quanteda.io for tutorials and examples.

tmpdir <- tempdir()
corpdf <- convert(data_corpus_inaugural, to = "data.frame")
for (d in corpdf$doc_id) {
  cat(jsonlite::toJSON(dplyr::filter(corpdf, doc_id == d)),
    file = paste0(tmpdir, "/", d, ".json")
  )
}

head(list.files(tmpdir))
## [1] "1789-Washington.json" "1793-Washington.json" "1797-Adams.json"     
## [4] "1801-Jefferson.json"  "1805-Jefferson.json"  "1809-Madison.json"

要阅读它们,您可以在此处使用 "glob" 模式补丁,只需阅读 JSON 文件。

rt <- readtext::readtext(paste0(tmpdir, "/*.json"),
  text_field = "text", docid_field = "doc_id"
)
summary(corpus(rt), n = 5)
## Corpus consisting of 58 documents, showing 5 documents:
## 
##                  Text Types Tokens Sentences Year  President FirstName
##  1789-Washington.json   625   1537        23 1789 Washington    George
##  1793-Washington.json    96    147         4 1793 Washington    George
##       1797-Adams.json   826   2577        37 1797      Adams      John
##   1801-Jefferson.json   717   1923        41 1801  Jefferson    Thomas
##   1805-Jefferson.json   804   2380        45 1805  Jefferson    Thomas
##                  Party
##                   none
##                   none
##             Federalist
##  Democratic-Republican
##  Democratic-Republican

所以一切正常。

但是如果我们添加到这个文本字段为空的文件,则会产生有问题的错误:

cat('[ { "doc_id" : "d1", "text" : "this is a file" },
       { "doc_id" : "d2", "text" :  } ]',
  file = paste0(tmpdir, "/badfile.json")
)
rt <- readtext::readtext(paste0(tmpdir, "/*.json"),
  text_field = "text", docid_field = "doc_id"
)
## File doesn't contain a single valid JSON object.
## Error: This JSON file format is not supported.

是的,那不是有效的 JSON 文件,因为它包含一个没有值的标签。但我怀疑你的一个文件中有类似的东西。

以下是识别问题的方法:遍历 b(来自问题,而不是我在下面指定的那样)。

b <- tail(list.files(tmpdir, pattern = ".*\.json", full.names = TRUE))
for (f in b) {
  cat("Reading:", f, "\n")
  rt <- readtext::readtext(f, text_field = "text", docid_field = "doc_id")
}
## Reading: /var/folders/92/64fddl_57nddq_wwqpjnglwn48rjsn/T//RtmpuhmGRK/2001-Bush.json 
## Reading: /var/folders/92/64fddl_57nddq_wwqpjnglwn48rjsn/T//RtmpuhmGRK/2005-Bush.json 
## Reading: /var/folders/92/64fddl_57nddq_wwqpjnglwn48rjsn/T//RtmpuhmGRK/2009-Obama.json 
## Reading: /var/folders/92/64fddl_57nddq_wwqpjnglwn48rjsn/T//RtmpuhmGRK/2013-Obama.json 
## Reading: /var/folders/92/64fddl_57nddq_wwqpjnglwn48rjsn/T//RtmpuhmGRK/2017-Trump.json 
## Reading: /var/folders/92/64fddl_57nddq_wwqpjnglwn48rjsn/T//RtmpuhmGRK/badfile.json 
## File doesn't contain a single valid JSON object.
## Error: This JSON file format is not supported.