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

3,203 阅读

原文地址:http://blog.csdn.net/qy20115549/article/details/52250022

目录

#分析要获取的数据

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

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

这里写图片描述
这里写图片描述

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

这里写图片描述
这里写图片描述

程序的结构

这里写图片描述
这里写图片描述

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

#构建封装数据的model

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

package renren.renren;
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 1563178220@qq.com
 */
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 = "十七岁的雨季1";
		String password = new MD5().GetMD5Code("a888888");  
		HttpPost httpost = new HttpPost(AutohomeRenLoginURL);  
		/*
		 * 建立一个NameValuePair数组,用于存储欲传送的参数
		 * 不明白这里参数的,请看我前面写的一篇关于模拟登陆网络抓包的的博客
		 */
		List<NameValuePair> nvps = new ArrayList<NameValuePair>();  
		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<String> 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<UserInfo> parser(String CrawlerUrl) { 
		List<UserInfo> UserInfomation = new ArrayList<UserInfo>();
		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("&nbsp;").text(), " ").split(":")[1];
				//System.out.println("area:"+area);
			}
			if (ele.text().contains("性别")) {
				gender=ele.text().replaceAll(Jsoup.parse("&nbsp;").text(), "").split(":")[1];
				//System.out.println("gender:"+gender);
			}
			if (ele.text().contains("生日")) {
				birthday=ele.text().replaceAll(Jsoup.parse("&nbsp;").text(), "").split(":")[1];
				//System.out.println("birthday:"+birthday);
			}
			if (ele.text().contains("用户名")) {
				username=ele.text().replaceAll(Jsoup.parse("&nbsp;").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<UserInfo> 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;

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;
    }
}

#结果展示

这里写图片描述
这里写图片描述

本文作者:合肥工业大学 管理学院 钱洋 有不明白,请发邮件1563178220@qq.com

DataLearner 官方微信

欢迎关注 DataLearner 官方微信,获得最新 AI 技术推送

DataLearner 官方微信二维码