1. 程式人生 > 實用技巧 >爬蟲-反爬與反反爬(12)

爬蟲-反爬與反反爬(12)

為什麼用redis

解決伺服器CPU記憶體壓力

方案一、存在Cookie中

此種方案需要將Session資料以Cookie的形式存在客戶端,不安全,網路負擔效率低

方案二、存在檔案伺服器或者是資料庫裡

此種方案會導致大量的IO操作,效率低.

方案三、Session複製

此種方案會導致每個伺服器之間必須將Session廣播到叢集內的每個節點,Session資料會冗餘,節點越多浪費越大,存在廣播風暴問題.

方案四、存在Redis中

  1. 目前來看,此種方案是最好的。將Session資料存在記憶體中,每臺伺服器都從記憶體中讀取資料,速度快,結構還相對簡單

  2. 將活躍的資料快取到Redis中,客戶端的請求先打到快取中來獲取對應的資料,如果能獲取到,直接返回,不需要從MySQL中讀取。如果快取中沒有,再從MySQL資料庫中讀取資料,將讀取的資料返回並存一份到Redis中,方便下次讀取

  3. 適用於對資料高併發的讀寫、海量資料的讀寫、對資料高可擴充套件性的

redis簡介及安裝

簡介

Redis是一個開源的key-value儲存系統。和Memcached類似,它支援儲存的value型別相對更多,包括string(字串)、list(連結串列)、set(集合)、zset(sorted set --有序集合)和hash(雜湊型別)。這些資料型別都支援push/pop、add/remove及取交集並集和差集及更豐富的操作,而且這些操作都是原子性的。在此基礎上,Redis支援各種不同方式的排序。

安裝

https://www.cnblogs.com/marvinn/p/11081106.html

redis的五大資料型別

基本操作

1\

key

  • String是Redis最基本的型別,你可以理解成與Memcached一模一樣的型別,一個key對應一個value

  • String型別是二進位制安全的。意味著Redis的string可以包含任何資料。比如jpg圖片或者序列化的物件 。

  • String型別是Redis最基本的資料型別,一個Redis中字串value最多可以是512M

常用操作
2\

list

  • 單鍵多值

  • Redis 列表是簡單的字串列表,按照插入順序排序。你可以新增一個元素導列表的頭部(左邊)或者尾部(右邊)。

  • 它的底層實際是個雙向連結串列,對兩端的操作效能很高,通過索引下標的操作中間的節點效能會較差
    3
    4\

Set

  • Redis set對外提供的功能與list類似是一個列表的功能,特殊之處在於set是可以自動排重的,當你需要儲存一個列表資料,又不希望出現重複資料時,set是一個很好的選擇,並且set提供了判斷某個成員是否在一個set集合內的重要介面,這個也是list所不能提供的
  • Redis的Set是string型別的無序集合。它底層其實是一個value為null的hash表,所以新增,刪除,查詢的複雜度都是O(1)
    5\

Hash

現有一個JavaBean物件,在Redis中如何存?
6
7\

Zset

  • Redis有序集合zset與普通集合set非常相似,是一個沒有重複元素的字串集合。不同之處是有序集合的每個成員都關聯了一個評分(score) ,這個評分(score)被用來按照從最低分到最高分的方式排序集合中的成員。集合的成員是唯一的,但是評分可以是重複了

  • 因為元素是有序的, 所以你也可以很快的根據評分(score)或者次序(position)來獲取一個範圍的元素。訪問有序集合的中間元素也是非常快的,因此你能夠使用有序集合作為一個沒有重複成員的智慧列表。
    \8

redis的相關配置

https://blog.csdn.net/P_ning/article/details/106241421

redis的Java客戶端

  1. 匯入jar包
    Commons-pool-1.6.jar
    Jedis-2.1.0.jar

  2. 注意事項

  • 禁用Linux的防火牆:Linux(CentOS7)裡執行命令 : systemctl stop firewalld.service

  • redis.conf中註釋掉bind 127.0.0.1 ,然後 protect-mode no

  1. 測試是否聯通
    \9
package com.atguigu.test;



import redis.clients.jedis.Jedis;



public class Test {



     public static void main(String[] args) {

          

          Jedis jedis = new Jedis("192.168.16.128",6379);

          String result = jedis.ping();

          System.out.println(result);

          jedis.set("a", "a");

          String a = jedis.get("a");

          System.out.println(a);

          jedis.close();

     }

}


  1. 完成一個手機驗證碼功能
  • 匯入jar包
    \10

  • index.jsp

1、index.jsp中
插入一些檔案
<script  src="/Verify_code/static/jquery/jquery-3.1.0.js" 
></script>

<link href="/Verify_code/static/bs/css/bootstrap.min.css" 
rel="stylesheet" />

<script  src="/Verify_code/static/bs/js/bootstrap.min.js"   
></script>

