好久没有用R了,今天复习了下,用rvest写了个抓取 http://pubmed.cn 网站关键字搜索结果的脚本,分享一下。
需求
- 按关键字搜索, 并记录文章列表中的链接等信息。
- 打开文章页面, 提取其中的abstract摘要信息。
分析网站请求
打开网站, 输入关键字 disease ,可以得到搜索链接,明显是GET请求
http://pubmed.cn/search?q=disease&p=2&pn=20&vt=Summary&ot=PublicationDate&st=main&dt=&ft=
观察链接,可以看出 q=disease 是关键字, p=2 是页码, pn=20 是每页记录数, 其它的参数也都可以尝试出来
搜索列表抓取函数
library("rvest")
getPageList <- function(purl){
# 读取页面
page <- read_html(url, encoding="utf8")
# 按照CSS选择器的语法, 选择页面中 <form id="EFORM"><div id="SFW"><div class="rprt">...</div></div></form> 中的内容
tmp <- html_nodes(page, css="form#EForm>div#SFW>div.rprt")
# 选择<h3 class="title" title="..."></h3> 中的 title="..." 属性值
title <- html_nodes(tmp, css="h3.title") %>% html_attr("title")
# 选择href属性值
furl <- html_nodes(tmp, css="h3.title>a[target=_blank]") %>% html_attr("href")
# 选择authors等标签内的文本, 并进行gsub处理掉其中的空格等多余字符
authors <- html_nodes(tmp, css="p.authors") %>% html_text() %>% gsub(pattern=" {2,}|\n|\r", replacement="")
sources <- html_nodes(tmp, css="p.source") %>% html_text() %>% gsub(pattern="\r|\n *", replacement=" ")
pmid <- html_nodes(tmp, css="p.pmid") %>% html_text() %>% gsub(pattern="\r\n| ?|\u00A0",replacement="")
# 结果保存入dataframe并返回
iData <- data.frame(Title=title, FUrl=furl, Authors=authors, Sources=sources, Pmid=pmid, stringsAsFactors = FALSE)
return(iData)
}
抓取摘要abstract的函数
getAbstract <- function(furl){
# 拼接页面链接
furl <- paste("http://pubmed.cn", furl, sep="")
print(furl)
# 提取出摘要字符串
tmp <- read_html(furl) %>% html_nodes(css="div#SFW>p.abstract") %>% html_text %>% gsub(pattern="Abstract(\\n)*(\\t)*|\\n\\t*", replacement="")
# 有的页面没有摘要信息, 会返回 character(0) , 需要做个处理, 否则会报错
if (identical(tmp, character(0))){
tmp <- ""
}
# 返回结果
return(tmp)
}
抓取单页信息做测试
url <- "http://pubmed.cn/search?q=disease&p=2&pn=20&vt=Summary&ot=PublicationDate&st=main&dt=&ft="
td <- getPageList(url)
for(i in 1:nrow(td)){
td[i,"Abstract"] <- getAbstract(td[i,2])
}
使用apply函数做遍历
R的apply函数族, 效率确实比for循环要快
td["Abstract"] <- apply(td, 1, FUN=function(x){getAbstract(x[2])})