前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >R 爬虫|手把手带你爬取 800 条文献信息

R 爬虫|手把手带你爬取 800 条文献信息

作者头像
庄闪闪
发布2021-08-20 17:38:25
5.7K0
发布2021-08-20 17:38:25
举报
文章被收录于专栏:庄闪闪的R语言手册

开始

今天学习了一些关于 R 爬虫的知识,后续会陆续写一些笔记,当然对于爬虫有更好的一些工具来进行爬取数据,作为入门小白,我自己先从 R 语言尝试开始吧。

我们在浏览器中看到的网页很多都是有 HTML(Hyper Text Markup Language)超文本标记语言构成的树形结构,包括一系列标签,HTML 是一类标记语言而不是编程语言,当然要爬虫的话最好去了解一些最基本的 HTMLXML(Extensible Markup Language) 语言知识比较好。html 和 xml 有着类似的树形结构,都是一种标记语言。

今天学习了一下怎么爬取 NCBI 上的文献和基本信息,分享给大家。

试水

我们主要是使用 rvest 这个 R 包来爬取,这个主要应用于静态网页的数据爬取会实用一些,安装:

代码语言:javascript
复制
install.packages('rvest')

我们的目的是搜索感兴趣的关键词,然后对搜索的结果进行爬取。假如我想搜索 2021m6a 相关的所有文章,获取文章的标题作者网页链接摘要内容

首先我们打开 NCBI 的 pubmed 网页,筛选 2021 年的 m6a 文章:

可以看到总共有 811 篇文章,我这设置了每页显示 200 篇文献,大家可以自行设置,我们需要获取的该页面的文章标题和作者信息,首先我们爬取的网址就是当前页面的网址,因为显示的限制,所以需要对每个页面的数据进行爬取:

代码语言:javascript
复制
# 加载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 主要有 headbody 两个成分组成:

代码语言:javascript
复制
# 示例,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 函数里就可以得到节点的内容了。

这里我们尝试第一篇文章的标题节点信息获取:

代码语言:javascript
复制
# 节点选择器
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&amp;article_id=32749190&amp;ordinalpos=1&amp;page=1" data-ga-category="result_ ...

可以看到返回的是完整的该位置处的节点信息,可以使用 html_text 函数从里面提取文本信息,去除 html 格式的标签等不必要信息:

代码语言:javascript
复制
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 参数指明:

代码语言:javascript
复制
# 相对路径
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 相对路径:

尝试一下:

代码语言:javascript
复制
# 节点名称
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 节点名称把该当前网页的所有文章标题都提取了出来,非常的方便。

接下来提取每篇文章的作者信息,同样的操作:

代码语言:javascript
复制
# 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 获取所有属性:

代码语言:javascript
复制
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 参数来获取指定属性的内容:

代码语言:javascript
复制
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 语言爬虫确实慢,哈哈:

代码语言:javascript
复制
# 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 字符,此外有些文章的摘要并不是一个完整的部分,分类了好几点,这样的情况也需要处理一下:

代码语言:javascript
复制
# 去除\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

最后我们把所有爬取的内容整理保存为一个表格里并保存输出:

代码语言:javascript
复制
# 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)

我们打开看看:

可以可以,所以今天你学习了吗?

推荐: 可以保存以下照片,在b站扫该二维码,或者b站搜索【庄闪闪】观看Rmarkdown系列的视频教程。Rmarkdown视频新增两节视频(写轮眼幻灯片制作)需要视频内的文档,可在公众号回复【rmarkdown

R沟通|Rmarkdown教程(4)

R沟通|Rmarkdown教程(3)

R沟通|Rmarkdown教程(2)

R沟通|Rmarkdown教程(1)

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-08-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 庄闪闪的R语言手册 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档