【问题标题】:encoding error with read_htmlread_html 的编码错误
【发布时间】:2017-12-30 14:55:13
【问题描述】:

我正在尝试通过网络抓取 page。我想到了使用包 rvest。 但是,我停留在第一步,即使用 read_html 读取内容。 这是我的代码:

library(rvest)
url <- "http://simec.mec.gov.br/painelObras/recurso.php?obra=17956"
obra_caridade <- read_html(url,
                        encoding = "ISO-8895-1")

我收到以下错误:

Error in doc_parse_raw(x, encoding = encoding, base_url = base_url, as_html = as_html,  : 
  Input is not proper UTF-8, indicate encoding !
Bytes: 0xE3 0x6F 0x20 0x65 [9]

我尝试使用类似问题的答案作为答案,但它没有解决我的问题:

obra_caridade <- read_html(iconv(url, to = "UTF-8"),
                        encoding = "UTF-8")

obra_caridade <- read_html(iconv(url, to = "ISO-8895-1"),
                        encoding = "ISO-8895-1")

两次尝试都返回了类似的错误。 有人对如何解决这个问题有任何建议吗? 这是我的会话信息:

R version 3.3.1 (2016-06-21)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows >= 8 x64 (build 9200)

locale:
[1] LC_COLLATE=Portuguese_Brazil.1252  LC_CTYPE=Portuguese_Brazil.1252   
[3] LC_MONETARY=Portuguese_Brazil.1252 LC_NUMERIC=C                      
[5] LC_TIME=Portuguese_Brazil.1252    

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
[1] rvest_0.3.2 xml2_1.1.1 

loaded via a namespace (and not attached):
[1] httr_1.2.1   magrittr_1.5 R6_2.2.1     tools_3.3.1  curl_2.6     Rcpp_0.12.11

【问题讨论】:

  • 试试encoding = "latin1"
  • 成功了,谢谢?您是否愿意提供一个正确的答案,并解释为什么使用 latin1 有效,而不是 ISO-8895-1(这是页面源代码中设置的字符)?

标签: r web-scraping rvest


【解决方案1】:

有什么问题?

您的问题在于正确确定网页的编码。

好消息
你的方法对我来说看起来不错,因为你查看了源代码并找到了元字符集,以 ISO-8895-1 给出。肯定是ideal to be told the encoding,而不是靠猜测。

坏消息
我不相信编码存在。首先,当我在网上搜索它时,结果往往看起来像是错别字。其次,R 通过iconvlist() 为您提供支持的编码列表。 ISO-8895-1 不在列表中,因此将其作为参数输入 read_html 是没有用的。我认为如果输入不受支持的编码会引发警告会很好,但这似乎不会发生。

快速解决方案
正如@MrFlick 在评论中所建议的那样,使用encoding = "latin1" 似乎可行。
我怀疑 Meta 字符集有错字,应该是 ISO-8859-1(与 latin1 相同)。


猜测编码的技巧

您的浏览器在做什么?
在浏览器中加载页面时,您可以see what encoding it is using 阅读该页面。如果页面看起来正确,这似乎是一个明智的猜测。在这种情况下,Firefox 使用西方编码(即 ISO-8859-1)。

用 R 猜测

  1. rvest::guess_encoding 是一个不错的、用户友好的函数,可以快速估算。您可以为该函数提供一个 url,例如guess_encoding(url),或复制具有更复杂字符的短语,例如guess_encoding("Situação do Termo/Convênio:").
    关于这个函数需要注意的一点是它只能检测 30 种更常见的编码,但还有更多的可能性。

  2. 如前所述,iconvlist() 提供了支持的编码列表。通过遍历这些编码并检查页面中的一些文本以查看它是否符合我们的预期,我们最终应该得到一个可能编码的候选清单(并排除许多编码)。
    示例代码可以在这个答案的底部找到。

决赛
以上所有观点都表明 ISO-8859-1 是对编码的合理猜测。

页面 url 包含一个 .br 扩展名,表明它是巴西语,并且 - according to Wikipedia - 这种编码具有巴西葡萄牙语的完整语言覆盖范围,这表明对于创建该网页的人来说,这可能不是一个疯狂的选择。我相信这也是一种相当常见的编码类型。


代码

“猜测 R”第 2 点的示例代码(使用 iconvlist()):

library(rvest)
url <- "http://simec.mec.gov.br/painelObras/recurso.php?obra=17956"

# 1. See which encodings don't throw an error
read_page <- lapply(unique(iconvlist()), function(encoding_attempt) {

  # Optional print statement to show progress to 1 since this can take some time
  print(match(encoding_attempt, iconvlist()) / length(iconvlist()))

  read_attempt <- tryCatch(expr=read_html(url, encoding=encoding_attempt),
                           error=function(condition) NA,
                           warning=function(condition) message(condition))
  return(read_attempt)
})

names(read_page) <- unique(iconvlist())

# 2. See which encodings correctly display some complex characters
read_phrase <- lapply(x, function(encoded_page) 
  if(!is.na(encoded_page))
    html_text(html_nodes(encoded_page, ".dl-horizontal:nth-child(1) dt")))

# We've ended up with 27 encodings which could be sensible...
encoding_shortlist <- names(read_phrase)[read_phrase == "Situação:"]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-09-06
    • 1970-01-01
    • 2020-12-18
    • 2017-04-26
    • 2011-07-26
    • 2012-02-18
    • 1970-01-01
    • 2017-05-18
    相关资源
    最近更新 更多