美文网首页R语言 生信P
R爬虫实战—抓取PubMed文章的基本信息

R爬虫实战—抓取PubMed文章的基本信息

作者: Clariom | 来源:发表于2020-08-20 09:26 被阅读0次

    前几期简单介绍了一系列R爬虫的基础知识、核心R包以及一些辅助工具,其中,基础知识包括R爬虫必备基础——HTML和CSS初识R爬虫必备基础——静态网页+动态网页R爬虫必备基础—HTTP协议R爬虫必备基础—动态异步加载;核心R包包括R爬虫必备——rvest包的使用R爬虫必备基础—rvest为什么不用于动态网页?R爬虫必备—httr+POST请求类爬虫(网易云课堂)R爬虫必备——httr+GET请求类爬虫(解螺旋课程);辅助工具包括R爬虫必备基础——CSS+SelectorGadgetR爬虫必备基础—Chrome开发者工具(F12)。今天呢,通过爬取PubMed实战案例来进一步巩固前期所学。

    爬取目的

    当要开展某个领域的研究时,需要检索查看下该领域都研究了什么。通过pubmed检索后文章可能非常多,这个时候不可能每篇都通读,通常都是先看下摘要,然后再选择感兴趣的进行全文查阅。为了避免一篇篇在线点击查阅,也不便于做记录,可以将该领域文章的基本信息(包括摘要内容)爬取下来,然后本地查看,最后通过PMID号下载感兴趣全文。下面,将以lncRNA为关键词,爬取2020年发表的综述类文章的题目、PMID号、作者、发表杂志、摘要等信息。

    网页分析

    首先打开网站,输入lncRNA关键词,选择review,然后时间限制在2020年,option选择Abstract,得到如下检索界面,网址为:https://pubmed.ncbi.nlm.nih.gov/?term=lncRNA&filter=pubt.review&filter=years.2020-2020&format=abstract,这为第一条信息,共计显示10条记录。从下图我们知道该网页是个带有Query String Parameters 参数的GET类请求

    image image

    共计有390条信息,需要完全获取该怎么办?先尝试点击more后,发现展示了page2(共计10条),将鼠标往下拉,网址会添加&page=2,最终网址:https://pubmed.ncbi.nlm.nih.gov/?term=lncRNA&filter=pubt.review&filter=years.2020-2020&format=abstract&page=2,Ctrl+R刷新开发工具后台,预览的结果是11-20条。按照如此规律,就可以构建有规律的网址,如下所示。共计390条记录,每页显示10条,那需要39页。按照这个思路就可以爬取所有信息。

    
    https://pubmed.ncbi.nlm.nih.gov/?term=lncRNA&filter=pubt.review&filter=years.2020-2020&format=abstract
    https://pubmed.ncbi.nlm.nih.gov/?term=lncRNA&filter=pubt.review&filter=years.2020-2020&format=abstract&page=2
    https://pubmed.ncbi.nlm.nih.gov/?term=lncRNA&filter=pubt.review&filter=years.2020-2020&format=abstract&page=3
    https://pubmed.ncbi.nlm.nih.gov/?term=lncRNA&filter=pubt.review&filter=years.2020-2020&format=abstract&page=4
    https://pubmed.ncbi.nlm.nih.gov/?term=lncRNA&filter=pubt.review&filter=years.2020-2020&format=abstract&page=5
    https://pubmed.ncbi.nlm.nih.gov/?term=lncRNA&filter=pubt.review&filter=years.2020-2020&format=abstract&page=6
    ...
    https://pubmed.ncbi.nlm.nih.gov/?term=lncRNA&filter=pubt.review&filter=years.2020-2020&format=abstract&page=39
    

    但是,还有另一种方式,回到首页,打开开发后台,定位到XHR面板。然后点击more,一直more,注意这个过程不要刷新页面****,发现XHR面板上每点击一次more,就会生成一个more,同时你主网页网址维持不变。这是个典型的通过more达到异步加载的目的。

    image

    查看这几个more的Headers信息,会发现明显的规律(如下所示),都是向https://pubmed.ncbi.nlm.nih.gov/more/发起请求,通过POST提交表单信息,只要修改page即可,按照这个思路也可以爬取所有文章信息。需要注意的是,这种动态加载的POST请求类爬虫是从第二页开始的。

    image

    爬虫策略

    第一种策略

    构建有规律的网址【https://pubmed.ncbi.nlm.nih.gov/?term=lncRNA&filter=pubt.review&filter=years.2020-2020&page=页码】 ,共计390条记录,每页显示10条,那需要39页,可以按照这个思路进行爬取,这里它属于一种GET请求类爬虫。对于这类爬虫,有以下几种爬取方式:

    • 方法一:rvest,不推荐,之前有专门有推文说过原因。爬取少量的确也能成功,但很容易被封。
    • 方法二:httr+rvest组合(推荐),httr解决网络请求问题,rvest解决网页解析和信息提取。
    • 方法三:RCurl+XML组合,RCurl解决网络请求问题,XML解决网页解析和信息提取。
    第二种策略

    根据more发起的动态加载,构建有规律的POST请求,也可以进行爬取,这里它属于一种POST请求类爬虫。对于这类爬虫,主要有以下两种爬取方式:

    • 方法一:httr+rvest组合(推荐),httr解决网络请求问题,rvest解决网页解析和信息提取。
    • 方法二:RCurl+XML组合,RCurl解决网络请求问题,XML

    今天呢,先介绍第一种爬取策略的方法二:httr+rvest组合。

    rm(list=ls())
    #加载所需要的R包,没安装的提前安装
    library("httr") 
    library("magrittr")
    library("rvest")
    library("xml2")
    library("stringr")
    
    #首先构造第一页的url
    url <- c('https://pubmed.ncbi.nlm.nih.gov/?term=lncRNA&filter=pubt.review&filter=years.2020-2020&format=abstract')
    #构造请求提交信息,根据Request headers的内容填写。
    mycookie <- 'ncbi_sid=CE8CCD5EEB3B8391_1825SID; _ga=GA1.2.284594426.1588836424; entrezSort=pubmed:; MyNcbiSigninPreferences=O25jYmlscyY%3D; WebCubbyUser=UFSJUQUQPJOPNU17DZHC79N0PN7V14ZM%3Blogged-in%3Dtrue%3Bmy-name%3Dyuanjiuyun%3Bpersistent%3Dtrue%40CE8CCD5EEB3B8391_1825SID; labs-pubmed-csrftoken=xKN3RWUpM9RzswSjmTAC4JiUbvWAqrtcAg0HGZHagClqGImTVx95DdMmRl117GHI; pmc.article.report=; _gid=GA1.2.1075622582.1592800677; sessionid=cwuommk94ngosh06896fslsck0ezxmb6; pm_ncbi_alert_dismiss=nCoV; pm-sid=U_VuaPR2IXwdvtAlIoP3EQ:bac28257745cb37e186420a3d2058fb9; pm-adjnav-sid=yWapb_Ia32GrozOuqYVerQ:54e8575844b60ed67d1216e4ff365989; pm-iosp=; ncbi_pinger=N4IgDgTgpgbg+mAFgSwCYgFwgCwE4BCAIgAykCM+AbAKzaHYBi1ppATPgwMysDsx2rAMKdCAOjKiAtnDJkQAGhABXAHYAbAPYBDVCqgAPAC6ZQrTOCUAjSVHSLO5sFZt2c5gM5QtEAMaJo7kpqxorU5gogsuZyiqzE5nhELBQ0dIzMLOxcvPxCIuJSMjEgrHJYTta2GBUuGJ7efgFBhhgAcgDyrQCiEaxm5c62oio+lsjDapLDyIiiAOYaML240dSclBGc8VgAHJTYm2WRaxv2/SA7rAf2DlgAZlpqnpsHWIYQSlCbO+H2K7vYHisH6KbDbC5A1grUG3EDEURQ0TxUGvZTqbS6AwhHBhLDFNbmSiUMyhVGQiLUDZYZEgag8cw0yhHMiUYjQkBEjxeXyIEAAXz5QA'
    #注意比较,保留不变的参数
    myheaders <- c('accept' ='text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
                   'accept-encoding' = 'gzip, deflate, br',
                   'accept-language' = 'zh-CN,zh;q=0.9',
                   'user-agent' = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36',
                   'referer'= 'https://pubmed.ncbi.nlm.nih.gov/?term=lncRNA&filter=years.2020-2020&format=abstract'
    )
    
    #构造请求头参数信息,根据Query String Parameters内容填写
    mypayload <- list("term" = "lncRNA",
                      "filter" = "pubt.review",
                      "filter"= "years.2020-2020",
                      "format" = "abstract")
    
    #执行第一页,httr的GET函数
    response <- GET(url = url, add_headers(.headers = myheaders), set_cookies(.cookies =mycookie),timeout(30),query = mypayload)
    
    #读入并解析网页内容
    web <- read_html(response, encoding ="utf-8")
    paper_inf <- data.frame()
    #提取文章题目
    paper_title <- web %>% html_nodes("div.full-view h1.heading-title a") %>% html_text() %>% str_replace_all("  ","") %>%str_replace_all("\n","")
    #提取文章PMID号
    paper_PMID <- web %>% html_nodes("ul.identifiers li span.pubmed strong.current-id") %>% html_text()
    paper_PMID <- paper_PMID[seq(2,length(paper_PMID),2)]
    #提取发表的杂志
    paper_journal <- web %>% html_nodes("div.journal-actions button") %>% html_attr("title")
    paper_journal <- paper_journal[seq(2,length(paper_journal),2)]
    #提取文章摘要
    paper_abstract <- web %>% html_nodes("div.abstract div.selected") %>% html_text() %>% str_replace_all("\n","") %>% str_replace_all("  ","")
    #提取文章作者
    paper_author <- web %>% html_nodes("div.authors-list") %>% html_text() %>% str_replace_all("\n","") %>% str_replace_all("  ","") %>% str_replace_all("(\u00A0)","")
    paper_author <- paper_author[seq(2,length(paper_author),2)]
    #创建数据框存储以上信息
    papers <- data.frame(paper_title,paper_author,paper_journal,paper_abstract,paper_PMID)
    paper_inf <- rbind(paper_inf,papers)
    
    
    #接下来,利用循环,从第二页开始
    for (i in 2:5){
      #首先构造第一页的url
      url <- c('https://pubmed.ncbi.nlm.nih.gov/?term=lncRNA&filter=pubt.review&filter=years.2020-2020&format=abstract')
      #构造请求提交信息,根据Request headers的内容填写。
      mycookie <- 'ncbi_sid=CE8CCD5EEB3B8391_1825SID; _ga=GA1.2.284594426.1588836424; entrezSort=pubmed:; MyNcbiSigninPreferences=O25jYmlscyY%3D; WebCubbyUser=UFSJUQUQPJOPNU17DZHC79N0PN7V14ZM%3Blogged-in%3Dtrue%3Bmy-name%3Dyuanjiuyun%3Bpersistent%3Dtrue%40CE8CCD5EEB3B8391_1825SID; labs-pubmed-csrftoken=xKN3RWUpM9RzswSjmTAC4JiUbvWAqrtcAg0HGZHagClqGImTVx95DdMmRl117GHI; pmc.article.report=; _gid=GA1.2.1075622582.1592800677; sessionid=cwuommk94ngosh06896fslsck0ezxmb6; pm_ncbi_alert_dismiss=nCoV; pm-sid=U_VuaPR2IXwdvtAlIoP3EQ:bac28257745cb37e186420a3d2058fb9; pm-adjnav-sid=yWapb_Ia32GrozOuqYVerQ:54e8575844b60ed67d1216e4ff365989; pm-iosp=; ncbi_pinger=N4IgDgTgpgbg+mAFgSwCYgFwgCwE4BCAIgAykCM+AbAKzaHYBi1ppATPgwMysDsx2rAMKdCAOjKiAtnDJkQAGhABXAHYAbAPYBDVCqgAPAC6ZQrTOCUAjSVHSLO5sFZt2c5gM5QtEAMaJo7kpqxorU5gogsuZyiqzE5nhELBQ0dIzMLOxcvPxCIuJSMjEgrHJYTta2GBUuGJ7efgFBhhgAcgDyrQCiEaxm5c62oio+lsjDapLDyIiiAOYaML240dSclBGc8VgAHJTYm2WRaxv2/SA7rAf2DlgAZlpqnpsHWIYQSlCbO+H2K7vYHisH6KbDbC5A1grUG3EDEURQ0TxUGvZTqbS6AwhHBhLDFNbmSiUMyhVGQiLUDZYZEgag8cw0yhHMiUYjQkBEjxeXyIEAAXz5QA'
      #注意比较,保留不变的参数
      myheaders <- c('accept' ='text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
                     'accept-encoding' = 'gzip, deflate, br',
                     'accept-language' = 'zh-CN,zh;q=0.9',
                     'user-agent' = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36',
                     'referer'= 'https://pubmed.ncbi.nlm.nih.gov/?term=lncRNA&filter=years.2020-2020&format=abstract')
      #构造请求头参数信息,根据Query String Parameters内容填写
      mypayload <- list("term" = "lncRNA",
                        "filter" = "pubt.review",
                        "filter"= "years.2020-2020",
                        "format" = "abstract",
                        "page" = i)
      #执行第一页,httr的GET函数
      response <- GET(url = url, add_headers(.headers = myheaders),set_cookies(.cookies =mycookie),timeout(30),query = mypayload)
      #读入并解析网页内容
      web <- read_html(response, encoding ="utf-8")
      #提取文章题目
      paper_title <- web %>% html_nodes("div.full-view h1.heading-title a") %>% html_text() %>% str_replace_all("  ","") %>%str_replace_all("\n","")
      #提取文章PMID号
      paper_PMID <- web %>% html_nodes("ul.identifiers li span.pubmed strong.current-id") %>% html_text()
      paper_PMID <- paper_PMID[seq(2,length(paper_PMID),2)]
      #提取发表的杂志
      paper_journal <- web %>% html_nodes("div.journal-actions button") %>% html_attr("title")
      paper_journal <- paper_journal[seq(2,length(paper_journal),2)]
      #提取文章摘要
      paper_abstract <- web %>% html_nodes("div.abstract div.selected") %>% html_text() %>% str_replace_all("\n","")
      #提取文章作者
      paper_author <- web %>% html_nodes("div.authors-list") %>% html_text() %>% str_replace_all("\n","") %>% str_replace_all("  ","") %>% str_replace_all("(\u00A0)","")
      paper_author <- paper_author[seq(2,length(paper_author),2)]
      #创建数据框存储以上信息
      papers <- data.frame(paper_title,paper_author,paper_journal,paper_abstract,paper_PMID)
      paper_inf <- rbind(paper_inf,papers)
    }
    
    #将数据写入csv文档
    write.csv(paper_inf, file="paper_lncRNA_revew_2020.csv")
    

    运行结束后,共计获取390条信息,内容如下:

    image

    以上代码主要是为了展示httr+rvest这类组合如何完成GET请求类爬虫,整体代码是比较简单粗糙的,没有添加访问出错时的应对方式,也没有设置代理池,且访问速度也不是很快,应付少量的文章爬取还是OK的。如果有小伙伴,的确有整理汇总Pubmed文章信息的需求,可以直接从官网上导出即可。新版PubMed可以提供一次性导出(10000条信息以内),具体方法,根据自身要求设置筛选条件后,点击save,选择All results即可。

    image

    结果如下图所示,内容很多,但却没有文章摘要信息,仍是美中不足(虽然网站是可以导出摘要信息的,但为txt文本格式,不直观)。所以,爬虫在一定程度上来说还是有用的。

    image

    当爬取到这些文章的基本信息后,可以本地查阅每篇文章的主要内容。对于看英文有困难,可以将其翻译成中文。将输出的文章信息修改成xls格式,然后打开https://translate.yandex.com/doc,将文件上传上去即可全文翻译。

    往期回顾
    R爬虫在工作中的一点妙用
    R爬虫必备基础——HTML和CSS初识
    R爬虫必备基础——静态网页+动态网页
    R爬虫必备——rvest包的使用
    R爬虫必备基础——CSS+SelectorGadget
    R爬虫必备基础—Chrome开发者工具(F12)
    R爬虫必备基础—HTTP协议
    R爬虫必备—httr+POST请求类爬虫(网易云课堂)
    R爬虫必备基础—rvest为什么不用于动态网页?
    R爬虫必备——httr+GET请求类爬虫(解螺旋课程)

    相关文章

      网友评论

        本文标题:R爬虫实战—抓取PubMed文章的基本信息

        本文链接:https://www.haomeiwen.com/subject/btevrktx.html