httpclient 人人网

时间:2021-10-27 00:34:42

登录的站点是3g.renren.com 因为是手机人人, 页面比较简单

首先用HttpGet取出"http://3g.renren.com"的html代码, 是用Jsoup解析出登录表单, 包括验证码的图片的url

因为没法做到绕过验证码,所以用验证码的url构建一个image, 显示出来让用户自己填写

构建image时一定要用httpget, 开始使用了ImageIO.read(new URL(url)); 这样, HttpClient实例中没有管理session

不写了, 全放到注释里去了, 直接上代码

因为程序很依赖html源码, 哪天人人的前台改动了html代码说不定就用不了了

  1. package com.renren.main;
  2. import java.awt.Graphics;
  3. import java.awt.Image;
  4. import java.awt.event.ActionEvent;
  5. import java.awt.event.ActionListener;
  6. import java.awt.image.BufferedImage;
  7. import java.io.IOException;
  8. import java.io.InputStream;
  9. import java.util.ArrayList;
  10. import java.util.HashMap;
  11. import java.util.List;
  12. import java.util.Map;
  13. import javax.imageio.ImageIO;
  14. import javax.swing.JButton;
  15. import javax.swing.JFrame;
  16. import javax.swing.JPanel;
  17. import javax.swing.JPasswordField;
  18. import javax.swing.JTextArea;
  19. import javax.swing.JTextField;
  20. import org.apache.http.HttpEntity;
  21. import org.apache.http.HttpResponse;
  22. import org.apache.http.HttpStatus;
  23. import org.apache.http.NameValuePair;
  24. import org.apache.http.client.ClientProtocolException;
  25. import org.apache.http.client.HttpClient;
  26. import org.apache.http.client.ResponseHandler;
  27. import org.apache.http.client.entity.UrlEncodedFormEntity;
  28. import org.apache.http.client.methods.HttpGet;
  29. import org.apache.http.client.methods.HttpPost;
  30. import org.apache.http.impl.client.BasicResponseHandler;
  31. import org.apache.http.impl.client.DefaultHttpClient;
  32. import org.apache.http.message.BasicNameValuePair;
  33. import org.apache.http.protocol.HTTP;
  34. import org.jsoup.Jsoup;
  35. import org.jsoup.nodes.Document;
  36. import org.jsoup.nodes.Element;
  37. import org.jsoup.select.Elements;
  38. public class Login extends JFrame implements ActionListener{
  39. private JTextField email;
  40. private JPasswordField password;
  41. private JTextField verifycode;
  42. private JButton login;
  43. private ImageBoxPanel imageBox;
  44. private Image image;
  45. private MsgBox box;
  46. private final HttpClient client;
  47. private HttpPost post;
  48. private HttpGet get;
  49. private HttpResponse response;
  50. private ResponseHandler<String> responseHandler;
  51. private Map<String, String> form_map;
  52. private boolean flag;//有没有验证码
  53. private String html;
  54. public Login() {
  55. super("人人登录");
  56. client = new DefaultHttpClient();
  57. responseHandler = new BasicResponseHandler();
  58. form_map = new HashMap<String, String>();
  59. Object obj;
  60. setLayout(null);
  61. setDefaultCloseOperation(EXIT_ON_CLOSE);
  62. setResizable(false);
  63. email = new JTextField("<email>");
  64. password = new JPasswordField("<password>");
  65. verifycode = new JTextField();
  66. login = new JButton("登录");
  67. login.addActionListener(this);
  68. html = view("http://3g.renren.com");
  69. init();
  70. try {
  71. imageBox = new ImageBoxPanel(createBufferedImage());
  72. } catch (Exception e) {
  73. e.printStackTrace();
  74. imageBox = new ImageBoxPanel();
  75. }
  76. //layout
  77. this.setBounds(500, 300, 280, 220);
  78. email.setBounds(10, 10, 250, 30);
  79. password.setBounds(10, 50, 250, 30);
  80. verifycode.setBounds(10, 90, 150, 30);
  81. imageBox.setBounds(205, 80, 54, 46);
  82. login.setBounds(10, 130, 250, 30);
  83. add(email);
  84. add(password);
  85. add(verifycode);
  86. add(imageBox);
  87. add(login);
  88. setVisible(true);
  89. }
  90. private BufferedImage createBufferedImage() {
  91. InputStream inputstream=null;
  92. try {
  93. String source = view("http://3g.renren.com");
  94. String url = getVerifycodeUrl(source);
  95. if("error".equals(url)) {
  96. return null;
  97. }
  98. ///rndimg?post=_REQUESTFRIEND_de6073b242a6fc34b67d228abf982916&rnd=1335096399071
  99. //分析登录表单可以发现如果某次登录需要验证码, 则表单中会有verifykey和verifycode
  100. //而verifykey 的值正好是验证码地址中的一部分(中间的32位字符), 所以把verifykey取出来
  101. String key = url;
  102. key = key.replaceAll("http[\\d\\D]*ND_", "");
  103. key = key.replaceAll("&[\\d\\D]*", "");
  104. form_map.put("verifykey", key);//更新下verifykey,和当前验证码对应
  105. System.out.println(key);
  106. get = new HttpGet(url);
  107. response = client.execute(get);
  108. if(HttpStatus.SC_OK == response.getStatusLine().getStatusCode()) {//以下两个if是网上摘来得
  109. HttpEntity entity = response.getEntity();
  110. if (entity != null) {
  111. inputstream = entity.getContent();
  112. //本来返回的是一个InputStream, 但是在finally中调用get.abort()后好像会变成null, 没办法, 所以直接构造出BufferedImage返回
  113. return ImageIO.read(inputstream);
  114. }
  115. }
  116. } catch (Exception e) {
  117. e.printStackTrace();
  118. } finally {
  119. get.abort();
  120. }
  121. return null;
  122. }
  123. /**
  124. * 获取某个url的html代码
  125. * @param url
  126. * @return
  127. */
  128. private String view(String url) {
  129. String html;
  130. try {
  131. get = new HttpGet("http://3g.renren.com/");
  132. html = client.execute(get, responseHandler);
  133. } catch (Exception e) {
  134. e.printStackTrace();
  135. html = "error";
  136. } finally {
  137. get.abort();
  138. }
  139. return html;
  140. }
  141. /**
  142. * 获取验证码图片的地址
  143. * @param source 某个页面的页面源代码
  144. * @return
  145. */
  146. private String getVerifycodeUrl(String source) {
  147. String url;
  148. flag = true;
  149. try {
  150. Document doc = Jsoup.parse(source);
  151. //分析表单可知此句可用, 不过用这种方法来做比较不好的一点就是一旦人人页面稍微改动下, 这个程序就可能用不了了
  152. Element e = doc.getElementsByAttributeValueContaining("alt", "此处为验证码").get(0);
  153. url = e.attr("src");
  154. url = "http://3g.renren.com" + url;
  155. } catch (Exception e) {
  156. //本来会打印异常信息, 不过看着不舒服, 就删了
  157. //大致就是有时没有验证码, 那么上面的get(0)肯定就行不通了
  158. System.out.println("没有验证码~");
  159. url = "error";
  160. flag = false;//标记有没有验证码, 可以让verifykey 和 verifycode 两个属性是否通过表单传过去
  161. }
  162. return url;
  163. }
  164. private void init() {
  165. String html = view("http://3g.renren.com");
  166. Document doc = Jsoup.parse(html);//取出3g.renren.com代码
  167. Element form = doc.getElementsByTag("form").get(0);
  168. String action = form.attr("action");
  169. form_map.put("action", action);
  170. Elements es = form.getElementsByTag("input");
  171. for(Element e: es) {
  172. form_map.put(e.attr("name"), e.attr("value"));
  173. }
  174. }
  175. @Override
  176. public void actionPerformed(ActionEvent e) {
  177. login();
  178. System.out.println(view("http://3g.renren.com"));
  179. //登录成功后显示发心情的界面, 主要实现了个功能, 没有考虑到其他的方面
  180. //包括是否登录成功啊, 是否发心情成功失败啊
  181. //不过这些还是挺简单的, 无非就是解析post后的html代码, 看会不会出现哪些错误信息
  182. box = new MsgBox();
  183. }
  184. private boolean login() {
  185. post = new HttpPost(form_map.get("action"));
  186. //据说有些网站如果不设置头会被过滤掉, 毕竟人人还是蛮大的一个网站, 就加上吧
  187. post.setHeader("User-Agent", "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/534.3 (KHTML, like Gecko) Chrome/6.0.472.63 Safari/534.3");
  188. List<NameValuePair> nvp = new ArrayList<NameValuePair>();
  189. nvp.add(new BasicNameValuePair("origURL", form_map.get("origURL")));
  190. nvp.add(new BasicNameValuePair("lbskey", form_map.get("lbskey")));
  191. nvp.add(new BasicNameValuePair("c", form_map.get("c")));
  192. nvp.add(new BasicNameValuePair("ref", form_map.get("ref")));
  193. nvp.add(new BasicNameValuePair("email", email.getText()));
  194. nvp.add(new BasicNameValuePair("password", new String(password.getPassword())));
  195. nvp.add(new BasicNameValuePair("pq", form_map.get("pq")));
  196. if(flag) {
  197. nvp.add(new BasicNameValuePair("verifycode", verifycode.getText()));
  198. nvp.add(new BasicNameValuePair("verifykey", form_map.get("verifykey")));
  199. }
  200. //  System.out.println(form_map.get("verifykey"));
  201. try {
  202. post.setEntity(new UrlEncodedFormEntity(nvp, HTTP.UTF_8));
  203. //response = client.execute(post);
  204. client.execute(post);
  205. } catch (Exception e) {
  206. e.printStackTrace();
  207. return false;
  208. } finally {
  209. post.abort();
  210. }
  211. return true;
  212. }
  213. public static void main(String[] args) {
  214. Login renren = new Login();
  215. //  System.out.println(renren.view("http://3g.renren.com"));
  216. }
  217. class MsgBox extends JFrame implements ActionListener {
  218. JTextArea msg;
  219. JButton submit;
  220. //某条心情发送次数, 本来想搞个刷屏的, 不过不太给力, 设置了休眠一段时间还是可以成功的
  221. JTextField time;
  222. public MsgBox() {
  223. setLayout(null);
  224. setResizable(false);
  225. setBounds(500, 500, 365, 125);
  226. msg = new JTextArea();
  227. submit = new JButton("发送~");
  228. time = new JTextField("1");
  229. msg.setBounds(10, 10, 250, 80);
  230. time.setBounds(270, 10, 81, 40);
  231. submit.setBounds(270, 50, 80, 40);
  232. submit.addActionListener(this);
  233. add(msg);
  234. add(submit);
  235. add(time);
  236. setVisible(true);
  237. }
  238. @Override
  239. public void actionPerformed(ActionEvent e) {
  240. for(int i = 0; i < Integer.parseInt(time.getText()); i++) {
  241. post = new HttpPost("http://3g.renren.com/status/wUpdateStatus.do");//反正都是从先认为的登录, 再把一些信息抓下来
  242. post.setHeader("User-Agent", "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/534.3 (KHTML, like Gecko) Chrome/6.0.472.63 Safari/534.3");
  243. List<NameValuePair> nvp = new ArrayList<NameValuePair>();
  244. nvp.add(new BasicNameValuePair("_rtk", "xxxxxxxx"));//这个不知道是怎么产生的, 可能每一个id都有对应一个把
  245. nvp.add(new BasicNameValuePair("sour", ""));
  246. nvp.add(new BasicNameValuePair("loginbybm", ""));
  247. nvp.add(new BasicNameValuePair("status", msg.getText() + i));//其他几个都无关紧要, 不过还是留着
  248. nvp.add(new BasicNameValuePair("pid", ""));
  249. nvp.add(new BasicNameValuePair("empty", "1"));
  250. try {
  251. post.setEntity(new UrlEncodedFormEntity(nvp, HTTP.UTF_8));
  252. response = client.execute(post);
  253. System.out.println(response);
  254. Thread.sleep(1000L);//没有设置休眠应该是被人人过滤掉了,具体多少时间间隔可以发一次没有测试过, 不过估计500毫秒应该是没有问题的吧
  255. } catch (Exception e1) {
  256. e1.printStackTrace();
  257. } finally {
  258. post.abort();
  259. }
  260. }
  261. }
  262. }
  263. }
  264. class ImageBoxPanel extends JPanel {
  265. private Image image;
  266. public ImageBoxPanel(Image image) {
  267. this.image = image;
  268. }
  269. public ImageBoxPanel() {
  270. }
  271. @Override
  272. protected void paintComponent(Graphics g) {
  273. g.drawImage(image, 0, 0, 54, 46, null);
  274. }
  275. }
  276. 转载出处:http://blog.csdn.net/ping_qc/article/details/7487352