使用httpclient、htmlcleaner 、xpath 采集新浪微博3G站点数据


转载:http://blog.csdn.net/telnetor/article/details/8582045

0、背景

原来对新浪微博的采集主要靠对weibo.com这个入口进行,但是最近发现有人使用weibo.cn这个入口操作。应为weibo.cn对应的是微博的3g版本,基本没有广告,页面小,这样下载数据量会小很多,并且3g版本的采集比较简单。于是就有了这个3g版本的采集程序。

写出来,分享给大家,希望对有需要的朋友有所帮助。


使用到的类库:httpclient、htmlcleaner

httpclient负责处理http的get和post请求,下载页面;htmlcleaner负责将下载的页面转化为规范的xml,之后用xpath匹配所需内容。


1、基础的http请求类

[java]  view plain copy
  1. package cn.mingyuan.weibo.commons;  
  2.   
  3. import org.apache.http.client.HttpClient;  
  4. import org.apache.http.client.methods.HttpRequestBase;  
  5. import org.apache.http.impl.client.DefaultHttpClient;  
  6.   
  7. /** 
  8.  * http请求基类 
  9.  *  
  10.  * @author mingyuan 
  11.  *  
  12.  */  
  13. public abstract class RequestCommons {  
  14.     protected HttpClient httpclient = null;  
  15.   
  16.     public RequestCommons() {  
  17.         initHttpClient();  
  18.     }  
  19.   
  20.     /** 
  21.      * 初始化httpclient 
  22.      */  
  23.     protected void initHttpClient() {  
  24.         httpclient = new DefaultHttpClient();  
  25.     }  
  26.   
  27.     protected HttpClient getHttpClient() {  
  28.         return httpclient;  
  29.     }  
  30.   
  31.     protected void addHeader(HttpRequestBase request, String key, String value) {  
  32.         request.addHeader(key, value);  
  33.     }  
  34.   
  35.     protected void addCookie(HttpRequestBase request, String cookie) {  
  36.         addHeader(request, "Cookie", cookie);  
  37.     }  
  38.   
  39.     protected void setCookie(HttpRequestBase request, String cookie) {  
  40.         request.setHeader("Cookie", cookie);  
  41.     }  
  42.   
  43.     /** 
  44.      * 设置请求的header值 
  45.      *  
  46.      * @param request 
  47.      *            http的get或者post请求 
  48.      */  
  49.     protected void setHeader(HttpRequestBase request) {  
  50.         request.setHeader("Accept""text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");  
  51.         request.setHeader("Accept-Language""en-us,en;q=0.5");  
  52.         request.setHeader("Connection""keep-alive");  
  53.         request.setHeader("User-Agent""Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:13.0) Gecko/20100101 Firefox/13.0.1");  
  54.     }  
  55. }  
2、weibo.cn登陆

