R 爬虫之爬取文献信息
开始
今天学习了一些关于 R 爬虫的知识,后续会陆续写一些笔记,当然对于爬虫有更好的一些工具来进行爬取数据,作为入门小白,我自己先从 R 语言尝试开始吧。
我们在浏览器中看到的网页很多都是有 HTML(Hyper Text Markup Language)超文本标记语言构成的树形结构,包括一系列标签,HTML 是一类标记语言而不是编程语言,当然要爬虫的话最好去了解一些最基本的 HTML 和 XML(Extensible Markup Language) 语言知识比较好。html 和 xml 有着类似的树形结构,都是一种标记语言。
今天学习了一下怎么爬取 NCBI 上的文献和基本信息,分享给大家。
试水
我们主要是使用 rvest 这个 R 包来爬取,这个主要应用于静态网页的数据爬取会实用一些,安装:
install.packages('rvest')
我们的目的是搜索感兴趣的关键词,然后对搜索的结果进行爬取。假如我想搜索 2021 年 m6a 相关的所有文章,获取文章的标题
,作者
,网页链接
和摘要内容
。
首先我们打开 NCBI 的 pubmed 网页,筛选 2021 年的 m6a 文章:
可以看到总共有 811 篇文章,我这设置了每页显示 200 篇文献,大家可以自行设置,我们需要获取的该页面的文章标题和作者信息,首先我们爬取的网址就是当前页面的网址,因为显示的限制,所以需要对每个页面的数据进行爬取:
# 加载R包
library(xml2)
library(rvest)
library(tidyverse)
# 爬取2021年m6a文献,总共有811篇,显示200篇文献,爬取5次即可
url <- c('https://pubmed.ncbi.nlm.nih.gov/?term=m6a&filter=years.2021-2021&size=200',
'https://pubmed.ncbi.nlm.nih.gov/?term=m6a&filter=years.2021-2021&size=200&page=2',
'https://pubmed.ncbi.nlm.nih.gov/?term=m6a&filter=years.2021-2021&size=200&page=3',
'https://pubmed.ncbi.nlm.nih.gov/?term=m6a&filter=years.2021-2021&size=200&page=4',
'https://pubmed.ncbi.nlm.nih.gov/?term=m6a&filter=years.2021-2021&size=200&page=5')
# 或者这样也行
root <- 'https://pubmed.ncbi.nlm.nih.gov/?term=m6a&filter=years.2021-2021&size=200&page='
url <- paste(root,1:5,sep = '')
接下来使用 read_html
函数解析网址的内容,html 主要有 head 和 body 两个成分组成:
# 示例,read_html 返回html格式的内容
read_html(url[1],encoding = 'utf-8')
## {html_document}
## <html lang="en">
## [1] <head itemscope itemtype="http://schema.org/WebPage" prefix="og: http://ogp.me/ns#">\n<meta http-equiv ...
## [2] <body>\n\n \n \n <noscript>\n <div class="no-script-banner" id="no-script-banner">\n <div cla ...
获取网址的 html 信息后就需要提取指定节点元素的内容了,需要使用 html_nodes
/html_node
来获取节点信息,该函数只需要输入节点名称或者节点的路径(绝对路径或者相对路径)或者节点选择器。
我们可以在网页上右键点击检查就可看到网页 html 格式的树形结构信息,再点击左上角箭头即可选中在网页中特定内容,右边就会自动定位到该内容的节点位置处:
选中页面特定内容:
接下来我们需要获取该节点的节点名称或者节点路径来提取该节点信息,首先点击我们选中的内容,然后在 3 位置上鼠标右键点击复制选项:
可以看到复制 selector
、复制 XPath
和复制完整的 XPath
三个选项,分别是节点选择器,节点相对路径,节点绝对路径,我们把复制的内容传到 html_nodes
/html_node
函数里就可以得到节点的内容了。
这里我们尝试第一篇文章的标题节点信息获取:
# 节点选择器
read_html(url[1],encoding = 'utf-8') %>%
html_nodes('#search-results > section.search-results-list > div.search-results-chunks > div > article:nth-child(2) > div.docsum-wrap > div.docsum-content > a')
## {xml_nodeset (1)}
## [1] <a class="docsum-title" href="/32749190/" ref="linksrc=docsum_link&article_id=32749190&ordinalpos=1&page=1" data-ga-category="result_ ...
可以看到返回的是完整的该位置处的节点信息,可以使用 html_text
函数从里面提取文本信息,去除 html 格式的标签等不必要信息:
read_html(url[1],encoding = 'utf-8') %>%
html_nodes('#search-results > section.search-results-list > div.search-results-chunks > div > article:nth-child(2) > div.docsum-wrap > div.docsum-content > a') %>%
html_text()
## [1] "\n Comprehensive analysis of the transcriptome-wide m6A methylome in colorectal cancer by MeRIP sequencing.\n "
# 加上trim = T 参数简洁化内容
read_html(url[1],encoding = 'utf-8') %>%
html_nodes('#search-results > section.search-results-list > div.search-results-chunks > div > article:nth-child(2) > div.docsum-wrap > div.docsum-content > a') %>%
html_text(trim = T)
## [1] "Comprehensive analysis of the transcriptome-wide m6A methylome in colorectal cancer by MeRIP sequencing."
同样的我们使用节点的相对路径和绝对路径也能得到相同的结果,此时需要用 xpath 参数指明:
# 相对路径
read_html(url[1],encoding = 'utf-8') %>%
html_nodes(xpath = '//*[@id="search-results"]/section[1]/div[1]/div/article[1]/div[2]/div[1]/a') %>%
html_text(trim = T)
## [1] "Comprehensive analysis of the transcriptome-wide m6A methylome in colorectal cancer by MeRIP sequencing."
# 绝对路径
read_html(url[1],encoding = 'utf-8') %>%
html_nodes(xpath = '/html/body/main/div[9]/div[2]/section[1]/div[1]/div/article[1]/div[2]/div[1]/a') %>%
html_text(trim = T)
## [1] "Comprehensive analysis of the transcriptome-wide m6A methylome in colorectal cancer by MeRIP sequencing."
此外我们可以使用 SelectorGadget
网页插件来获取节点名称,插件安装直接去官网:https://selectorgadget.com/,拉到最下面,把 SelectorGadget
拉到收藏夹就可以使用了:
来到我们爬取的网页,点击 SelectorGadget,选择特定要获取的网页内容,复制节点名称就可以了,这个也可以复制 xpath 相对路径:
尝试一下:
# 节点名称
read_html(url[1],encoding = 'utf-8') %>%
html_nodes('.docsum-title') %>%
html_text(trim = T)
## [1] "Comprehensive analysis of the transcriptome-wide m6A methylome in colorectal cancer by MeRIP sequencing."
## [2] "RNA m6A methylation promotes the formation of vasculogenic mimicry in hepatocellular carcinoma via Hippo pathway."
...
## [199] "Main N6-Methyladenosine Readers: YTH Family Proteins in Cancers."
## [200] "FTO overexpression inhibits apoptosis of hypoxia/reoxygenation-treated myocardial cells by regulating m6A modification of Mhrt."
# 批量提取文章标题
title <- c()
for (i in url) {
title <- c(title,read_html(i,encoding = 'utf-8') %>% html_nodes(".docsum-title") %>% html_text(trim = T))
}
# 查看数量
length(title)
## [1] 813
可以看到 .docsum-title
节点名称把该当前网页的所有文章标题都提取了出来,非常的方便。
接下来提取每篇文章的作者信息,同样的操作:
# 2、爬取文章作者
author <- c()
for (i in url) {
author <- c(author,read_html(i,encoding = 'utf-8') %>%
html_nodes('.full-authors') %>%
html_text())
}
# 查看数量
length(author)
## [1] 813
爬取文章地址,其实每篇文章的标题都是一个链接,我们点击标题就可以进入另一个网址,所以只需要获取该标题的超链接地址就可以了,也就是这篇文章的地址,这时我们使用 html_attr 函数来提取标题节点的属性。
在 html 元素中可以看到 href
标识,就是链接地址的 id,我们进入该文章后,这篇文章的地址只是在上级网页地址后加了这个 id:
网址地址:
我们用 html_attrs 获取所有属性:
read_html(url[1],encoding = 'utf-8') %>%
html_nodes('.docsum-title') %>%
html_attrs() %>% head()
[[1]]
class
"docsum-title"
href
"/32749190/"
ref
"linksrc=docsum_link&article_id=32749190&ordinalpos=1&page=1"
data-ga-category
"result_click"
data-ga-action
"1"
data-ga-label
"32749190"
data-full-article-url
"from_term=m6a&from_filter=years.2021-2021&from_size=200&from_page=1&from_pos=1"
data-article-id
"32749190"
...
可以使用 html_attr 指定 name 参数来获取指定属性的内容:
read_html(url[1],encoding = 'utf-8') %>%
html_nodes('.docsum-title') %>%
html_attr(name = 'href') %>% head()
## [1] "/32749190/" "/32920668/" "/32821938/" "/33314339/" "/33070036/" "/33156926/"
## 批量获取文章链接
# 3、爬取文章地址,地址是https://pubmed.ncbi.nlm.nih.gov/加上爬取的编号
web <- c()
for (i in url) {
web <- c(web,read_html(i,encoding = 'utf-8') %>% html_nodes('.docsum-title') %>% html_attr(name = 'href'))
}
# 查看数量
length(web)
## [1] 813
# 连接成网址
web_link <- paste('https://pubmed.ncbi.nlm.nih.gov',web,sep = '')
web_link
## [1] "https://pubmed.ncbi.nlm.nih.gov/32749190/" "https://pubmed.ncbi.nlm.nih.gov/32920668/" "https://pubmed.ncbi.nlm.nih.gov/32821938/"
## [4] "https://pubmed.ncbi.nlm.nih.gov/33314339/" "https://pubmed.ncbi.nlm.nih.gov/33070036/" "https://pubmed.ncbi.nlm.nih.gov/33156926/"
要获取文章的摘要就得进入该网址,在上一步我们已经获取了每篇文章的网址,就可以再次对其解析,然后获取摘要的内容了,基本上是同样的操作:
循环每篇文章,稍微花点时间,R 语言爬虫确实慢,哈哈:
# 4、爬取文章摘要
abstract <- list()
for (i in web_link) {
# 根据节点相对路径提取
# abstract[[i]] <- read_html(i,encoding = 'utf-8') %>% html_nodes(xpath = '//*[@id="enc-abstract"]/p') %>% html_text(trim = T)
# 根据节点绝对路径提取
# abstract[[i]] <- read_html(i,encoding = 'utf-8') %>% html_nodes(xpath = '/html/body/div[5]/main/div[2]/div[2]/p') %>% html_text(trim = T)
# 根据节点名称提取
abstract[[i]] <- read_html(i,encoding = 'utf-8') %>% html_nodes("#enc-abstract > p") %>% html_text(trim = T)
}
# 查看数量
length(abstract)
## [1] 813
爬取的摘要会有 \n 字符,此外有些文章的摘要并不是一个完整的部分,分类了好几点,这样的情况也需要处理一下:
# 去除\n
abstract_clean <- lapply(abstract, gsub,pattern = '\n',replacement = '')
# 连接为一个字符串对于多个部分的摘要
abs_res <- c()
for(i in 1:807){
# 判断元素长度
len = length(abstract_clean[[i]])
if(len == 1){
# 如果只有一个摘要就保存
abs_res <- c(abs_res,abstract_clean[[i]])
}else{
# 如果摘要格式有多个,连接成一个
abs_res <- c(abs_res,paste(abstract_clean[[i]],sep = '-',collapse = ' '))
}
}
# 查看数量
length(abs_res)
## [1] 813
最后我们把所有爬取的内容整理保存为一个表格里并保存输出:
# 5、保存爬取数据
final_res <- data.frame(Title = title,Author = author,web = web_link,Abstract = abs_res)
# 6、保存爬取的数据
write.csv(final_res,file = 'C:/Users/admin/Desktop/m6a_Articles.csv',row.names = F)
我们打开看看:
可以可以,所以今天你学习了吗?
发现更多精彩
关注公众号
欢迎小伙伴留言评论!
今天的分享就到这里了,敬请期待下一篇!
最后欢迎大家分享转发,您的点赞是对我的鼓励和肯定!
如果觉得对您帮助很大,打赏一下吧!
推 荐 阅 读