突破限制爬取网页数据 googlesholar为例【转】

转载 2016年05月31日 19:48:54

突破限制爬取网页数据 googlesholar为例【转】


1、为什么要爬取google scholar数据
     Google Scholar上论文信息较为丰富,可以对应中英文搜索,结果较为完备,通过高级查找能够找到精确的
结果。等等

2、爬取网页的一般设置
    我们有时候会发现,用浏览器可以查看某个网站的网页,但是当我们用程序去爬取网页时,却得不到结果,
或者说返回错误(如果你没遇到过,那看来你一般爬取的是比较简单的网站的网页)。这是什么原因呢?一
般的http请求,浏览器在执行的时候,并不是像我们看到的那样简单,只是向服务器发送请求某个网页的命
令。在这个过程中,浏览器还会发送一些附加的信息,如“Accept”接收文件爱你的类型,”Accept-
Language”接受语言,”Accept-Charset”接受的编码等。
    在这其中,对于一般爬取网页比较重要的就是“User-Agent”,它代表发出该http请求的客户端,一般包括浏
览器和操作系统的信息。如“User-Agent Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.2) Gecko/20100115
Firefox/3.6”。一般网站为了封堵程序爬取其信息,或是避免影响正常用户的访问,都会检查该项设置。那
我们在程序中对该项进行设置,就可以正常的访问爬取网页了。
    可能有些网页,不仅检查该项,还会同时检查“referer”项信息。Referer记录的是你从那个网页上的链接点
击现在正在查看的网页的。这是因为有时候,网站的某个网页只要求是在其网站内部访问时点击进来的才可
以访问,举个比较常见的例子,有时候你在浏览网页的时候会发现网页上的图片显示错误,“你看的图片来
自…”,”…仅限于站内交流”,俗称“图片盗链”,这就是网站通过查看“referer”信息实现的。
通过设置这两项内容,基本就可以下载一般网站的网页了。

3、Google scholar的特殊之处及应对措施
     如果只是爬取Google Scholar的搜索结果,并没有什么特殊的地方,直接爬取就行了。但是,因为我需要每
个论文的参考信息(在高级设置里有),即将论文导出成Endnote信息。该选项默认是不显示的,那要进行
怎样的设置才能找到该信息呢?
     要对这个问题进行说明,首先要介绍下网络服务模型的一些东西。首先,分服务器端和客户端,服务器端一
般就是我们所说的网站了,那么你在浏览其网站时,就是一个客户端,更直接点说就是浏览器。当我们做出
一些选择时,怎么让服务器知道呢,怎么把参数传给服务器,一般有post和get两种方式。Get方式是直接
在链接的后面跟上一些参数,post方式则是在http的请求中,位于请求头内部的。在Google搜索中,我们可以设置一页显示100条结果记录,可以设置中英文搜索,可以设置从第几条结果返回,等等。这些参数都是通过get方式设定的。但是要让scholar的结果显示“导出Endnote”的链接,需要事先到一个页面上进行设置,向服务器提交设置。在提交这些设置的过程中,很容易发现它是通过form-get方式传递参数的。但是设定完之后,再次进行搜索时,并没有在搜索页面的后面增加一个参数,而仍是和原来一样的url。页面中也没有其他的隐藏的post参数。那为什么现在就能显示出来“导出Endnote”的链接呢?
     Cookie?没错,GoogleScholar使用了Cookie来保存你的搜索偏好设置。Cookie是为了维护你在浏览网页时的一些信息设置的,比如在不同的页面间维持登录消息。查知,分两种session cookie和persistencecookie,一种存在你的硬盘上,一种则是随着窗口的关闭而消失。不管怎样,GoogleScholar是把我们搜索的高级选择存到了cookie中,那接下来就是要在你的程序中进行相应的设置。
