使用 Google Apps Script 从网页中提取数据时的字符编码问题

Ice*_*ape 4 extract character-encoding hebrew windows-1255 google-apps-script

我已经使用 Google Apps 脚本编写了一个脚本,用于将网页中的文本提取到 Google 表格中。我只需要这个脚本来处理特定的网页,所以它不需要是通用的。该脚本几乎完全按照我的要求工作,只是我遇到了字符编码问题。我正在提取希伯来语和英语文本。HTML 中的元标记具有 charset=Windows-1255。英语提取完美,但希伯来语显示为包含问号的黑色菱形。

我发现这个问题说将数据传递到 blob 然后使用 getDataAsString 方法转换为另一种编码。我尝试转换为不同的编码并得到不同的结果。UTF-8 显示带问号的黑色菱形,UTF-16 显示韩语,ISO 8859-8 返回一个错误并说它不是一个有效的参数,原始的 Windows-1255 显示一个希伯来字符,但显示一堆其他乱码。

但是,我可以手动将希伯来语文本复制并粘贴到 Google 表格中,并且显示正确。

我什至测试过直接从 Google Apps 脚本代码传递希伯来语,如下所示:

function passHebrew() {
  return "??????????";
}
Run Code Online (Sandbox Code Playgroud)

这会在 Google 表格上正确显示希伯来语文本。

希伯来语显示为我提到的每种编码

我的代码如下:

function passHebrew() {
  return "??????????";
}
Run Code Online (Sandbox Code Playgroud)

我忽略、误解或做错了什么?我对编码的工作原理不太了解,所以我不明白为什么将其转换为 UTF-8 不起作用。

Mog*_*dad 6

您的问题出现在您作为编码问题注释的行之前:因为 UrlFetchApp 的默认编码从一开始就修改了 unicode 文本。

您应该使用返回编码为给定字符集字符串的 HTTP 响应内容.getContentText()方法的变体对于您的情况:

var xml = UrlFetchApp.fetch(url).getContentText("Windows-1255");
Run Code Online (Sandbox Code Playgroud)

这应该是您需要更改的全部内容,尽管blob()不再需要变通方法。(不过,这是无害的。)其他评论:

  • 逻辑 OR 运算符 ( ||) 对设置默认值非常有帮助。我已经调整了前几行以启用测试,但仍然让函数使用参数正常运行。

  • 在用字符串填充空数组之前设置空数组的方式是 Bad JavaScript;这是不需要的复杂代码,所以扔掉它。相反,我们将声明array数组,然后push()在其上添加行。

  • .replace()功能可以与更巧妙正则表达式使用减少; 我已经包含了真正棘手的演示的 URL。

  • \n文本中有换行符,我猜对于您的目的来说是不必要的,因此也replace()为它们添加了一个。

这是你剩下的:

function parseText(book, chapter) {
  var bk = book || '04'; //hard-coded for testing purposes
  var ch = chapter || '01'; //hard-coded for testing purposes
  var url = 'http://www.mechon-mamre.org/p/pt/pt' + bk + ch + '.htm';

  var xml = UrlFetchApp.fetch(url).getContentText("Windows-1255");

  //I had to "fix" these xml errors for XmlService.parse(xml) below
  //to function.
  xml = xml.replace(/(<!DOCTYPE.*EN")>/gi, '$1 "">')
           .replace(/(<(LINK|meta).*>)/gi,'$1</$2>')        // https://regex101.com/r/nH3pU8/1
           .replace(/(<.*?=)([^"']*?)([ >])/gi,'$1"$2"$3')  // https://regex101.com/r/eP7wO7/1
           .replace(/<BR>/gi, '<BR/>')
           .replace(/\n/g, '')

  //This section is the specific route to the table in the page I want
  var document = XmlService.parse(xml);
  var body = document.getRootElement().getChildren("BODY");
  var maintable = body[0].getChildren("TABLE");
  var maintablechildren = maintable[0].getChildren();

  //This is where the table gets parsed into the array
  var array = [];
  for (var i = 0; i < maintablechildren.length; i++) {
    var verse = maintablechildren[i].getChildren();

    //I originally tried verse[0].getText() but it didn't work.** It does now!
    var hebrew = verse[0].getText();
    //This array receives the English text and works fine.
    var english = verse[1].getText();
    array.push([hebrew,english]);
  }

  return array;
}
Run Code Online (Sandbox Code Playgroud)

结果

 [
  [
    "  ?????????? ?????? ???-?????? ??????????? ??????, ???????? ??????:  ???????? ???????? ????????? ?????????? ??????????, ???????? ??????? ?????????--??????.",
    " And the LORD spoke unto Moses in the wilderness of Sinai, in the tent of meeting, on the first day of the second month, in the second year after they were come out of the land of Egypt, saying:"
  ],
  [
    "  ??????, ???-????? ????-????? ??????-??????????, ???????????????, ?????? ???????--??????????? ???????, ????-????? ??????????????.",
    " 'Take ye the sum of all the congregation of the children of Israel, by their families, by their fathers' houses, according to the number of names, every male, by their polls;"
  ],
  [
    "  ?????? ????????? ?????? ?????????, ????-????? ????? ?????????????--?????????? ????? ???????????, ?????? ?????????.",
    " from twenty years old and upward, all that are able to go forth to war in Israel: ye shall number them by their hosts, even thou and Aaron."
  ],
  ...
Run Code Online (Sandbox Code Playgroud)