网络爬虫模拟登陆获取数据并解析实战(二)

本文为原创博客,仅供学习使用。未经本人允许禁止复制下来,上传到百度文库等平台。

目录

  • 分析要获取的数据
  • 程序的结构
  • 构建封装数据的model
  • 模拟登陆程序并解析数据
  • 结果展示

分析要获取的数据

下面继续实战,写一个模拟登陆获取汽车之家,用户信息的程序。如果大家对模拟登陆获取数据不太了解,建议看完http://blog.csdn.net/qy20115549/article/details/52249232,我写的这篇含有抓包获取人人网数据的案例程序,研究透之后,再来看这个要轻松很多。

首先,大家打开汽车之家这个网站(http://i.autohome.com.cn/7741675/info)看看,能否直接观测到返回的用户信息数据。如下图所示,你会发现,他直接跳转到了登陆界面,并没有返回我们想看到的用户信息数据。

网络爬虫模拟登陆获取数据并解析实战(二)_第1张图片

为更好的讲解,我注册了一个用户,你会在我的程序中,看到用户名及密码。以下是我们要获取的用户信息。即用户的id,用户名。用户出生日期、用户所在地。为此,我们需要建立封装数据对象的Model。有不明白为什么要建Model的,请看我的这篇博客http://blog.csdn.net/qy20115549/article/details/52203722【基于Java的网络爬虫框架

网络爬虫模拟登陆获取数据并解析实战(二)_第2张图片

程序的结构

网络爬虫模拟登陆获取数据并解析实战(二)_第3张图片

为了简单,本文就没有建框架。程序的目录结果,如上图所示。

构建封装数据的model

以下是我要建的封装数据对象的model,包含要获取的用户ID,用户名,年龄,性别,地域,网站来源,爬该数据的时间点

package renren.renren;
/*   
 *  合肥工业大学 管理学院 qianyang [email protected]
 */
public class UserInfo {
    private String authorId;
    private String authorname;
    private String age;
    private String gender;
    private String area;
    private String source;
    private String craw_time;
    public String getAuthorId() {
        return authorId;
    }
    public void setAuthorId(String authorId) {
        this.authorId = authorId;
    }
    public String getAuthorname() {
        return authorname;
    }
    public void setAuthorname(String authorname) {
        this.authorname = authorname;
    }
    public String getAge() {
        return age;
    }
    public void setAge(String age) {
        this.age = age;
    }
    public String getGender() {
        return gender;
    }
    public void setGender(String gender) {
        this.gender = gender;
    }
    public String getArea() {
        return area;
    }
    public void setArea(String area) {
        this.area = area;
    }
    public String getSource() {
        return source;
    }
    public void setSource(String source) {
        this.source = source;
    }
    public String getCraw_time() {
        return craw_time;
    }
    public void setCraw_time(String craw_time) {
        this.craw_time = craw_time;
    }
}

模拟登陆程序,并解析数据

为了简单起见,下面,我把模拟登陆获取html文件,解析html文件以及main方法,都放到了一个程序中去了。建议大家还是按照我之前写博客中的框架来写,逻辑比较清晰。下面是我的程序:

package renren.renren;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
/*   
 *  合肥工业大学 管理学院 qianyang [email protected]
 */
public class Autohome1 {

    private static String AutohomeRenLoginURL = "http://account.autohome.com.cn/Login/ValidIndex";  
    HttpResponse response;  
    private DefaultHttpClient httpclient = new DefaultHttpClient();  
    /*   
     *  这里是模拟登陆的过程
     */
    private boolean login() { 
        /*
         * 用户名及密码
         * 在我们抓包的过程中,我们发现我们的密码,被MD5加密了,所以这里有一个将密码,转换成MD5的形式
         */
        String userName = "";
        String password = new MD5().GetMD5Code("");  
        HttpPost httpost = new HttpPost(AutohomeRenLoginURL);  
        /*
         * 建立一个NameValuePair数组,用于存储欲传送的参数
         * 不明白这里参数的,请看我前面写的一篇关于模拟登陆网络抓包的的博客
         */
        List nvps = new ArrayList();  
        nvps.add(new BasicNameValuePair("domain", "autohome.com.cn"));  
        nvps.add(new BasicNameValuePair("isauto", "true"));  
        nvps.add(new BasicNameValuePair("method", "post"));  
        nvps.add(new BasicNameValuePair("name", userName));  
        nvps.add(new BasicNameValuePair("pwd", password));  
        try {  
            httpost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8));  
            response = httpclient.execute(httpost);  
        } catch (Exception e) {  
            e.printStackTrace();  
            return false;  
        } finally {  
            httpost.abort();  
        }  
        return true;  
    }  
    private String getText(String redirectLocation) {  
        HttpPost httpget = new HttpPost(redirectLocation);  
        ResponseHandler responseHandler = new BasicResponseHandler();  
        String responseBody = "";  
        try {  
            //获取html文件
            responseBody = httpclient.execute(httpget, responseHandler);
        } catch (Exception e) {  
            e.printStackTrace();  
            responseBody = null;  
        } finally {  
            httpget.abort();  
        }  
        return responseBody;  
    }  
    public String printText(String redirectLocation) {
        String htmlText=null;
        if (login()) {  
            if (redirectLocation != null) {
                htmlText=getText(redirectLocation);
            }  
        } 
        return htmlText;
    }  
    /*   
     *  以下是jsoup解析的过程,有不明白Jsoup的上网搜索其API
     *  
     */
    public List parser(String CrawlerUrl) { 
        List UserInfomation = new ArrayList();
        Autohome1 autohome = new Autohome1();  
        String htmltext=autohome.printText(CrawlerUrl);
        Document doc = Jsoup.parse(htmltext);
        String authorId="autohome"+doc.select("li[class=current]").select("a").attr("href").replaceAll("\\D","");
        Elements dataElements=doc.select("div[class=uData]").select("p");
        String source="autohome";
        Date date=new Date();
        DateFormat format=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String craw_time=format.format(date);
        String area="";
        String username="";
        String gender="";
        String birthday="";
        for (Element ele:dataElements) {
            if (ele.text().contains("所在地")) {
                area=ele.text().replaceAll(Jsoup.parse(" ").text(), " ").split(":")[1];
                //System.out.println("area:"+area);
            }
            if (ele.text().contains("性别")) {
                gender=ele.text().replaceAll(Jsoup.parse(" ").text(), "").split(":")[1];
                //System.out.println("gender:"+gender);
            }
            if (ele.text().contains("生日")) {
                birthday=ele.text().replaceAll(Jsoup.parse(" ").text(), "").split(":")[1];
                //System.out.println("birthday:"+birthday);
            }
            if (ele.text().contains("用户名")) {
                username=ele.text().replaceAll(Jsoup.parse(" ").text(), "").split(":")[1];
                //System.out.println("birthday:"+username);
            }

        }
        /*   
         *  将数据封装在集合中,返回
         */
        UserInfo Info = new UserInfo();
        Info.setAuthorId(authorId);
        Info.setAuthorname(username);
        Info.setAge(birthday);
        Info.setGender(gender);
        Info.setArea(area);
        Info.setSource(source);
        Info.setCraw_time(craw_time);
        UserInfomation.add(Info);
        return UserInfomation;
    }  
    public static void main(String[] args){
        Autohome1 AutoHome = new Autohome1(); 
        /*需要获取网页的地址*/
        String url="http://i.autohome.com.cn/7741675/info";
        /*获取数据,解析数据,返回解析之后的数据*/
        List authorInfo=AutoHome.parser(url);
        /*打印数据在控制台,这里可以按照前面博客的方法,写入数据库*/
        for (UserInfo userinfo:authorInfo) {
            System.out.println("ID: "+userinfo.getAuthorId()+" Age: "+userinfo.getAge()+" +Area: "+userinfo.getArea());
        }
    }
}

