R科研作图学习小组

http://group.keyangou.com/RGraph
组长: 管理员:
  • 访问次数:15626
  • 小组等级:8
  • 话题:567
  • 回答:34
  • 签到:357
  • 小组排名:
  • R语言第二期2-2R读取pubmed存入mysql数据库

    真·科研狗 发布于:2018.01.24

    本期任务有三个,看情况2-3周提交作业。

    使用到的包:httr, xml2, RMySQL (前面两个包是第一次作业用到的)


    任务1. 安装mysql数据库

    任务2. 获得并存储cell杂志2017年发表文章的pubmedid

    任务3. 获得并存储cell杂志2017年发表文章的title和abstract


    任务说明:

    任务1.安装mysql数据库。

    mysql数据库是当前最流行的数据库,操作简单,性能优越。你可以单独下载mysql的安装包,并通过windows的命令控制行进行操作,或者通过navicat软件操作。不过鉴于操作难度,推荐下载wampserver这个安装程序,wampserver是一个web服务器软件集合软件,包含了mysql/php/apacha,并且自带了phpmyadmin的mysql管理界面,所以推荐小白用来下载安装(不要求你一定安装wampserver,只要安装了mysql数据库就可以)。

    安装好wampserver之后,打开wampserver,在电脑右下角会有一个图标,等图标变为绿色,右键,可以看到如下界面:

    微信截图_20180124115637.png

    点击phpmyadmin,然后出出现一个mysql数据库管理界面:

    微信截图_20180124115850.png

    点击“New” 新建一个数据库,我们取名为“rdb”表示是R语言的database

    然后进入rdb界面,在中间会有一个“导入”按钮,你可以导入附件提供的rdb.sql文件,这样数据库和数据表就创建好了。

    然后我们在R里面测试mysql

    #任务1
    library(RMySQL)
    help(package="RMySQL") #查看RMySQL的说明文档,里面有RMySQL所有可用的方法  
    #创建数据库连接 ,localhost代表本机,dbname就是上面创建的rdb,用户名一般是root
    # password为空(如果你没设置的话一般都是这样的)
    con <- dbConnect(MySQL(),host="localhost",dbname="rdb",user="root",password="")
    dbSendQuery(con,'SET NAMES utf8')
    #获取连接信息,查看database下所有表
    #summary(con)  
    #dbGetInfo(con)  
    #dbListTables(con)  
    #dbRemoveTable(con,"test")
    
    #数据库连接删除函数,每个任务之前最好先清理所有的连接,调用此函数就可以
    killDbConnections <- function () {
      all_cons <- dbListConnections(MySQL())
      print(all_cons)
      for(con in all_cons)
        +  dbDisconnect(con)
      print(paste(length(all_cons), " connections killed."))
    }


    任务2.获得cell杂志2017年所有文章的id

    根据第一次的作业我们通过search接口获得了总数以及前20的id,那么我们可以循环将所有的id获取到,参考代码如下:

    library(httr)
    #上一次得到的总数
    totalNum=562
    pageSize=10 #每页数目,获取摘要的时候设置数目过大容易引起网络阻塞
    
    #获得总页数
    
    ...#隐去一行代码
    #上一行代码要求得到总页数totalPate=xxx
    
    currentPage=1 #当前页数
    term='(cell[TA]) AND 2017[DP]'
    
    usehistory='Y'#是否使用历史搜索
    querykey=''
    webenv=''
    
    postSearchUrl='https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esearch.fcgi'
    while(currentPage<=totalPage){
      retstart=(currentPage-1)*pageSize
      r <- POST(postSearchUrl, 
                body = list(
                  ...#隐去部分代码,根据第一次作业,你填入(可以不用理会userhistory,querykey,webenv)
                )
      )
      
      stop_for_status(r) #clear http status
      data=content(r, "parsed", "application/json")
      #data里面存储了所有数据
      esearchresult=data$esearchresult
      #$idlist=array $count=562,$retmax=20, $retstart=0,$querykey=1, $webenv=NCID_1_30290513_130.14.18.34_9001_1515165012_617859421_0MetA0_S_MegaStore_F_1
      
      querykey=esearchresult$querykey
      webenv=esearchresult$webenv
      
      #idlist为搜索结果中pmid的合集,下面的代码用于拼接出Rmysql需要的数据
      idlist =esearchresult$idlist
      
      
      ...#隐去部分代码
      
      
      #上述代码要求得到一个变量pmid=c(203343434,23402304,13221323)之类的向量,里面存储pubmedid
      
      
      #可以查看Rmysql帮助文档,需要构建一个frame
      article=data.frame('pmid'=pmid)
      #写入article数据表内,append=TRUE表示附加到表后面,否则每次都是覆盖
      
      ...#隐去一行代码
      
      #while循环后记得增加,否则就是死循环了
      
      ...#隐去一行代码
      
    }
    #close
    dbDisconnect(con)


    任务3:通过efetch接口获取title和abstract

    思路:从数据库rdb的article表里面每次获取10个pmid,然后发送到efecth接口(作业1里任务2)然后获得10篇文章的数据,循环将其更新到article表里面,并且将isdone设置为1

    #任务3
    #从mysql数据库里面循环取出id,每次取出10个,然后获取到title和abstract
    #为什么要用mysql数据库?
    #1. 本次作业数量比较少,用其他方法比如txt文本存储也是可以
    #2. mysql是当前最流行的数据库,学习mysql数据库的使用
    #3. 如果网络获取数量达百万级,一次执行不可能获得所有内容,可能多次中断执行,用mysql数据库方便纪录哪些已经被处理了
    library(RMySQL)
    library(xml2)
    library(httr)
    #清除所有mysql连接,否则会报错说超过16个连接
    killDbConnections()
    #创建数据库连接  
    con <- dbConnect(MySQL(),host="localhost",dbname="rdb",user="root",password="")
    dbSendQuery(con,'SET NAMES utf8')
    
    #isdone=0 表示查询article表里面还没有获取完的条目
    rs <- dbSendQuery(con, "SELECT * FROM article WHERE isdone=0")
    while (!dbHasCompleted(rs)) {
      chunk <- dbFetch(rs, 10)
      #mode(chunk)
      #print(chunk)
      #chunk[x,3] 第3列为获取到的pmid
      pmidStr=""
       
       ...#隐去部分代码,根据chunk里面的数据得到下面的pmid
       
      #pmid=",29195067,29195066,29195065,29195064,29153837,29153836,29153835,29153834,29153833,29153832"
      #去掉pmid第一个逗号
      ... #隐去一行代码
      
      
      #上面字符串就是我们post到pubmed上面的字符串,用于获取title和abstract
      
      #下面就是第一次作业里面获取title和abstract
      postFetchUrl='https://eutils.ncbi.nlm.nih.gov/entrez/eutils/efetch.fcgi'
      r2 <- POST(postFetchUrl, 
                 body = list(
                   db='pubmed',
                   id=pmidStr,
                   retmode='xml'
                 )
      )
      stop_for_status(r2) #clear http status
      data2=content(r2, "parsed", "application/xml")
      article=xml_children(data2)
      #xml_length(article)为里面文章的数量
      count=length(article)
      cnt=1
      while(cnt<=count){
        #下面的xml_text和xml_find_first均为XML2包里面的函数
        title=xml_text(xml_find_first(article[cnt],".//ArticleTitle")) #找到第一个ArticleTitle节点
        abstract=xml_text(xml_find_first(article[cnt],".//AbstractText"))
        pmid=xml_text(xml_find_first(article[cnt],".//PMID"))
        #接下来我们要更新数据库
        
        #1首先我们去掉title和abstract里面的单引号,单引号会导致mysql更新出现问题
        
        ... #隐去两行代码,用于得到新的title和abstract(没有单引号)
        
        #1构建mysql更新语句,R语言的字符串拼接不太好,不能使用"+",也不能使用点"."
        #设置isdone字段用于标记已经处理完的
        sql=paste("UPDATE article SET title='",title,"',abstract='",abstract,"',isdone=1"," where pmid='",pmid,"'",sep="")
        #2执行,需要新开通一个mysql连接
        con2 <- dbConnect(MySQL(),host="localhost",dbname="rdb",user="root",password="")
        dbSendQuery(con2,'SET NAMES utf8')
        dbSendQuery(con2,sql)
        #一定要执行下面的语句
        dbDisconnect(con2)
        cnt = cnt + 1
        #延迟1秒运行,pubmed接口说明如果1秒内并发超过3次将会被封禁IP
        Sys.sleep(1)
        #break 用于中断循环,调试程序的时候非常有用
      }
      #break 用于终端循环,调试的时候非常有用
    }


    最终得到的截图如下(用phpmyadmin查看的rdb数据库的article表)

    微信截图_20180124121515.png


    下一节我们学习进行分词处理

     
  • rdb.zip(大小:1.6 KB;下载:22)
  • 0条评论 227浏览 邀请回答
    沙发空缺中~

    小组告示

    科研狗 2012-2016 京ICP备16006621 科研好助手,专业的科研社交共享平台