主體中
<div class="container">//1、boostrap中的樣式,可以用來控制是否在12個格子中

          <div class="row">//2、與container配合減少一些空白

              <div id="alertdiv" class="col-md-12">//一行12個

                    <form class="navbar-form navbar-left"><u>role</u>="search" id="codeform">

                     <div class="form-group">

                       <input type="text" class="form-control" <u>placeholder</u>="填寫手機號" name="phone_no">//加入form-control會使用boostrap自帶的input框

                       <button type="button" class="btn btn-default" id="sendCode">傳送驗證碼</button>//name可重複、value不可重複

                     <br><font id="countdown" color="red" ></font> <br>

                     <input type="text" class="form-control" <u>placeholder</u>="填寫驗證碼" name="verify_code">

                     <button type="button" class="btn btn-default" id="verifyCode">確定</button>

                     <font id="result" color="green" ></font><font id="error" color="red" ></font>

                     </div>

                   </form>

    </div>

   </div>

  </div>



1、https://blog.csdn.net/weixin_42097173/article/details/80381896</u>

2、https://www.cnblogs.com/olivertian/p/11119784.html</u>

3、https://blog.csdn.net/wem603947175/article/details/83004364</u>

javascript中

var t=120;//設定倒計時的時間 
var interval;

function refer(){  
    $("#countdown").text("請於"+t+"秒內填寫驗證碼 "); // 顯示倒計時 
    t--; // 計數器遞減 
    if(t<=0){
    	clearInterval(interval);
    	$("#countdown").text("驗證碼已失效,請重新發送! ");
    }
} 

$(function(){//整個頁面載入完成後
	$("#sendCode").click( function () {//繫結傳送驗證碼按鈕
		   $.post("/Verify_code/CodeSenderServlet",$("#codeform").serialize(),function(data){//1、-跳轉訪問路徑、-form表單中資訊序列化資訊、反應(傳回來的資訊)
	    	 	if(data=="true"){//2、定時器倒計時
	    		 	t=120;
	    		 	clearInterval(interval);
	    		 	interval= setInterval("refer()",1000);//啟動1秒定時  
	   		 }else if (data=="limit"){
	   			clearInterval(interval);
	   			$("#countdown").text("單日傳送超過次數! ")
	   		 }
		  });   
    });
	
	$("#verifyCode").click( function () {//繫結驗證確定按鈕
		   $.post("/Verify_code/CodeVerifyServlet",$("#codeform").serialize(),function(data){
	    	 	if(data=="true"){
	    		 	$("#result").attr("color","green");//3、設定或返回備選元素的屬性或值
	    		 	$("#result").text("驗證成功");
	    		 	clearInterval(interval);
	    		 	$("#countdown").text("");
	   		}else{
	    		 	$("#result").attr("color","red");
	    		 	$("#result").text("驗證失敗");
	   		}
		  });   
    });
	
	
});

1、<u>https://www.cnblogs.com/webapi/p/10550185.html</u>

2、<u>https://blog.csdn.net/YDesire/article/details/81124331</u>

3、<u>https://www.cnblogs.com/blmlove/p/12701722.html</u>

2、CodeSenderServlet

@WebServlet("/CodeSenderServlet")

public class CodeSenderServlet extends HttpServlet {

      private static final long serialVersionUID = 1L;

       

    /**

     * @see HttpServlet#HttpServlet()

     */

      public CodeSenderServlet() {

        super();

        // TODO Auto-generated constructor stub

      }

      private String getCode(int length) {

          String code = "";

          Random random = new Random();

          for(int i = 0; i < length; i++) {

              int rand = random.nextInt(10);//1、生成隨機數字

              code += rand;

          }

          return code;
      }

     /**

      * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)

      */

     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            //獲取手機號
            String phone_no = request.getParameter("phone_no");
            //獲取驗證碼
             String code = getCode(6);
             //拼接key
             String codeKey = "Verify_code:" + phone_no + ":code";//Verify_code:12345:code
            String countKey = "Verify_code:" + phone_no + ":count";
             Jedis jedis = new Jedis("192.168.16.128", 6379);
            //判斷髮送驗證碼的次數
            String count = jedis.get(countKey);
            if(count == null) {
            //代表第一次
            jedis.setex(countKey, 24*60*60, "1");

          }else if(Integer.parseInt(count) <= 2) {

              jedis.incr(countKey);

          }else if(Integer.parseInt(count) > 2) {

              response.getWriter().print("limit");

              jedis.close();

              return ;

          }

          

          //向<u>redis</u>中進行儲存,以手機號為鍵,以驗證碼為值

          jedis.setex(codeKey, 120, code);

          jedis.close();

          response.getWriter().print(true);

          

     }

}



1、https://www.cnblogs.com/hm1990hpu/p/8875928.html</u>





3、CodeVerifyServlet

@WebServlet("/CodeVerifyServlet")

public class CodeVerifyServlet extends HttpServlet {

     private static final long serialVersionUID = 1L;

       

    /**

     * @see HttpServlet#HttpServlet()

     */

    public CodeVerifyServlet() {

        super();

        // TODO Auto-generated constructor stub

    }

     /**

      * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)

      */
       protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

          //獲取驗證碼和手機號

          String phone_no = request.getParameter("phone_no");

          String verify_code = request.getParameter("verify_code");

          //拼接key

          String codeKey = "Verify_code:" + phone_no + ":code";

          //從<u>redis</u>中獲取手機號所對應的驗證碼

          Jedis jedis = new Jedis("192.168.16.128", 6379);

          String code = jedis.get(codeKey);

          if(code.equals(verify_code)) {

              response.getWriter().print(true);

          }

          jedis.close();

          

     }

}