浅谈数据抓取的几种方法

在下抓数据也小有研究,现分享几个本身研究出来的抓数据的技术,可能会有不少不足的地方,欢迎你们指正补充哈哈!


方法一:直接抓取网页源码
优势:速度快。
缺点:1,正因为速度快,易被服务器端检测,可能会限制当前ip的抓取。对于这点,能够尝试使用ip代码解决。
   2,若是你要抓取的数据,是在网页加载完后,js修改了网页元素,没法抓取。
   3,遇到抓取一些大型网站,若是须要抓取如登陆后的页面,可能须要破解服务器端账号加密算法以及各类加密算法,及其考验技术性。
适用场景:网页彻底静态化,而且你要抓取的数据在网页首次加载完成就加载出来了。涉及登陆或者权限操做的相似页面未作任何账号加密或只作简单加密的。
固然,若是该网页你抓取的数据,是经过接口得到的json,那么,你就更幸福的,直接抓取json页面便可。
对于有登陆的页面,咱们如何拿到他的登陆页以后的源码呢?
首先我要介绍一下,对于session保存账号信息的状况下,服务器是如何肯定该用户身份的。
首先,用户登陆成功后,服务器端会将用户的当前会话信息保存到session中,每个session有一个惟一标志sessionId。则用户访问这个页面,session被建立后,就会接收到服务器端传回的sessionId,并将其保存到cookie中,所以,咱们能够用chrome浏览器打开检查项,查看当前页面的jsessionId。下次用户访问须要登陆的页面时,用户发送的请求头会附上这个sessionId,服务器端经过这个sessionId就能够肯定用户的身份。
这里,我搭建了一个简单的jsp登陆页面,登陆后的账号信息保存在服务器端session中。
思路:1,登陆。2,登陆成功后得到cookie。3,将cookie放到请求头中,向登陆页发送请求。
附上java版本的代码及python
java版:html

package craw;  
   
import java.io.BufferedReader;  
import java.io.IOException;  
import java.io.InputStreamReader;  
import java.io.PrintStream;  
import java.io.PrintWriter;  
import java.net.HttpURLConnection;  
import java.net.MalformedURLException;  
import java.net.URL;  
import java.net.URLConnection;  
import java.util.List;  
import java.util.Map;  
   
public class CrawTest {  
    //得到网页源代码  
    private static String getHtml(String urlString,String charset,String cookie){  
        StringBuffer html = new StringBuffer();  
        try {  
            URL url = new URL(urlString);  
            HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();  
            urlConn.setRequestProperty("Cookie", cookie);  
            BufferedReader br = new BufferedReader(new InputStreamReader(urlConn.getInputStream(),charset));  
               
            String str;  
            while((str=br.readLine())!=null){  
                html.append(str);  
            }  
        } catch (MalformedURLException e) {  
            // TODO Auto-generated catch block  
            e.printStackTrace();  
        } catch (IOException e) {  
            // TODO Auto-generated catch block  
            e.printStackTrace();  
        }  
           
        return html.toString();  
    }  
       
       
    //发送post请求,并返回请求后的cookie  
    private static String postGetCookie(String urlString,String params,String charset){  
        String cookies=null;  
        try {  
            URL url = new URL(urlString);  
            URLConnection urlConn = url.openConnection();  
            urlConn.setDoInput(true);  
            urlConn.setDoOutput(true);  
            PrintWriter out = new PrintWriter(urlConn.getOutputStream());  
            out.print(params);  
            out.flush();  
            cookies = urlConn.getHeaderFields().get("Set-Cookie").get(0);  
        } catch (MalformedURLException e) {  
            // TODO Auto-generated catch block  
            e.printStackTrace();  
        } catch (IOException e) {  
            // TODO Auto-generated catch block  
            e.printStackTrace();  
        }  
        return cookies;  
    }  
       
    public static void main(String[] args) {  
        String cookie = postGetCookie("http://localhost:8080/loginDemo/login",  
                "username=admin&password=123456","utf-8");  
        String html = getHtml("http://localhost:8080/loginDemo/index.jsp", "utf-8", cookie);  
        System.out.println(html);//这里咱们就可能输出登陆后的网页源代码了  
    }  
}  

  python版:java

