标签:
目录
下面继续实战,写一个模拟登陆获取汽车之家,用户信息的程序。如果大家对模拟登陆获取数据不太了解,建议看完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,包含要获取的用户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(" ").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<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
标签:
原文地址:http://blog.csdn.net/qy20115549/article/details/52250022