[java]  view plain copy
  1. package cn.mingyuan.weibo.login;  
  2.   
  3. import java.io.IOException;  
  4. import java.io.InputStream;  
  5. import java.io.UnsupportedEncodingException;  
  6. import java.util.ArrayList;  
  7. import java.util.List;  
  8. import java.util.concurrent.TimeUnit;  
  9.   
  10. import org.apache.http.Header;  
  11. import org.apache.http.HttpEntity;  
  12. import org.apache.http.HttpResponse;  
  13. import org.apache.http.NameValuePair;  
  14. import org.apache.http.client.ClientProtocolException;  
  15. import org.apache.http.client.HttpClient;  
  16. import org.apache.http.client.entity.UrlEncodedFormEntity;  
  17. import org.apache.http.client.methods.HttpGet;  
  18. import org.apache.http.client.methods.HttpPost;  
  19. import org.apache.http.message.BasicNameValuePair;  
  20. import org.apache.http.util.EntityUtils;  
  21. import org.htmlcleaner.HtmlCleaner;  
  22. import org.htmlcleaner.TagNode;  
  23. import org.htmlcleaner.XPatherException;  
  24.   
  25. import cn.mingyuan.weibo.commons.RequestCommons;  
  26. import cn.mingyuan.weibo.until.Constants;  
  27.   
  28. /** 
  29.  * 登陆 获取cookie 
  30.  *  
  31.  * @author mingyuan 
  32.  *  
  33.  */  
  34. public class Login extends RequestCommons {  
  35.     /** 
  36.      * 获取登陆参数。主要有三个值:第一个是表单提交地址、第二个是密码输入框的名字、第三个是vk的值 
  37.      *  
  38.      * @return 返回登陆参数,string数组,里面的元素:第一个是表单提交地址、第二个是密码输入框的名字、第三个是vk的值 
  39.      */  
  40.     private String[] getLoginParameters() {  
  41.         HttpClient httpClient = getHttpClient();  
  42.         String location = "http://3g.sina.com.cn/prog/wapsite/sso/login.php?backURL=http%3A%2F%2Fweibo.cn%2F&backTitle=%D0%C2%C0%CB%CE%A2%B2%A9&vt=4&revalid=2&ns=1";  
  43.         HttpGet get = new HttpGet(location);  
  44.         setHeader(get);  
  45.         HttpResponse response;  
  46.         InputStream content;  
  47.         String retAction = null;  
  48.         String retPassword = null;  
  49.         String retVk = null;  
  50.         try {  
  51.             response = httpClient.execute(get);  
  52.             HttpEntity entity = response.getEntity();  
  53.             content = entity.getContent();  
  54.   
  55.             // 提取登陆参数  
  56.             HtmlCleaner cleaner = new HtmlCleaner();  
  57.             TagNode tagNode = cleaner.clean(content, "utf-8");  
  58.             Object[] action = tagNode.evaluateXPath("//form/@action");  
  59.   
  60.             if (action.length > 0) {  
  61.                 retAction = action[0].toString();  
  62.             }  
  63.             Object[] passwordKey = tagNode.evaluateXPath("//form//input[@type='password']/@name");  
  64.   
  65.             if (passwordKey.length > 0) {  
  66.                 retPassword = passwordKey[0].toString();  
  67.             }  
  68.             Object[] vkKey = tagNode.evaluateXPath("//form//input[@name='vk']/@value");  
  69.   
  70.             if (vkKey.length > 0) {  
  71.                 retVk = vkKey[0].toString();  
  72.             }  
  73.             EntityUtils.consume(entity);  
  74.         } catch (ClientProtocolException e) {  
  75.             System.out.println("获取登陆页面失败,location=" + location);  
  76.             e.printStackTrace();  
  77.         } catch (IOException e) {  
  78.             System.out.println("获取页面内容流失败");  
  79.             e.printStackTrace();  
  80.         } catch (XPatherException e) {  
  81.             System.out.println("解析登陆参数失败");  
  82.             e.printStackTrace();  
  83.         } finally {  
  84.             if (get != null) {  
  85.                 get.releaseConnection();  
  86.             }  
  87.         }  
  88.   
  89.         System.out.println("请求页面:" + location);  
  90.         System.out.println("提交地址:" + retAction);  
  91.         System.out.println("密码输入框名称:" + retPassword);  
  92.         System.out.println("vk值:" + retVk);  
  93.   
  94.         return new String[] { retAction, retPassword, retVk };  
  95.     }  
  96.   
  97.     /** 
  98.      * 提交账号密码,开始登陆 
  99.      *  
  100.      * @param postAction 
  101.      *            登陆地址 
  102.      * @param userNameValue 
  103.      *            微博登陆账号 
  104.      * @param passwordValue 
  105.      *            微博登陆密码 
  106.      * @param passwordKey 
  107.      *            微博登陆框的name 
  108.      * @param vkValue 
  109.      *            vk的值 
  110.      * @return 返回取到的cookie与跳转地址,组合成一个String数组。第一个元素为cookie,第二个元素为跳转地址 
  111.      */  
  112.     private String[] submitPassword(String postAction, String userNameValue, String passwordValue, String passwordKey, String vkValue) {  
  113.         HttpClient httpclient = getHttpClient();  
  114.         String url = "http://3g.sina.com.cn/prog/wapsite/sso/" + postAction;  
  115.         System.out.println("开始提交账号密码:" + url);  
  116.         HttpPost post = new HttpPost(url);  
  117.         setHeader(post);  
  118.         List<NameValuePair> nvps = new ArrayList<NameValuePair>();  
  119.         nvps.add(new BasicNameValuePair("mobile", userNameValue));  
  120.         nvps.add(new BasicNameValuePair(passwordKey, passwordValue));  
  121.         nvps.add(new BasicNameValuePair("remember""on"));  
  122.         nvps.add(new BasicNameValuePair("vk", vkValue));  
  123.         nvps.add(new BasicNameValuePair("backURL""http://weibo.cn/"));  
  124.         nvps.add(new BasicNameValuePair("backTitle""新浪微博"));  
  125.         nvps.add(new BasicNameValuePair("submit""登录"));  
  126.         HttpResponse response;  
  127.         String cookie = null;  
  128.         String location = null;  
  129.         try {  
  130.             post.setEntity(new UrlEncodedFormEntity(nvps));  
  131.             response = httpclient.execute(post);  
  132.             HttpEntity entity2 = response.getEntity();  
  133.             Header[] setCookie = response.getHeaders("Set-Cookie");  
  134.   
  135.             if (setCookie != null) {  
  136.                 cookie = setCookie[0].getValue();  
  137.                 System.out.println("获取到Cookie:" + cookie);  
  138.             }  
  139.             Header[] locations = response.getHeaders("Location");  
  140.             if (locations != null) {  
  141.                 location = locations[0].getValue();  
  142.                 System.out.println("获取到跳转链接:" + location);  
  143.             }  
  144.             EntityUtils.consume(entity2);  
  145.         } catch (UnsupportedEncodingException e1) {  
  146.             e1.printStackTrace();  
  147.         } catch (ClientProtocolException e) {  
  148.             e.printStackTrace();  
  149.         } catch (IOException e) {  
  150.             e.printStackTrace();  
  151.         } finally {  
  152.             post.releaseConnection();  
  153.         }  
  154.   
  155.         return new String[] { cookie, location };  
  156.     }  
  157.   
  158.     /** 
  159.      * 获取重定向页面内容 
  160.      *  
  161.      * @param redirectUrl 
  162.      *            获取重定向页面地址 
  163.      * @return 获取cookie和要跳转的地址 
  164.      */  
  165.     private String[] getRedirectPageInfo(String redirectUrl) {  
  166.         System.out.println("开始获取跳转链接页面");  
  167.         HttpGet get = new HttpGet(redirectUrl);  
  168.         setHeader(get);  
  169.         HttpResponse redirectResponse;  
  170.         String cookie = null;  
  171.         String clickHref = null;  
  172.         try {  
  173.             redirectResponse = httpclient.execute(get);  
  174.             Header[] headers = redirectResponse.getHeaders("Set-Cookie");  
  175.             if (headers != null) {  
  176.                 cookie = headers[0].getValue();  
  177.                 String[] splits = cookie.split(";");  
  178.   
  179.                 for (String str : splits) {  
  180.                     if (str.startsWith("gsid_CTandWM")) {  
  181.                         cookie = str;  
  182.                         break;  
  183.                     }  
  184.                 }  
  185.             }  
  186.             HttpEntity entity = redirectResponse.getEntity();  
  187.             InputStream content = entity.getContent();  
  188.             HtmlCleaner cleaner = new HtmlCleaner();  
  189.             TagNode tagNode = cleaner.clean(content, "utf-8");  
  190.             Object[] clickHrefs = tagNode.evaluateXPath("//div/a/@href");  
  191.   
  192.             if (clickHrefs != null) {  
  193.                 clickHref = clickHrefs[0].toString();  
  194.                 System.out.println("获取到跳转链接地址:" + clickHref);  
  195.   
  196.             }  
  197.             EntityUtils.consume(entity);  
  198.         } catch (ClientProtocolException e) {  
  199.             e.printStackTrace();  
  200.         } catch (IOException e) {  
  201.             e.printStackTrace();  
  202.         } catch (XPatherException e) {  
  203.             e.printStackTrace();  
  204.         } finally {  
  205.             get.releaseConnection();  
  206.         }  
  207.         return new String[] { cookie, clickHref };  
  208.     }  
  209.   
  210.     /** 
  211.      * 跳转 
  212.      *  
  213.      * @param cookie 
  214.      *            上次请求取到的cookie 
  215.      * @param redirectUrl 
  216.      *            跳转url 
  217.      * @return 返回跳转后取得的cookie 
  218.      */  
  219.     private String doRedirection(String cookie, String redirectUrl) {  
  220.         HttpGet get = new HttpGet(redirectUrl);  
  221.         setHeader(get);  
  222.         get.setHeader("Cookie", cookie);  
  223.         HttpResponse response;  
  224.         try {  
  225.             response = httpclient.execute(get);  
  226.             HttpEntity entity = response.getEntity();  
  227.             Header[] headers2 = response.getHeaders("Set-Cookie");  
  228.             if (headers2 != null) {  
  229.                 cookie = headers2[0].getValue();  
  230.                 System.out.println("跳转页面取回的cookie:" + cookie);  
  231.                 String[] splits = cookie.split(";");  
  232.                 for (String str : splits) {  
  233.                     if (str.startsWith("_WEIBO_UID")) {  
  234.                         cookie = str;  
  235.                         break;  
  236.                     }  
  237.                 }  
  238.             }  
  239.             EntityUtils.consume(entity);  
  240.         } catch (ClientProtocolException e) {  
  241.             e.printStackTrace();  
  242.         } catch (IOException e) {  
  243.             e.printStackTrace();  
  244.         }  
  245.         return cookie;  
  246.     }  
  247.   
  248.     /** 
  249.      * 提交账号密码,登陆 
  250.      *  
  251.      * @param userNameValue 
  252.      *            微博账号 
  253.      * @param passwordValue 
  254.      *            微博密码 
  255.      * @return 返回cookie 
  256.      */  
  257.     public String doLogin(String userNameValue, String passwordValue) {  
  258.         // 获取登陆页面的参数  
  259.         String[] loginParameters = getLoginParameters();  
  260.         String postAction = loginParameters[0];  
  261.         String passwordKey = loginParameters[1];  
  262.         String vkValue = loginParameters[2];  
  263.   
  264.         // 提交账号密码,获取重定向页面链接与cookie  
  265.         String[] cookieRedirectLocation = submitPassword(postAction, userNameValue, passwordValue, passwordKey, vkValue);  
  266.         String cookie = cookieRedirectLocation[0];  
  267.         String redirectUrl = cookieRedirectLocation[1];  
  268.         // 获取重定向页面内容  
  269.         String[] redirectInfo = getRedirectPageInfo(redirectUrl);  
  270.         cookie = redirectInfo[0];  
  271.         redirectUrl = redirectInfo[1];  
  272.         System.out.println("准备跳转");  
  273.         try {  
  274.             TimeUnit.SECONDS.sleep(3);  
  275.         } catch (InterruptedException e) {  
  276.             e.printStackTrace();  
  277.         }  
  278.         System.out.println("开始跳转");  
  279.         String cookieOfRedirect = doRedirection(cookie, redirectUrl);  
  280.   
  281.         StringBuffer sb = new StringBuffer(cookie);  
  282.         sb.append(';').append(cookieOfRedirect);  
  283.         System.out.println("登陆成功,最终cookie为:" + sb.toString());  
  284.         return sb.toString();  
  285.     }  
  286.   
  287.     /** 
  288.      * 使用配置的账号、密码登陆 
  289.      *  
  290.      * @return 返回登陆cookie 
  291.      */  
  292.     public String doLogin() {  
  293.         return this.doLogin(Constants.LOGIN_USERNAME, Constants.LOGIN_PASSWORD);  
  294.     }  
  295. }  

