R:str_extract 来自 stringr 在使用 rvest 从网络中提取的字符串上的意外行为

R: Unexpected behavior of str_extract from stringr on a string extracted from the web with rvest

我知道这是一个非常奇怪的例子,但它可重现的:

我有一个简单的正则表达式模式来提取一个人的身高:

pattern <- "1\.[0-9]{2} m"

在一个简单的字符串上测试它有效:

library(stringr)
str_extract("1.75 m", pattern)
[1] "1.75 m"

但是,它不适用于我从维基百科抓取的字符串,比如提取 Linda Evangelista 的身高,使用 rvest 中的 html_text:

library(rvest)
url <- "https://en.wikipedia.org/wiki/Linda_Evangelista"
text <- read_html(url) %>%
  html_nodes(".infobox") %>%
  html_text()
text
[1] "Linda Evangelista\n\nEvangelista in August 2004\n\nBorn\n(1965-05-10) May 10, 1965 (age 52)St. Catharines, Ontario, Canada\nOccupation\nModel\nYears active\n1984–1998 (retired)\n2001–present\nSpouse(s)\nGérald Marie\n(m. 1987; div. 1993)\nChildren\n1\nModeling information\nHeight\n5 ft 9 in (1.75 m)[1]\nHair color\nBrown\nEye color\nBlue-green\nManager\nDNA Model Management (New York)Models 1 (London)\nView Management (Barcelona)\nPriscilla's Model Management (Sydney)\n\n"

str_extract(text, pattern)
[1] NA

不过,如果仔细观察,"1.75 m" 字符串就在那里。

可以肯定的是,如果我 手动 将上面的字符串复制粘贴到一个新变量中,str_extract 会按预期工作:

text_manual <- "Linda Evangelista\n\nEvangelista in August 2004\n\nBorn\n(1965-05-10) May 10, 1965 (age 52)St. Catharines, Ontario, Canada\nOccupation\nModel\nYears active\n1984–1998 (retired)\n2001–present\nSpouse(s)\nGérald Marie\n(m. 1987; div. 1993)\nChildren\n1\nModeling information\nHeight\n5 ft 9 in (1.75 m)[1]\nHair color\nBrown\nEye color\nBlue-green\nManager\nDNA Model Management (New York)Models 1 (London)\nView Management (Barcelona)\nPriscilla's Model Management (Sydney)\n\n"
str_extract(text_manual, pattern)
[1] "1.75 m"

注意两个 text 变量都是简单的字符串:

class(text)
[1] "character"
typeof(text)
[1] "character"
class(text_manual)
[1] "character"
typeof(text_manual)
[1] "character"

但它们是一样的吗?否:

text == text_manual
[1] FALSE

他们似乎在第 83 个字符上有所不同:

str_sub(text, 1, 82) == str_sub(text_manual, 1, 82)
[1] TRUE
str_sub(text, 1, 83) == str_sub(text_manual, 1, 83)
[1] FALSE

但我不知道为什么,它们看起来一样,最后一个字符在两者中都是 space:

str_sub(text, 1, 83)
[1] "Linda Evangelista\n\nEvangelista in August 2004\n\nBorn\n(1965-05-10) May 10, 1965 (age "
str_sub(text_manual, 1, 83)
[1] "Linda Evangelista\n\nEvangelista in August 2004\n\nBorn\n(1965-05-10) May 10, 1965 (age "

我想在 Github 上的 stringr 包中打开一个问题,但我不确定它是 stringr 还是 rvest 问题。

有人可能知道这里的问题是什么吗?

这两个字符串不同,因为它们的编码不同:

Encoding(text)
#> [1] "UTF-8"
Encoding(text_manual)
#> [1] "latin1"

utf8ToInt(str_sub(text, 83, 83))
#> [1] 160
utf8ToInt(str_sub(text_manual, 83, 83))
#> [1] 32

intToUtf8(utf8ToInt(str_sub(text, 83, 83)))
#> [1] " "
intToUtf8(utf8ToInt(str_sub(text_manual, 83, 83)))
#> [1] " "

(请注意,Encoding(text_manual) 的结果可能会根据您的区域设置而变化)

为避免此问题,请在 reg-exp 中使用 \s 来匹配任何空白字符:

library(rvest)
library(stringr)
url <- "https://en.wikipedia.org/wiki/Linda_Evangelista"
text <- read_html(url) %>%
    html_nodes(".infobox") %>%
    html_text()

pattern <- "1\.[0-9]{2}\sm"

str_extract(text, pattern)
#> [1] "1.75 m"