使用rvest进行网页爬取循环时遇到的三类问题
解决期刊引文爬取的三个常见问题
我来帮你逐个搞定这三个爬取和数据整理的问题,直接上修改后的代码和详细解释:
问题1:生成长向量而非表格
你的scrape函数返回的是cbind生成的矩阵,再加上lapply会把每个网页的结果存成列表元素,自然没法直接形成规整的表格。我们需要让每个scrape调用返回单行数据框,之后再把所有行合并成完整的DataFrame。
问题2:read_xml报错factor类型
read.csv默认会把字符型列(比如你的URL链接)转换成factor类型,而read_html需要的是纯字符型输入。解决方法很简单:读取CSV时加上stringsAsFactors = FALSE,或者用readr::read_csv(更推荐,默认不转factor)。
问题3:多个邮箱生成多行数据
当一篇文章有多个邮箱时,我们需要让同一篇文章的其他信息重复对应每个邮箱,生成多行数据。这里用tidyr::unnest就能轻松实现,不用手动写复杂的循环。
修改后的完整代码
先加载需要的工具包:
library(rvest) library(dplyr) library(tidyr) # 专门处理多行拆分的工具 library(purrr) # 更便捷的列表处理
改进后的爬取函数
scrape <- function(x){ doc <- read_html(x) # 用html_text2替代html_text,自动清理多余换行和空格,提取的文本更干净 author <- html_text2(html_nodes(doc, '.art_authors')) year <- html_text2(html_nodes(doc, '.year')) journalName <- html_text2(html_nodes(doc, '.journalName')) art_title <- html_text2(html_nodes(doc, '.art_title')) volume <- html_text2(html_nodes(doc, '.volume')) page <- html_text2(html_nodes(doc, '.page')) email <- html_text2(html_nodes(doc, xpath = "//a[@class = 'email']")) # 处理空值:如果字段为空,设为NA;邮箱为空时设为长度1的NA,方便后续合并 author <- if(length(author) == 0) NA_character_ else author year <- if(length(year) == 0) NA_character_ else year journalName <- if(length(journalName) == 0) NA_character_ else journalName art_title <- if(length(art_title) == 0) NA_character_ else art_title volume <- if(length(volume) == 0) NA_character_ else volume page <- if(length(page) == 0) NA_character_ else page email <- if(length(email) == 0) NA_character_ else email # 返回数据框:用tibble替代基础data.frame,更适配tidyverse工具链 tibble( Author = author, Year = year, Journal_Name = journalName, Art_Title = art_title, Volume = volume, Page = page, Email = email ) %>% unnest_longer(Email) # 自动把多个邮箱拆分成单独行,其他字段同步重复 }
用URL向量直接测试
data <- c("http://journals.sagepub.com/doi/abs/10.3102/0013189X037001060", "http://journals.sagepub.com/doi/abs/10.3102/0013189X037002102", "http://journals.sagepub.com/doi/abs/10.3102/0013189X037002104", "http://journals.sagepub.com/doi/full/10.3102/0013189X17737739") # 用map_dfr自动合并所有爬取结果成一个数据框,比lapply+do.call更简洁 y <- map_dfr(data, scrape) View(y)
从CSV加载URL的正确方式
# 方法1:基础包read.csv,指定不转factor data <- read.csv("link_test.csv", stringsAsFactors = FALSE) y <- map_dfr(data$link, scrape) # 方法2:推荐用readr包,默认不转factor,读取速度也更快 # data <- read_csv("link_test.csv") # y <- map_dfr(data$link, scrape)
关键改动说明
- 返回标准数据框:用
tibble替代cbind生成的矩阵,确保每个爬取结果是规整的数据结构,方便后续合并。 - 解决factor类型报错:读取CSV时禁用自动转factor,保证URL是纯字符型,让
read_html可以正常处理。 - 自动拆分多邮箱:
unnest_longer(Email)会自动把每个邮箱拆成单独一行,同时重复其他字段的内容,完美匹配你的需求。 - 更稳定的文本提取:
html_text2会自动清理网页文本中的多余换行、空格,提取的内容更整洁。
内容的提问来源于stack exchange,提问作者JWH2006
相关产品推荐
相关产品推荐