不同的浏览器是不共享cookie的,网上查询知,在java中可以通过一定的步骤来获取某次http请求的cookie信息(cookie信息是从服务器发送到客户端进行存储的),那我得到cookie信息后,就可以模仿人为访问来爬取页面了。
     不过值得说明的是,在我爬取的过程中,发现设置完cookie后并没有显示想要的链接内容,通过对比浏览器的cookie和我仿造的cookie,发现需要在得到cookie的基础上进行改进,可是通过多次测试,也没整明白这个额外的信息是从什么时候给添加到浏览器客户端上的。
    比如我模拟opera浏览器的user-agent(在opera浏览器的地址栏中输入“javascript:alert(navigator.userAgent)”可得),向googlescholar的搜索爱好设置项页面发送请求,得到的cookie信息为“PREF=ID=7d7f54d6ace3ddee:LD=en:NR=100:NW=1:TM=1269084787:LM=1269084787:S=9SzH07PRA1xd7rwh;GSP=ID=7d7f54d6ace3ddee”。简单说明下,分号前面的据我推测应该是搜索偏好的搜索设置信息,后面的就是你的cookieid信息了。利用这个cookie进行请求时,并没能如我所愿的看到“导出为Endnote”的链接,这是为什么呢?现在拿这个cookie对比浏览器中进行过相应设置的cookie,如PREF=ID=3091859a4fd2f136:U=4927399a4c6ef959:LD=en:NR=100:NW=1:CR=2:TM=1268316933:LM=1268987338:GM=1:S=gxL2FV6kIdXGARMD;NID=32=GYLdF8rZWqUo82gx_Pop-eaiDGHpDa7-d6g3n-d66c1UVWNEFiD99ERd9T-0izVjmI4-u5SzsU2bIFjbCjGTV7poV22bpNWbKIOHYsIv4pDnHO2BbsFKRmg7DvIJPmCE;
GSP=ID=3091859a4fd2f136:IN=8b9a455bd1c58d67:CF=3;S=sorry=ZKTU9UFyzml7PNQcOySXww;GDSESS=ID=3091859a4fd2f136:EX=1269100800:S=9vcgIt1YDAWR9C_P;SID=DQAAAIkAAACaSIE2V1fT5KDklGwKUutN-3eiGuOTGfQFGxtm_pWhRDUmx-hG6FOhht4eVM5MHbiyZpyB_h3UwONT8SZrw08fqu_36vfh9kTUvCR1g4UU3aGWx9k1lQTDvQEgbhIOIJ3QFfxdVACSEI22Oz-3tVydfrqDOjK-PUuuzPwNRMkMHlCgGI7nKInKjHrIIO0VuI;HSID=Akp34ZX0kDvONGUMm
   刚刚得到的cookie,信息比较多,可能是保存了我进行过过多请求的原因。不过无所谓,注意红色部分,多了一个CF=3,在我仿的cookie上加该信息即可得到想要的内容了。

4、 针对高技术网站反爬的对策
    你能想的到的,那帮天才们当让也会想的到。即使模仿了cookie,也是有办法阻止你的爬取的。其实我现在
也不知道需不需要费心的去模拟浏览器得到一个新的cookie,因为我们已经能够通过工具看到浏览器在进行请求时的cookie了,直接用它不就完了吗?之所以这样做,一部分原因是怕google会进行用户行为的记录,而如果它把我的账户与当前cookie关联起来,以后如果遇到一些问题岂不麻烦。也许杞人忧天了。开始爬取时,我用的就是浏览器里看到的cookie信息,结果进行一次搜索后,就被google发现而禁止了,就是弹出“sorry。。。。”然后好一点给你个机会让你输下数字等,证明你是human,不好的话就是你只能等待一段时间再进行搜索了。当然,这样不行啊。短时间进行大量访问请求,很容易被网站发现封掉。那我们可以一次请求后等待一段时间。有些网站会观察你一段时间的请求,看你是不是在十分精确地间隔一段时间发一次请求。因为人是不会这样的,你查看一个链接的间隔是很不规则的。既然有人提出了,不管google有没有做,那我就按照通常的做法,进行一次请求,随机的等待一段时间,更human些。为了避免被封掉,我把等待间隔设置的很长。每几十秒进行一次请求,因为相信只要有愚公移山的精神,总能够完成页面的爬取,何况程序整天工作也不会觉得累。
      还是怕会被封掉,因为是在实验室进行的,如果我的被封掉,那整个实验室都不能再进行访问了,后果有点严重。能不能避免呢?代理。通过中间代理进行访问,那即使封也不会封到实验室的ip了。而且,你还可以通过多个代理同时进行访问,加快速度。

5、用到的工具说明
    请求网页和设置cookie等,都是通过java urlconnection完成的
    搜索得到的结果,在提取所用信息时,通过html parser来做
    如何查看浏览器的发送请求和响应信息呢,十分推荐firebug,是firefox浏览器的一个插件,如果你经常和网页打交道,它是很有用的。用它,就可以看到浏览器中的cookie信息。

