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

淡淡的烟草味﹌ 2022-09-25 10:19 290阅读 0赞

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

目录

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

分析要获取的数据

下面继续实战,写一个模拟登陆获取汽车之家,用户信息的程序。如果大家对模拟登陆获取数据不太了解,建议看完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,用户名,年龄,性别,地域,网站来源,爬该数据的时间点

  1. package renren.renren;
  2. /* * 合肥工业大学 管理学院 qianyang 1563178220@qq.com */
  3. public class UserInfo {
  4. private String authorId;
  5. private String authorname;
  6. private String age;
  7. private String gender;
  8. private String area;
  9. private String source;
  10. private String craw_time;
  11. public String getAuthorId() {
  12. return authorId;
  13. }
  14. public void setAuthorId(String authorId) {
  15. this.authorId = authorId;
  16. }
  17. public String getAuthorname() {
  18. return authorname;
  19. }
  20. public void setAuthorname(String authorname) {
  21. this.authorname = authorname;
  22. }
  23. public String getAge() {
  24. return age;
  25. }
  26. public void setAge(String age) {
  27. this.age = age;
  28. }
  29. public String getGender() {
  30. return gender;
  31. }
  32. public void setGender(String gender) {
  33. this.gender = gender;
  34. }
  35. public String getArea() {
  36. return area;
  37. }
  38. public void setArea(String area) {
  39. this.area = area;
  40. }
  41. public String getSource() {
  42. return source;
  43. }
  44. public void setSource(String source) {
  45. this.source = source;
  46. }
  47. public String getCraw_time() {
  48. return craw_time;
  49. }
  50. public void setCraw_time(String craw_time) {
  51. this.craw_time = craw_time;
  52. }
  53. }

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

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

  1. package renren.renren;
  2. import java.text.DateFormat;
  3. import java.text.SimpleDateFormat;
  4. import java.util.ArrayList;
  5. import java.util.Date;
  6. import java.util.List;
  7. import org.apache.http.HttpResponse;
  8. import org.apache.http.NameValuePair;
  9. import org.apache.http.client.ResponseHandler;
  10. import org.apache.http.client.entity.UrlEncodedFormEntity;
  11. import org.apache.http.client.methods.HttpPost;
  12. import org.apache.http.impl.client.BasicResponseHandler;
  13. import org.apache.http.impl.client.DefaultHttpClient;
  14. import org.apache.http.message.BasicNameValuePair;
  15. import org.apache.http.protocol.HTTP;
  16. import org.jsoup.Jsoup;
  17. import org.jsoup.nodes.Document;
  18. import org.jsoup.nodes.Element;
  19. import org.jsoup.select.Elements;
  20. /* * 合肥工业大学 管理学院 qianyang 1563178220@qq.com */
  21. public class Autohome1 {
  22. private static String AutohomeRenLoginURL = "http://account.autohome.com.cn/Login/ValidIndex";
  23. HttpResponse response;
  24. private DefaultHttpClient httpclient = new DefaultHttpClient();
  25. /* * 这里是模拟登陆的过程 */
  26. private boolean login() {
  27. /* * 用户名及密码 * 在我们抓包的过程中,我们发现我们的密码,被MD5加密了,所以这里有一个将密码,转换成MD5的形式 */
  28. String userName = "";
  29. String password = new MD5().GetMD5Code("");
  30. HttpPost httpost = new HttpPost(AutohomeRenLoginURL);
  31. /* * 建立一个NameValuePair数组,用于存储欲传送的参数 * 不明白这里参数的,请看我前面写的一篇关于模拟登陆网络抓包的的博客 */
  32. List<NameValuePair> nvps = new ArrayList<NameValuePair>();
  33. nvps.add(new BasicNameValuePair("domain", "autohome.com.cn"));
  34. nvps.add(new BasicNameValuePair("isauto", "true"));
  35. nvps.add(new BasicNameValuePair("method", "post"));
  36. nvps.add(new BasicNameValuePair("name", userName));
  37. nvps.add(new BasicNameValuePair("pwd", password));
  38. try {
  39. httpost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8));
  40. response = httpclient.execute(httpost);
  41. } catch (Exception e) {
  42. e.printStackTrace();
  43. return false;
  44. } finally {
  45. httpost.abort();
  46. }
  47. return true;
  48. }
  49. private String getText(String redirectLocation) {
  50. HttpPost httpget = new HttpPost(redirectLocation);
  51. ResponseHandler<String> responseHandler = new BasicResponseHandler();
  52. String responseBody = "";
  53. try {
  54. //获取html文件
  55. responseBody = httpclient.execute(httpget, responseHandler);
  56. } catch (Exception e) {
  57. e.printStackTrace();
  58. responseBody = null;
  59. } finally {
  60. httpget.abort();
  61. }
  62. return responseBody;
  63. }
  64. public String printText(String redirectLocation) {
  65. String htmlText=null;
  66. if (login()) {
  67. if (redirectLocation != null) {
  68. htmlText=getText(redirectLocation);
  69. }
  70. }
  71. return htmlText;
  72. }
  73. /* * 以下是jsoup解析的过程,有不明白Jsoup的上网搜索其API * */
  74. public List<UserInfo> parser(String CrawlerUrl) {
  75. List<UserInfo> UserInfomation = new ArrayList<UserInfo>();
  76. Autohome1 autohome = new Autohome1();
  77. String htmltext=autohome.printText(CrawlerUrl);
  78. Document doc = Jsoup.parse(htmltext);
  79. String authorId="autohome"+doc.select("li[class=current]").select("a").attr("href").replaceAll("\\D","");
  80. Elements dataElements=doc.select("div[class=uData]").select("p");
  81. String source="autohome";
  82. Date date=new Date();
  83. DateFormat format=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  84. String craw_time=format.format(date);
  85. String area="";
  86. String username="";
  87. String gender="";
  88. String birthday="";
  89. for (Element ele:dataElements) {
  90. if (ele.text().contains("所在地")) {
  91. area=ele.text().replaceAll(Jsoup.parse(" ").text(), " ").split(":")[1];
  92. //System.out.println("area:"+area);
  93. }
  94. if (ele.text().contains("性别")) {
  95. gender=ele.text().replaceAll(Jsoup.parse(" ").text(), "").split(":")[1];
  96. //System.out.println("gender:"+gender);
  97. }
  98. if (ele.text().contains("生日")) {
  99. birthday=ele.text().replaceAll(Jsoup.parse(" ").text(), "").split(":")[1];
  100. //System.out.println("birthday:"+birthday);
  101. }
  102. if (ele.text().contains("用户名")) {
  103. username=ele.text().replaceAll(Jsoup.parse(" ").text(), "").split(":")[1];
  104. //System.out.println("birthday:"+username);
  105. }
  106. }
  107. /* * 将数据封装在集合中,返回 */
  108. UserInfo Info = new UserInfo();
  109. Info.setAuthorId(authorId);
  110. Info.setAuthorname(username);
  111. Info.setAge(birthday);
  112. Info.setGender(gender);
  113. Info.setArea(area);
  114. Info.setSource(source);
  115. Info.setCraw_time(craw_time);
  116. UserInfomation.add(Info);
  117. return UserInfomation;
  118. }
  119. public static void main(String[] args){
  120. Autohome1 AutoHome = new Autohome1();
  121. /*需要获取网页的地址*/
  122. String url="http://i.autohome.com.cn/7741675/info";
  123. /*获取数据,解析数据,返回解析之后的数据*/
  124. List<UserInfo> authorInfo=AutoHome.parser(url);
  125. /*打印数据在控制台,这里可以按照前面博客的方法,写入数据库*/
  126. for (UserInfo userinfo:authorInfo) {
  127. System.out.println("ID: "+userinfo.getAuthorId()+" Age: "+userinfo.getAge()+" +Area: "+userinfo.getArea());
  128. }
  129. }
  130. }

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

  1. package renren.renren;
  2. import java.security.MessageDigest;
  3. import java.security.NoSuchAlgorithmException;
  4. /* * 合肥工业大学 管理学院 qianyang 1563178220@qq.com */
  5. public class MD5 {
  6. // 全局数组
  7. private final static String[] strDigits = { "0", "1", "2", "3", "4", "5",
  8. "6", "7", "8", "9", "a", "b", "c", "d", "e", "f" };
  9. public MD5() {
  10. }
  11. // 返回形式为数字跟字符串
  12. private static String byteToArrayString(byte bByte) {
  13. int iRet = bByte;
  14. // System.out.println("iRet="+iRet);
  15. if (iRet < 0) {
  16. iRet += 256;
  17. }
  18. int iD1 = iRet / 16;
  19. int iD2 = iRet % 16;
  20. return strDigits[iD1] + strDigits[iD2];
  21. }
  22. // 返回形式只为数字
  23. private static String byteToNum(byte bByte) {
  24. int iRet = bByte;
  25. System.out.println("iRet1=" + iRet);
  26. if (iRet < 0) {
  27. iRet += 256;
  28. }
  29. return String.valueOf(iRet);
  30. }
  31. // 转换字节数组为16进制字串
  32. private static String byteToString(byte[] bByte) {
  33. StringBuffer sBuffer = new StringBuffer();
  34. for (int i = 0; i < bByte.length; i++) {
  35. sBuffer.append(byteToArrayString(bByte[i]));
  36. }
  37. return sBuffer.toString();
  38. }
  39. public static String GetMD5Code(String strObj) {
  40. String resultString = null;
  41. try {
  42. resultString = new String(strObj);
  43. MessageDigest md = MessageDigest.getInstance("MD5");
  44. // md.digest() 该函数返回值为存放哈希值结果的byte数组
  45. resultString = byteToString(md.digest(strObj.getBytes()));
  46. } catch (NoSuchAlgorithmException ex) {
  47. ex.printStackTrace();
  48. }
  49. return resultString;
  50. }
  51. }

结果展示

这里写图片描述

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

发表评论

表情:
评论列表 (有 0 条评论,290人围观)

还没有评论,来说两句吧...

相关阅读