A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

作者:卧颜沉默
链接:https://www.zhihu.com/question/36909173/answer/97643000
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

最近写了一个基于JAVA的知乎爬虫,抓取知乎用户基本信息。
基于HttpClient 4.5的
在服务器上跑着的
到现在抓取了60W+用户


可以对这些数据做简单的挖掘,可以得到很多有趣的信息。

下面说下我的大致思路:
1.首先模拟登录知乎,登录成功后将Cookie序列化到磁盘,不用以后每次都登录(如果不模拟登录,可以直接从浏览器塞入Cookie也是可以的)。


模拟登录通过浏览器F12抓包分析登录过程,需要注意的是验证码的获取和登录过程只能通过一个CloseHttpClient对象完成,CloseHttpClient就好比一个浏览器。不能每次请求都创建对象,不然Cookie失效了。


模拟登录关键代码如下,是通过邮箱登录方式,手机号码登录的方式类似

  1. 作者:卧颜沉默
  2. 链接:https://www.zhihu.com/question/36909173/answer/97643000
  3. 来源:知乎
  4. 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

  5.     /**
  6.      *
  7.      * @param httpClient Http客户端
  8.      * @param context Http上下文
  9.      * @return
  10.      */
  11. public boolean login(CloseableHttpClient httpClient, HttpClientContext context){
  12. String yzm = null;
  13. String loginState = null;
  14. HttpGet getRequest = new HttpGet("https://www.zhihu.com/#signin");
  15. HttpClientUtil.getWebPage(httpClient,context, getRequest, "utf-8", false);
  16. HttpPost request = new HttpPost("https://www.zhihu.com/login/email");
  17. List<NameValuePair> formParams = new ArrayList<NameValuePair>();
  18. yzm = yzm(httpClient, context,"https://www.zhihu.com/captcha.gif?type=login");//肉眼识别验证码
  19. formParams.add(new BasicNameValuePair("captcha", yzm));
  20. formParams.add(new BasicNameValuePair("_xsrf", ""));//这个参数可以不用
  21. formParams.add(new BasicNameValuePair("email", "邮箱"));
  22. formParams.add(new BasicNameValuePair("password", "密码"));
  23. formParams.add(new BasicNameValuePair("remember_me", "true"));
  24. UrlEncodedFormEntity entity = null;
  25. try {
  26. entity = new UrlEncodedFormEntity(formParams, "utf-8");
  27. } catch (UnsupportedEncodingException e) {
  28. e.printStackTrace();
  29. }
  30. request.setEntity(entity);
  31. loginState = HttpClientUtil.getWebPage(httpClient,context, request, "utf-8", false);//登录
  32. JSONObject jo = new JSONObject(loginState);
  33. if(jo.get("r").toString().equals("0")){
  34. System.out.println("登录成功");
  35. getRequest = new HttpGet("https://www.zhihu.com");
  36. HttpClientUtil.getWebPage(httpClient,context ,getRequest, "utf-8", false);//访问首页
  37. HttpClientUtil.serializeObject(context.getCookieStore(),"resources/zhihucookies");//序列化知乎Cookies,下次登录直接通过该cookies登录
  38. return true;
  39. }else{
  40. System.out.println("登录失败" + loginState);
  41. return false;
  42. }
  43. }
  44. /**
  45.      * 肉眼识别验证码
  46.      * @param httpClient Http客户端
  47.      * @param context Http上下文
  48.      * @param url 验证码地址
  49.      * @return
  50.      */
  51. public String yzm(CloseableHttpClient httpClient,HttpClientContext context, String url){
  52. HttpClientUtil.downloadFile(httpClient, context, url, "d:/test/", "1.gif",true);
  53. Scanner sc = new Scanner(System.in);
  54. String yzm = sc.nextLine();
  55. return yzm;
  56. }
  57. HttpClientUtil工具类
  58. /**
  59. * HttpClient工具类
  60. */
  61. public class HttpClientUtil {
  62.         private static Logger logger = MyLogger.getMyLogger(HttpClientUtil.class);
  63.         public static void main(String args []){
  64.         }
  65.         /**
  66.          *
  67.          * @param httpClient HttpClient客户端
  68.          * @param context 上下文
  69.          * @param request 请求
  70.          * @param encoding 字符编码
  71.          * @param isPrintConsole 是否打印到控制台
  72.      * @return 网页内容
  73.      */
  74.         public static String getWebPage(CloseableHttpClient httpClient
  75.                         , HttpClientContext context
  76.                         , HttpRequestBase request
  77.                         , String encoding
  78.                         , boolean isPrintConsole){
  79.                 CloseableHttpResponse response = null;
  80.                 try {
  81.                         response = httpClient.execute(request,context);
  82.                 } catch (HttpHostConnectException e){
  83.                         e.printStackTrace();
  84.                         logger.error("HttpHostConnectException",e);
  85.                 } catch (IOException e) {
  86.                         e.printStackTrace();
  87.                         logger.error("IOException",e);
  88.                 }
  89.                 System.out.println("status---" + response.getStatusLine().getStatusCode());
  90.                 BufferedReader rd = null;
  91.                 StringBuilder webPage = null;
  92.                 try {
  93.                         rd = new BufferedReader(
  94.                     new InputStreamReader(response.getEntity().getContent(),encoding));
  95.                         String line = "";
  96.                         webPage = new StringBuilder();
  97.                         while((line = rd.readLine()) != null) {
  98.                                 webPage.append(line);
  99.                                 if(isPrintConsole){
  100.                                         System.out.println(line);
  101.                                 }
  102.                         }
  103.                 } catch (IOException e) {
  104.                         e.printStackTrace();
  105.                 }
  106.                 request.releaseConnection();
  107.                 return webPage.toString();
  108.         }
  109.         /**
  110.          * 序列化对象
  111.          * @param object
  112.          * @throws Exception
  113.          */
  114.         public static void serializeObject(Object object,String filePath){
  115.                 OutputStream fos = null;
  116.                 try {
  117.                         fos = new FileOutputStream(filePath);
  118.                         ObjectOutputStream oos = new ObjectOutputStream(fos);
  119.                         oos.writeObject(object);
  120.                         System.out.println("序列化成功");
  121.                         oos.flush();
  122.                         fos.close();
  123.                         oos.close();
  124.                 } catch (FileNotFoundException e) {
  125.                         e.printStackTrace();
  126.                 } catch (IOException e) {
  127.                         e.printStackTrace();
  128.                 }
  129.         }
  130.         /**
  131.          * 反序列化对象
  132.          * @param name
  133.          * @throws Exception
  134.          */
  135.         public static Object antiSerializeMyHttpClient(String name){
  136.                 InputStream fis = HttpClientUtil.class.getResourceAsStream(name);
  137.                 ObjectInputStream ois = null;
  138.                 Object object = null;
  139.                 try {
  140.                         ois = new ObjectInputStream(fis);
  141.                         object = ois.readObject();
  142.                         fis.close();
  143.                         ois.close();
  144.                 } catch (IOException e) {
  145.                         e.printStackTrace();
  146.                         logger.error("IOException",e);
  147.                 } catch (ClassNotFoundException e) {
  148.                         e.printStackTrace();
  149.                         logger.error("ClassNotFoundException",e);
  150.                 } catch (NullPointerException e){
  151.                         e.printStackTrace();
  152.                         logger.error("NullPointerException",e);
  153.                 }
  154.                 System.out.println("反序列化成功 ");
  155.                 return object;
  156.         }
  157.         /**
  158.          * 设置Cookies策略
  159.          * @return CloseableHttpClient
  160.          */
  161.         public static CloseableHttpClient getMyHttpClient(){
  162.                 CloseableHttpClient httpClient = null;
  163.                 RequestConfig globalConfig = RequestConfig.custom()
  164.                                 .setCookieSpec(CookieSpecs.BROWSER_COMPATIBILITY)
  165.                                 .build();
  166.                 httpClient = HttpClients.custom()
  167.                                 .setDefaultRequestConfig(globalConfig)
  168.                                 .build();
  169.                 return httpClient;
  170.         }
  171.         /**
  172.          * 设置上下文
  173.          * @return HttpClientContext
  174.          */
  175.         public static HttpClientContext getMyHttpClientContext(){
  176.                 HttpClientContext context = null;
  177.                 context = HttpClientContext.create();
  178.                 Registry<CookieSpecProvider> registry = RegistryBuilder
  179.                                 .<CookieSpecProvider> create()
  180.                                 .register(CookieSpecs.BEST_MATCH, new BestMatchSpecFactory())
  181.                                 .register(CookieSpecs.BROWSER_COMPATIBILITY,
  182.                                                 new BrowserCompatSpecFactory()).build();
  183.                 context.setCookieSpecRegistry(registry);
  184.                 return context;
  185.         }
  186.         }
复制代码




3 个回复

倒序浏览
受教受教受教受教受教!
回复 使用道具 举报
大神!!!!!!!!!这个可以做黑客吗?
回复 使用道具 举报
哇塞,都写到爬虫了!!!!感觉真棒!!!我感觉爬虫挺难写的,不过,只能说,会者不难,难者不会!!!!棒棒哒!!!!
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马