搞科研的同学肯定离不开谷歌学术,谷歌学术搜索是文献搜索下载一大利器。之前实验室开发了一款学术应用,遗留了历史问题,就是没有解决文献搜索的功能,而这个任务最后落在我的身上。我采用的方案就是集成谷歌学术,但是国内的网络环境,你懂的,自然状态下根本就访问不了谷歌学术的,你得翻墙才能访问。你不能期望使用你开发的学术应用都能翻墙访问谷歌学术(虽然搞科研的人电脑翻墙软件肯定都准备好了!),所以呢我还要给谷歌学术搭建一个代理。不仅要集成谷歌学术一键搜索并下载,还要能导入和分享文献到自己开发的应用,获取文献的BIBTEX并导入到自己的学术应用中,就是要在代理中hack谷歌学术的原始响应,注入相关脚本。(关于BIBTEX可以去维基百科脑补一下。)
废话少说,放效果图过来先:

谷歌学术代理

谷歌学术代理默认采用的是node-http-proxy模块实现的,node-http-proxy的使用见博客用node-http-proxy搭建谷歌代理和node-http-proxy的Github地址。有人读到这已经急,Talk is cheap, Show me the code! 好好,博主这就废话少说,放码过来。新鲜热乎的代码如下:

/*** Created by Jaye on 15/7/11.*/
var config = require('./config');
var http = require('http');
var https = require('https');
var httpProxy = require('http-proxy');
var url = require('url');
var cookie = require('./cookie');
var util = require('util');
var modifyHtml = require('./modify_html');
var querystring = require('querystring');
var PROXY_PORT = config.proxyPort;var proxy, server;
var cookieArr = [];
var hl = 'zh-CN';
var injected = "";// 创建代理服务器
proxy = httpProxy.createProxy();//处理error
proxy.on('error', function (err,req,res) {res.writeHead(500, {'Content-Type': 'text/plain'});res.end('Something went wrong. And we are reporting a custom error message.' + err.message);
});server = http.createServer(function (req, res) {//载入需要注入的内容injected = fs.readFileSync('./inject.html', 'utf8');//解析语言,没有设置默认为zh-CN,重构时可以用url_auth来代替var query = querystring.parse(url.parse(req.url).query);if(query){hl = query.hl?query.hl:'zh-CN';}//todo:加入权限认证,调用url_auth中的urlAuth函数进行判断,如果auth为true放行,否则拦截 // var finalUrl = req.url,var finalUrl = 'https://scholar.google.com',finalAgent = null,parsedUrl = url.parse(finalUrl);if (parsedUrl.protocol === 'https:') {finalAgent = https.globalAgent;} else {finalAgent = http.globalAgent;}//proxy.web(req, res, {target: finalUrl,agent: finalAgent,headers: { host: parsedUrl.hostname,},prependPath:false,xfwd:true,hostRewrite:config.proxyHost+':'+config.proxyPort,//设置重定向地址,protocolRewrite: 'http'//设置重定向协议});
});proxy.on('proxyReq',function(proxyReq,req,res){//如果不去掉这个头字段,浏览器报330错误,无法解码if(proxyReq._headers){if(proxyReq._headers['accept-encoding']){proxyReq._headers['accept-encoding'] = '';}}});/*** [在响应返回到客户端时,重写html并注入js脚本]* @param  {[type]} proxyRes    [description]* @param  {[type]} request     [description]* @param  {[type]} response    [description]* @return {[type]}             [description]*/
proxy.on('proxyRes',function(proxyRes,request,response){if(proxyRes.headers && proxyRes.headers[ 'set-cookie' ]){cookieArr =  cookie.parseGoogleCookies(proxyRes.headers['set-cookie']); proxyRes.headers['set-cookie']=cookieArr;} //inject js,rewrite html bodyif( proxyRes.headers &&proxyRes.headers[ 'content-type' ] &&proxyRes.headers[ 'content-type' ].match( 'text/html' ) ) {var _end = response.end,chunks,_writeHead = response.writeHead,_write = response.write;response.writeHead = function(){if( proxyRes.headers && proxyRes.headers[ 'content-length' ] ){response.setHeader('content-length',parseInt( proxyRes.headers[ 'content-length' ], 10 ) + injected.length);}//不设置可能出现少量乱码response.setHeader( 'transfer-encoding', proxyRes.headers['transfer-encoding'] );// Disable cache for all http as wellresponse.setHeader( 'cache-control', 'no-cache' );_writeHead.apply( this, arguments );};response.write = function( data ) {if( chunks ) {chunks += data;} else {chunks = data;}};response.end = function() {if( chunks && chunks.toString ) {_end.apply( this, [ modifyHtml( chunks.toString(),hl , injected) ] );}else {_end.apply( this, arguments );}    };}
});console.log('listening on port ' + PROXY_PORT);
server.listen(PROXY_PORT);

代理的功能跟谷歌代理的动能类似,这里不再赘述。谷歌代理见博文用node-http-proxy搭建谷歌代理,下面我主要讲修改cookie来启用谷歌学术的设置功能,有设置功能的谷歌学术才够高大上!谷歌学术的设置是通过cookie来做的,需要完整的功能必须解决cookie的问题。我下面的例子是设置显示导入链接。谷歌学术的默认设置是隐藏导入链接的,需要到设置里勾选显示导入[BibTex、EndNote、RefMan、RefWorks]的链接,见下图:

  • 点击右上角我的著作引用情况右边的三角图标,选择设置
  • 然后选择显示导入BibTeX的链接
  • 点击保存后自动跳转到搜索结果,将会显示导入BibTeX(谷歌学术的原始显示)

    修改谷歌学术的cookie技术原理挺简单的,我们在proxyRes返回之前对set-cookie进行解析并修改相关字段即可,对应以上代码:
if(proxyRes.headers && proxyRes.headers[ 'set-cookie' ]){cookieArr =  cookie.parseGoogleCookies(proxyRes.headers['set-cookie']); proxyRes.headers['set-cookie']=cookieArr;}

我们再看看parseGoogleCookies函数做了什么事情,代码如下:


/*** 解析google scholar返回的cookie**/parseGoogleCookies: function (cookies) {// console.log(cookies);var cookieArr = [];if (cookies && cookies.length > 0) {for (var i = 0; i < cookies.length; i++) {var cookieItem = cookieUtil.parse(cookies[i]);if (cookieItem.domain) {//   delete cookieItem.domain;cookieItem.domain = proxyHost;}if (cookieItem.path) {cookieItem.path = '/';}var tempArr = [];for (var key in cookieItem) {if (key === 'expires' || key === 'path') {tempArr.push(key+'='+cookieItem[key]);} else {tempArr.push(key+'='+cookieItem[key]);}}cookieArr.push(tempArr.join('; '));};}return cookieArr;}

如果不够熟悉http cookie,请到谷歌先脑补一下相关的知识,这里推荐一篇博客全面解读HTTP Cookie。这里选取有助于理解上面程序的两点。谷歌cookie的用途:Cookie也被用来记忆用户自定义的一些功能。用户在设置自定义特征的时候,仅仅是保存在用户的浏览器中,在下一次访问的时候服务器会根据用户本地的cookie来表现用户的设置。例如google将搜索设置(使用语言、每页的条数,以及打开搜索结果的方式等等)保存在一个COOKIE里。cookie的Domain and Path
的作用:定义Cookie的生效作用域,只有当域名和路径同时满足的时候,浏览器才会将Cookie发送给Server。如果没有设置Domain和Path的话,他们会被默认为当前请求页面对应值。下面简单讲解一下cookie的http实现:

以访问http://blog.noobsky.com为例

  • Step1.客户端发起http请求到Server
GET / HTTP/1.1
Host: blog.noobsky.com
(这里是省去了User-Agent,Accept等字段)
  • Step2. 服务器返回http response,其中可以包含Cookie设置
HTTP/1.1 200 OK
Content-type: text/html
Set-Cookie: name1=value1
Set-Cookie: name2=value2; Expires=Wed, 06 Jun 2066 18:18:18 GMT
(content of page)
  • Step3. 后续访问blog.noobsky.com的相关页面
GET /archives HTTP/1.1
Host: blog.noobsky.com
Cookie: name1=value1; name2=value2
Accept: */*

第一次访问服务器的适合,服务器返回的头字段里通过set-cookie设置cookie,后面再次访问服务器时,客户端会自动的带上相关的cookie字段。这里需要注意的是要想客户端自动带上相关的cookie字段,cookie的domain和path字段必须要跟你访问的server服务。比如你在第一次访问blog.noobsky.com的时候通过技术手段把服务器response中的set-cookie中的domain域(默认值为blog.noobsky.com)修改为coolshell.cn的话,你下次再访问blog.noobsky.com的相关页面时,将不会带上相关的cookie,因为cookie的domain不匹配。同理通过访问代理然后代理访问scholar.google.com时,scholar.google.com服务器返回的response的set-cookie中的domain域的值是scholar.google.com,下次再访问代理时,因为domain域不匹配,将不会自动带上相关的cookie,所以我们在proxyRes返回给客户端之前,需要hack掉相关的cookie域,我们只需把cookie的domain域修改为proxyHost(代理主机),path域设置为'/'

if (cookieItem.domain) {cookieItem.domain = proxyHost;
}
if (cookieItem.path) {cookieItem.path = '/';
}

下次再访问代理主机时,因为domain域匹配,就会自动带上相关的cookie,谷歌学术就能实现记忆用户自定义的功能啦,你就可以随心所欲使用谷歌学术的设置功能!

除了能使用设置功能我们还需要把谷歌学术的默认显示导入BibTeX更改为导入我的网站,并修改默认的点击事件。默认的点击事件是跳转另一页面显示相应地BibTeX,我需要的点击事件是获取BibTeX数据,并推送给我的学术应用,cool!方法很简单:利用cheerio库修改response的html中导入BibTeX,然后注入相关的js脚本,js脚本修改默认点击事件!
* 通过重写response.end函数hack返回的html页面

response.end = function() {if( chunks && chunks.toString ) {_end.apply( this, [ modifyHtml( chunks.toString(),hl , injected) ] );}else {_end.apply( this, arguments );}    };
  • 修改html的函数如下:
function(str,lang,inject){$ = cheerio.load(str);var str = config.zhStr;if(lang.toLowerCase()=='en'){str = config.enStr;}//修改显示文本$(".gs_nta.gs_nph").each(function(i,elem){$(this).text(str);});str = $.html();// Add or script to the page,注入脚本if( str.indexOf( '</body>' ) > -1 ) {str = str.replace( '</body>', inject + '</body>' );} else if ( str.indexOf( '</html>' ) > -1 ){str = str.replace( '</html>', inject + '</html>' );} else {str = str + inject;}return str;
}
  • 注入的js脚本
<script type="text/javascript">$(document).ready(function () {$(".gs_nta.gs_nph").each(function () {$(this).bind("click", getData);});function getData() {var pdfUrl;if ($(this).parent().parent().prev(".gs_ggs.gs_fl")) {pdfUrl = $(this).parent().parent().prev(".gs_ggs.gs_fl").children("div.gs_md_wp.gs_ttss").children("a").attr("href");}var path = $(this).attr("href");$.ajax({type: "get",url: path,async: false,success: function (data) {alert("获取BibTex成功!" + data + "pdfUrl:" + pdfUrl);},error: function () {alert("获取BibTex失败!");}});return false;}});
</script>

这里需要注意的是,推送BibTeX到自己的学术应用中存在跨域问题,这里采用JSONP的方式。激动人心的时刻来了,我们来看一下最终的效果

  • hack原始html后的显示
  • 修改后的点击事件

    详细代码见Github上的google-scholar-proxy。

本文链接:http://blog.noobsky.com/2015/11/25/学术应用使用node-http-proxy集成谷歌学术/

–EOF–

学术应用使用node-http-proxy集成谷歌学术相关推荐

  1. 2020谷歌学术指标出炉,CVPR成AI学术会议总榜第一名

    机器之心报道 参与:泽南 在人工智能领域,计算机视觉顶会 CVPR 已成为谷歌学术总榜第一名. 近日,谷歌正式发布了 2020 年的学术指标(Scholar Metrics)榜单.在最新一期排名中,C ...

  2. endNote X9 导入英文文献(谷歌学术、web of science 等)

    文章目录 1 导入英文文献(谷歌学术.web of science 等) 2 EndNote X9 插入参考文献常见问题总结 3 EndNote X9 快速上手教程(毕业论文参考文献管理器) 1 导入 ...

  3. 人工智能的前沿信息获取之使用谷歌学术搜索

    谷歌学术是谷歌公司开发的一款专门针对学术搜索的在线搜索引擎[4],谷歌学术的网址为https://scholar.google.com,界面如图 6‑1所示.使用谷歌学术搜索可以检索会议或者期刊论文. ...

  4. python爬取谷歌学术参考文献的BibTex格式——基于selenium

    1.背景 进行Latex写作时,当引用文献,需要根据文章名,一个一个去谷歌学术搜索,找到BibTex,再复制进bib文件里,耗费大量时间和精力. 图1.传统方法引用参考文献 这样枯燥重复的工作完全可以 ...

  5. 2021谷歌学术指标出炉:CVPR总榜第4,仅次于Science,ECCV超过ICCV......

    点击上方"视学算法",选择加"星标"或"置顶" 重磅干货,第一时间送达 来源丨AI科技评论 编辑丨极市平台 导读 近日,谷歌学术更新了202 ...

  6. 2018谷歌学术指数发布——看看综合、生物、生信、微生物领域高引文章和杂志

    谷歌学术指数简介 2018年8月2号,谷歌发布了2018年度的学术指数(Google Scholar Metrics),用来评价各个领域杂志的影响力.该系统主要包括H指数(h-index或Hirsch ...

  7. 谷歌学术公布2021年最有影响力工作,CV顶会论文“夹缝求生”!凯明 YYDS!

    编译 | 陈彩娴 转自:AI科技评论 不久前,谷歌学术(Google Scholar)公布了2021年最有影响力的论文列表,结果在意料之中. 由于去年新冠疫情的全球性爆发,研究 COVID-19 的早 ...

  8. 2019谷歌学术指标出炉,影响因子何去何从?

    海归学者发起的公益学术平台 分享信息,整合资源 交流学术,偶尔风月 日前,谷歌学术发表了2018年最新的学术期刊和会议影响力排名.今年榜单上,Nature仍高居榜首,Science则位居第三.医学名刊 ...

  9. livechart 只显示 y 值_【科研工具51】谷歌,谷歌学术,Scihub有效网址检索软件——Y学术...

    软件介绍: Y学术是一款可以检索最新有效的谷歌镜像,谷歌学术镜像,Scihub有效网址的小软件,界面简洁,操作简单.此软件仅0.51 M,为绿色单文件免安装,适用于Windows操作系统.该软件可以手 ...

最新文章

  1. 【编程之美】2.12快速寻找满足条件的两个数
  2. sql server schema下拉不到存储过程_mysql数据库字符编码总结--数据存储编码
  3. 批处理bat命令--获取当前盘符和当前目录和上级目录
  4. 创建自定义Widgets小部件扩展
  5. C++ 类对象作为类成员
  6. 会话跟踪技术之Cookie
  7. Spark精华问答 | 怎么运行Spark?
  8. 大前端的自动化工厂(3)—— babel
  9. 体验Joomla2.5,从joomla1.5说起【转】
  10. BIEE回写(BIEE write back)
  11. 简易可行Live2D直播应用路线分享
  12. 爱心的数学函数方程_求心形函数表达式~~~
  13. VCRedist.exe静默安装方法(转)
  14. If today were the last day of my life
  15. 视频特征提取常用范式总结
  16. 智能卷发器的原理和功能
  17. NBUT1225 NEW RDSP MODE I(快速幂,规律)
  18. 干货来了,这些物联网基础知识你了解吗
  19. hive 正则表达式-regexp
  20. 一文搞懂什么是QPS PV 关于并发的面试

热门文章

  1. Excel2016 自动换行
  2. SATA系列专题之五:Link Power Management解析
  3. H5+CSS3实现官网首页--视频全屏背景
  4. 如何实现水平,垂直,水平垂直居中
  5. adobe flash player已过期
  6. 微信小程序-如何申请百度开放平台的密钥
  7. 渗透测试之Windows基础(新手必看)
  8. MVC4 AspNet MVC下的Ajax / 使用JQuery做相关的Ajax请求
  9. 一个积分不等式的再讨论
  10. Web 身份证读取,ActiveX 网页 二代身份证读取