上述程序调用了一个MD5加密的程序,下面是MD5的程序。

package renren.renren;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
/*   
 *  合肥工业大学 管理学院 qianyang [email protected]
 */
public class MD5 {
     // 全局数组
    private final static String[] strDigits = { "0", "1", "2", "3", "4", "5",
            "6", "7", "8", "9", "a", "b", "c", "d", "e", "f" };
    public MD5() {
    }
    // 返回形式为数字跟字符串
    private static String byteToArrayString(byte bByte) {
        int iRet = bByte;
        // System.out.println("iRet="+iRet);
        if (iRet < 0) {
            iRet += 256;
        }
        int iD1 = iRet / 16;
        int iD2 = iRet % 16;
        return strDigits[iD1] + strDigits[iD2];
    }

    // 返回形式只为数字
    private static String byteToNum(byte bByte) {
        int iRet = bByte;
        System.out.println("iRet1=" + iRet);
        if (iRet < 0) {
            iRet += 256;
        }
        return String.valueOf(iRet);
    }

    // 转换字节数组为16进制字串
    private static String byteToString(byte[] bByte) {
        StringBuffer sBuffer = new StringBuffer();
        for (int i = 0; i < bByte.length; i++) {
            sBuffer.append(byteToArrayString(bByte[i]));
        }
        return sBuffer.toString();
    }

    public static String GetMD5Code(String strObj) {
        String resultString = null;
        try {
            resultString = new String(strObj);
            MessageDigest md = MessageDigest.getInstance("MD5");
            // md.digest() 该函数返回值为存放哈希值结果的byte数组
            resultString = byteToString(md.digest(strObj.getBytes()));
        } catch (NoSuchAlgorithmException ex) {
            ex.printStackTrace();
        }
        return resultString;
    }
}

结果展示

这里写图片描述

本文作者:合肥工业大学 管理学院 钱洋
有不明白,请发邮件[email protected]

你可能感兴趣的:(java)