6、程序
代理设置例:
            System.getProperties().put("proxySet", "true");
            System.getProperties().put("proxyHost", host);
            System.getProperties().put("proxyPort", port);
请求信息设置例:
            URL url = new URL(pageURL);
            HttpURLConnection con = (HttpURLConnection)url.openConnection();
            con.setConnectTimeout(500000);
            con.setReadTimeout(1000000);
            con.setRequestProperty("User-Agent", "Opera/9.27 (Windows NT 5.2; U; zh-cn)");
               con.setRequestProperty("Cookie","PREF=ID=7d7f54d6ace3ddee:LD=en:NR=100:NW=1:TM=1269084787:LM=1269084787:S=9SzH07P
RA1xd7rwh;GSP=ID=7d7f54d6ace3ddee:CF=3");
            con.connect();
得到cookie:
        public void getCookies(URLConnection con){
        Map<String,String> cookie = new HashMap<String,String>();
        String headerName = null;
        for(int i=1;(headerName = con.getHeaderFieldKey(i))!=null;i++){
            System.out.println(headerName+":"+con.getHeaderField(i));
            if(headerName.equalsIgnoreCase("Set-Cookie")){
                StringTokenizer st = new StringTokenizer(con.getHeaderField(i),";");              
                if(st.hasMoreElements()){
                    //System.out.println("here");
                    String token = st.nextToken();
                    String name = token.substring(0,token.indexOf('='));
                    String value = token.substring(token.indexOf('=')+1);
                    cookie.put(name, value);
                }
            }
        }
        System.out.println(cookie.toString());
    }
7、    慎重爬取网站数据
////////////////////////////////////////////////////////////////
author:wendell
mail:wcw19861217@163.com
If you have any question, please send email to me!

如何抓取google的搜索结果?

昨天周末快下班的时候,看到QQ群一朋友在在问"如何抓取google的搜索结果?",平时这群高手也众多,都很活跃,今天突然没动静了(估计周末忙),我就去看了下google 的搜索结果页面的源码。源码中没...

chrome启动参数

chrome启动参数 转载▼ http://src.chromium.org/svn/trunk/src/chrome/common/chrome_switches.cc 参数:--user-da...

给定A, B两个整数,不使用除法和取模运算,求A/B的商和余数

给定A, B两个整数,不使用除法和取模运算,求A/B的商和余数。 1.   最基本的算法是,从小到大遍历: for (i = 2 to A -1)          if (i * B > A)...

利用K-means聚类算法根据经纬度坐标对中国省市进行聚类

K-means聚类算法是一种非层次聚类算法,在最小误差的基础上将数据划分了特定的类,类间利用距离作为相似度指标,两个向量之间的距离越小,其相似度就越高。程序读取全国省市经纬度坐标,然后根据经纬度坐标进...

android.hardware.camera2使用指南

API 21中将原来的camera API弃用转而推荐使用新增的camera2 API,这是一个大的动作,因为新API换了架构,让开发者用起来更难了。 先来看看camera2包架构示意图: 这...

source insight的查找功能

source insight是一款很好的c语言的程序编辑器,方便对project管理,方便程序的阅读和编辑。查找功能使用十分频繁,选项较多,与其它软件的查找功能也类似,下面对英文版的查找功能,做简单说...
  • kobesdu
  • kobesdu
  • 2014年07月24日 14:53
  • 35816

第十一章全部上机代码

上机练习1 --查询每个年级的总学时数,并按照升序排列。 SELECT SUM(ClassHour) AS 总学时,GradeId AS 年级 FROM Subject GROUP BY Grade...

python调用java编写的Webservice

首先我使用的是java自带的对webservice的支持包来编写的服务端和发布程序,代码如下。 webservice的接口代码: package com.xxx.test.ws; import ja...
  • dmcpxy
  • dmcpxy
  • 2014年03月10日 16:06
  • 4687

linux/ubuntu 端口开放

在ubuntu下面开放端口好像主要有两种方法,一种是ubuntu自带的防火墙,一种是iptables,这里我们主要使用iptables。本文的系统版本为ubuntu14.04和ubuntu16.04 ...

java 判断对象是否是某个类的类型两种方法

一、 instanceof 运算符是用来在运行时指出对象是否是特定类的一个实例。instanceof通过返回一个布尔值来指出,这个对象是否是这个特定类或者是它的子类的一个实例。  用法: ...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:突破限制爬取网页数据 googlesholar为例【转】
举报原因:
原因补充:

(最多只允许输入30个字)