#encoding:utf-8  
import urllib  
import urllib2  
   
data={'username':'admin','password':'123456'}  
data=urllib.urlencode(data)  
response = urllib2.urlopen('http://localhost:8080/loginDemo/login',data=data)//登陆  
cookie = response.info()['set-cookie']//得到登陆后的cookie  
jsessionId = cookie.split(';')[0].split('=')[-1]//从cookie得到sessionId  
html = response.read()  
if html=='error':  
    print('用户名密码错误!')  
elif html=='success':  
    headers = {'Cookie':'JSESSIONID='+jsessionId}//请求头  
    request =urllib2.Request('http://localhost:8080/loginDemo/index.jsp',headers=headers)  
    html = urllib2.urlopen(request).read()  
    print(html)//输出登陆后的页面源码  

咱们能够很明显看出python的优点,会比java少写至少一半的代码量,固然这便是java的优势,也是java的缺点,优势就是更加灵活,程序员能够更好的控制底层代码的实现,缺点就是不易上手,对技术要求太高,所以,若是你是一名数据抓取新人,我的极力推荐你学习python。


方法二:模拟浏览器操做
优势:1,和用户操做相相似,不易被服务器端检测。
    2,对于登陆的网站,即便是通过了N层加密的,无需考虑其加密算法。
    3,可随时得到当前页面各元素最新状态。
缺点:1,速度稍慢。
   
这里介绍几个不错的模拟浏览器操做的类库:
C# webbrower控件:
若是你研究过c# winform,相信你绝对不会对webbrower这个控件陌生,他就是一个浏览器,内部驱动其实也是ie的驱动。
他能够以dom方式随时解析当前的document(网页文档对象),不只能够拿到相关Element对象,还能够对element对象进行修改,乃至调用方法,如onclick方法,onsubmit等等,也能够直接调用页面js方法。

C#对webbrower操做代码:python

webBrowser1.Navigate("https://localhost//index.html");//加载一个页面  
 
须要注意的是:不要直接执行如下代码,由于网页加载须要时间,建议如下代码写到webBrowser1_DocumentCompleted(加载完成)事件中:  
webBrowser1.Document.GetElementById("username").InnerText="admin";//在网页中找到id为username的元素,设置其文本为admin  
 webBrowser1.Document.GetElementById("password").InnerText = "123456";//在网页中找到id为password的元素,设置其文本为123456  
   
  webBrowser1.Document.InvokeScript("loginEncrypt");//调用网页js函数:loginEncrypt.

因为有些页面ie可能不够友好,或者若是ie版本太低,甚至是安全证书等问题,那么这个方案可能就pass掉了。
咱们能够直接使用selenium库来操做系统中真实浏览器,如chrome浏览器,selenuim支持多语言开发,以python调用selenium为例,selenium就是直接操做咱们系统中的浏览器,但须要确保浏览器安装对应的驱动。
然而,真正开发中,有时咱们可能不但愿看到这个浏览器界面,这里,我能够推荐你们一个后台浏览器,他直接在cmd中进行操做,没有界面,那就是phantomjs。
这样,咱们使用python+selenium+phantomjs就能够模拟浏览器的操做,而且看不到界面,因为phantomjs没有界面,因此他会比通常的浏览器要快不少。
这里网上有大量的资料,一时半会也讲不请,这里就不作过多讲解,你们能够看看:http://www.cnblogs.com/luxiaojun/p/6144748.html

三,Fidder script:
fidder是一款很是强大的数据抓取工具,他不只能够抓取到当前系统中的http请求,他还能够提供安全证书,所以有时候,咱们抓取过程当中,若是遇到安全证书错误,咱们不妨把fidder打开,让他提供你一个证书,或许你就近成功近在咫尺。
使人更增强大的是fidder script,他能够在对抓取到了请求后,进行一系统操做,如将请求到的数据保存到硬盘中。或者在请求前,修改请求头,可谓是抓取一利器,这样,咱们使用fidder配合上以前的各种方法,相信能够解决大多难题。而且他的语法和C like系列语法类似,类库和c#大多相同,相信对C#熟悉的同窗,上手fiddler script会很快。
fidder script:http://blog.csdn.net/crisschan/article/details/45602745程序员

相关文章
相关标签/搜索