【问题标题】:Web Scraping Wikipedia - string manipulationWeb Scraping Wikipedia - 字符串操作
【发布时间】:2017-02-17 03:05:48
【问题描述】:

我已经成功地抓取了这个维基百科页面Oscars Nominations 并提取了“提名”下的表格。我可以通过以下代码获取表格:

wiki <- "https://en.wikipedia.org/wiki/89th_Academy_Awards"
text <- wiki %>% 
         read_html() %>% 
         html_nodes('//*[@id="mw-content-text"]/table[3]') %>% 
         html_table()

输出一个“列表”作为名称“文本”

test <- data.frame(one=unlist(text), stringsAsFactors=F)
row.names(test) <- NULL
test <- test[-16,]
nw_lst <- strsplit(test, "\n")

我尝试将结果放在一个 df 中,然后删除一个无用的行,然后在 'nw_lst' 中的换行符正则表达式 '\n' 上的 'strsplit' 输出另一个列表,但有 23 个对应的元素更清晰每个奥斯卡提名的标题如下。然后我想将列表解析为 2 个 df,一个用于最佳影片提名,第二个 df 与其他提名。

oscr.bp <- data.frame(Best.Picture=unlist(nw_lst[[1]]), stringsAsFactors=F)
oscr.bp <- as.data.frame(oscr.bp[-1,], stringsAsFactors=F)
colnames(oscr.bp) <- c("Best.Picture")

所以这是我的问题,一旦我分开提名,我想清理文本。问题是由于某种原因,'stringr' 包中的任何内容都无法删除除电影标题之外的所有不必要的文本。

str_replace_all(oscr.bp$Best.Picture,pattern = "\n", replacement = " ") 
str_replace_all(oscr.bp$Best.Picture,pattern = "[\\^]", replacement = " ") 
str_replace_all(oscr.bp$Best.Picture,pattern = "\"", replacement = " ") 
str_replace_all(oscr.bp$Best.Picture,pattern = "\\s+", replacement = " ") 
str_trim(oscr.bp$Best.Picture,side = "both")

但是当我在我的环境中检查 df 的结构并单击蓝色箭头以查看向量类并将鼠标悬停在 chr 向量上时,但它在字符向量中具有奇怪的形状并且在字符串中具有 |__truncated__但在控制台中检查字符串时不可见。

我只是想知道清理这些字符串的最佳方法,还是另一种方法来获取 &lt;ul&gt;&lt;li&gt; 解析下 HTML 节点中每个提名的标题名称?除了查看源代码并使用选择器小工具找到我需要的内容外,对基本的 HTML 代码含义了解不多。

【问题讨论】:

  • “字符向量中有奇怪的形状”——这可能是一个编码问题(参见?Encoding)。你试过XML包里的html解析功能吗?

标签: r web-scraping rstudio wiki


【解决方案1】:

另一种方法是针对每个人 &lt;td&gt; 然后使用可用的元数据:

library(rvest)
library(tidyverse)

pg <- read_html("https://en.wikipedia.org/wiki/89th_Academy_Awards")

html_nodes(pg, xpath=".//h2[span/@id = 'Nominees']/following-sibling::table[1]") %>%
  html_nodes("td") %>%
  map_df(function(x) {
    category <- html_nodes(x, "div") %>% html_text()
    html_nodes(x, "li") %>%
      map_df(function(y) {
        html_nodes(y, "a") %>% html_attr("title") -> tmp
        movie <- tmp[1]
        nominee <- tmp[-1]
        data_frame(movie=rep(movie, length(nominee)), nominee)
      }) %>%
      mutate(category = category)
  }) %>%
  select(category, movie, nominee)
## # A tibble: 236 × 3
##        category          movie           nominee
##           <chr>          <chr>             <chr>
## 1  Best Picture Arrival (film)        Shawn Levy
## 2  Best Picture Arrival (film)       David Linde
## 3  Best Picture  Fences (film)       Scott Rudin
## 4  Best Picture  Fences (film) Denzel Washington
## 5  Best Picture  Fences (film)        Todd Black
## 6  Best Picture  Hacksaw Ridge     Bill Mechanic
## 7  Best Picture  Hacksaw Ridge      David Permut
## 8  Best Picture Hidden Figures   Donna Gigliotti
## 9  Best Picture Hidden Figures     Peter Chernin
## 10 Best Picture Hidden Figures     Jenno Topping
## # ... with 226 more rows

【讨论】:

  • 这正是我想要完成的。您是如何在代码开头获得该 xpath 的?您是使用工具还是仅查看 HTML 代码?
  • 只看代码。 XPath 和我有着长期的爱/恨关系。
  • 这适用于最佳影片,但如果我们以最佳导演为例,导演的名字是第一位的。所以最终“电影”列包含人名,而“提名”列包含电影标题。
  • 是的。出于某种原因,它被称为“网络抓取”而不是“使用网络 api”。你必须真正知道你在为前者做什么,而不是为后者做什么。如果您还有其他需要@MTurgeon,您应该提出一个新问题。
  • @hrbrmstr 不需要其他问题。我的需求得到满足,现在 cmets 中有一个免责声明来回答您的问题
【解决方案2】:

我相信我有解决问题的方法,但编码问题可能仍然存在。实际任务是简单地获取电影标题,然后是破折号字符。

我从粘贴您的代码开始,除了指定 html_nodes 参数是 xpath 而不是 css(在您的问题中向我抛出错误)。

wiki <- "https://en.wikipedia.org/wiki/89th_Academy_Awards"
text <- wiki %>% 
         read_html() %>% 
         html_nodes(xpath='//*[@id="mw-content-text"]/table[3]') %>% 
         html_table()

然后当你定义 Best.Picture 时我就停下来了。除非我遗漏了什么,否则将其强制转换为 data.frame 是不必要的,因为它只是一个向量。

Best.Picture <- unlist(nw_lst[[1]])[-1]

然后我拆分Best.Picture 字符向量中的每个条目,并应用于拆分列表(每个元素都是一个向量,用于隔离每个向量元素中的每个字符)。我们这样做是为了确定魔术破折号符号在哪里(我只是直接从终端复制并粘贴了它,因为破折号不是“-”,而是一些类似的符号(这可能说明了评论中引用的编码问题。

dash <- sapply(strsplit(Best.Picture, ''), function(x){which(x == '–')})

在我们确定了破折号在Best.Picture 元素的每个元素中的位置之后,我们可以使用substr 将向量截断为仅我们关心的部分。如果您想安全起见,您可以将所有内容剪切到 dash - 1 (这也会剪切破折号),然后使用 trimws 删除前导或尾随空格。

movTitle <- substr(Best.Picture, 1, dash-2)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-09-04
    • 1970-01-01
    • 1970-01-01
    • 2011-05-12
    • 1970-01-01
    相关资源
    最近更新 更多