3、测试

步骤:先登录取cookie再拿cookie填到请求里面取页面内容


[java]  view plain copy
  1. package cn.mingyuan.weibo.test;  
  2.   
  3. import java.io.BufferedReader;  
  4. import java.io.IOException;  
  5. import java.io.InputStream;  
  6. import java.io.InputStreamReader;  
  7.   
  8. import org.apache.http.HttpEntity;  
  9. import org.apache.http.HttpResponse;  
  10. import org.apache.http.client.ClientProtocolException;  
  11. import org.apache.http.client.methods.HttpGet;  
  12. import org.apache.http.util.EntityUtils;  
  13.   
  14. import cn.mingyuan.weibo.commons.RequestCommons;  
  15. import cn.mingyuan.weibo.login.Login;  
  16. /** 
  17.  * 测试,取页面内容 
  18.  * @author mingyuan 
  19.  * 
  20.  */  
  21. public class WeiboTest extends RequestCommons {  
  22.   
  23.     /** 
  24.      * 打印流 
  25.      *  
  26.      * @param in 
  27.      *            InputStream 
  28.      */  
  29.     private void printContent(InputStream in) {  
  30.         BufferedReader reader = null;  
  31.         try {  
  32.             reader = new BufferedReader(new InputStreamReader(in, "utf-8"));  
  33.             String line;  
  34.             while ((line = reader.readLine()) != null) {  
  35.                 System.out.println(line);  
  36.             }  
  37.         } catch (Exception e) {  
  38.             e.printStackTrace();  
  39.         } finally {  
  40.             // 这里不关闭流,留作他用  
  41.         }  
  42.     }  
  43.   
  44.     /** 
  45.      * 测试,读取一个微博地址,打印出页面内容 
  46.      *  
  47.      * @param finalCookie 
  48.      *            cookie 
  49.      */  
  50.     private void test(String finalCookie) {  
  51.         HttpGet get = new HttpGet("http://weibo.cn/irlucene");  
  52.         setHeader(get);  
  53.         get.setHeader("Cookie", finalCookie.toString());  
  54.         HttpResponse response;  
  55.         try {  
  56.             response = httpclient.execute(get);  
  57.             HttpEntity entity = response.getEntity();  
  58.             printContent(entity.getContent());  
  59.             EntityUtils.consume(entity);  
  60.         } catch (ClientProtocolException e) {  
  61.             e.printStackTrace();  
  62.         } catch (IOException e) {  
  63.             e.printStackTrace();  
  64.         } finally {  
  65.             get.releaseConnection();  
  66.         }  
  67.     }  
  68.   
  69.     public static void main(String[] args) {  
  70.         Login login = new Login();  
  71.         String userNameValue = "username";  
  72.         String passwordValue = "password";  
  73.         String cookie = login.doLogin(userNameValue, passwordValue);  
  74.         System.out.println("final Cookie=" + cookie);  
  75.         new WeiboTest().test(cookie);  
  76.     }  
  77.   
  78. }  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值