使用Ruby在CP932中解码Amazon报告

mlmc2os5  于 2023-04-20  发布在  Ruby
关注(0)|答案(1)|浏览(108)

Amazon的SP-API的报告通常是UTF-8格式的,除了日本的报告是CP 932格式的。我似乎不知道如何将这些报告解码成可用的数据。
运行Ruby 3.1.2并使用amz_sp_api gem连接Amazon
对于CSV报告,我们正在执行以下操作:

data = AmzSpApi.inflate_document(content, report_document)
csv_string = CSV.generate do |csv|
  data.gsub("\r", "").split("\n").each do |line|
    csv << line.split("\t")
  end
end
csv_string.force_encoding 'ASCII-8BIT'
csv = CSV.parse(csv_string, headers: true)

它没有抱怨任何事情,但结果数据看起来像这样:

...
"ship-state"=>"\xE7\xA6\x8F\xE5\xB2\xA1\xE7\x9C\x8C",

如果我强制编码为'CP 932',那么当我尝试解析csv时,我会得到:

3.1.2/lib/ruby/3.1.0/csv/parser.rb:786:in `build_scanner': Invalid byte sequence in Windows-31J in line 2. (CSV::MalformedCSVError)

对于XML报告,我们使用Nokogiri并执行如下操作:

data = AmzSpApi.inflate_document(content, report_document)
parsed_xml = Nokogiri::XML(data)

产生的XML实际上只是第一个节点的一部分,因为它似乎默默地失败了。
在上面的例子中,data具有:

data.encoding
=> #<Encoding:ASCII-8BIT>

你懂的
我显然需要做些什么来正确地解析这一切,但我不清楚那是什么。
我相信也许数据正在从字节字符串转换为字符串,但这一定是在幕后自动发生的

quhf5bfb

quhf5bfb1#

什么不起作用(但适用于其他地区的所有UTF-8格式的Amazon报告):

report_result, _status_code, headers = importer.api.get_report_with_http_info(report_id)
report_document_id = report_result.report_document_id
report_document = importer.api.get_report_document(report_document_id)
url = report_document.url
content = Faraday.get(url).body
p "Content is #{content.encoding}"
data = AmzSpApi.inflate_document(content, report_document)
p "Data is #{data.encoding}"
xml = Nokogiri::XML(data)
p "We found #{xml.xpath("//Order").count} orders"

输出:

"Content is ASCII-8BIT"
"Data is ASCII-8BIT"
"We found 1 orders"

在上面的例子中,xml将是格式错误的,不能工作(因此是1阶)
什么工作:

report_result, _status_code, headers = importer.api.get_report_with_http_info(report_id)
report_document_id = report_result.report_document_id
report_document = importer.api.get_report_document(report_document_id)
url = report_document.url
content = Faraday.get(url).body
p "Content is #{content.encoding}"
data = AmzSpApi.inflate_document(content, report_document).gsub("CP932", "UTF-8")
p "Data is #{data.encoding}"
xml = Nokogiri::XML(data)
p "We found #{xml.xpath("//Order").count} orders"

输出:

=> "Content is ASCII-8BIT"
=> "Data is ASCII-8BIT"
=> "We found 151 orders"

问题似乎是Nokogiri(和我发现的其他在线解析器)无法处理表示编码为CP 932的XML标记。
<?xml version="1.0" encoding="CP932"?>
上面的gsub代码也适用于UTF-8文件(因为它什么也不做)
注意:如果您使用HTTParty而不是Faraday,则内容编码为UTF-8而不是ASCII-8BIT,但问题(和解决方案)仍然相同。

相关问题