網站自動刷帖,刷贊,刷評論等網絡推廣方式的基本實現

上週寫了一個騰訊旗下的一個小說網站的自動回帖程序:javascript

  具體怎麼實現的呢?      html

  其實它就是一個,找到評論接口,而後利用程序模擬HTTP請求的過程。再結合爬蟲的相關技術具體實現。 大概分爲這麼幾步:java

  第一步:先找到評論接口:sql

      使用chrome或者火狐瀏覽器,或者專業點的fiddler對評論過程抓包chrome

獲得具體的請求爲:數據庫

POST http://chuangshi.qq.com/bookcomment/replychapterv2 HTTP/1.1
Host: chuangshi.qq.com Connection: keep-alive Content-Length: 102 Accept: application/json, text/javascript, */*; q=0.01 Origin: http://chuangshi.qq.com X-Requested-With: XMLHttpRequest User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.93 Safari/537.36 Content-Type: application/x-www-form-urlencoded; charset=UTF-8 Referer: http://chuangshi.qq.com/bk/xh/AGkEMF1hVjEAOlRlATYBZg-r-69.html Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.8 Cookie: xxxxxx bid=14160172&uuid=69&content=%E4%B9%A6%E5%86%99%E7%9A%84%E4%B8%8D%E9%94%99&_token=czo4OiJJRm9TQ0RnbSI7

 

第二步:模擬請求,它的邏輯是:首先經過頻道頁(玄幻·奇幻 武俠·仙俠 都市·職場 歷史·軍事 遊戲·體育 科幻·靈異 二次元)抓取文章信息。json

如玄幻小說的頻道頁爲:http://chuangshi.qq.com/bk/huan/ 瀏覽器

而後提取文章標題、文章ID,章節ID等數據服務器

 

注入cookie等參數,模擬請求核心代碼:cookie

 1     public class AutoCommentService : AutoComment.service.IAutoCommentService  2  {  3         public delegate void CommentHandler(Article article,Comment comment);  4         public event CommentHandler Commented;  5         bool stop;  6         /// <summary>
 7         /// 是否中止服務  8         /// </summary>
 9         public bool Stop  10  {  11             get { return stop; }  12             set { stop = value; }  13  }  14 
 15         /// <summary>
 16         /// 初始化數據庫  17         /// </summary>
 18         public void InitDatabase()  19  {  20             SQLiteConnection.CreateFile(AppSetting.DB_FILE);//建立SQL文件 
 21             SQLiteConnection con = new SQLiteConnection();//創建鏈接 
 22             SQLiteConnectionStringBuilder sqlstr = new SQLiteConnectionStringBuilder();//構建鏈接字符串 
 23             sqlstr.DataSource = AppSetting.DB_FILE;  24             con.ConnectionString = sqlstr.ToString();  25             con.Open();//打開鏈接 
 26             string cmdStr = @"create table comment (  27  id integer primary key autoincrement,  28  content varchar(500),  29  articleId varchar(50),  30  articleName varchar(50),  31  url varchar(50)  32  )";  33             SQLiteCommand cmd = new SQLiteCommand(cmdStr, con);  34  cmd.ExecuteNonQuery();  35             con.Close();//關閉鏈接 
 36  }  37 
 38         /// <summary>
 39         /// 運行自動評論  40         /// </summary>
 41         public void RunAutoComment()  42  {  43             this.Stop = false;  44             List<string> articleTypes = AppSetting.articleType;  45             while (!Stop)  46  {  47                 foreach (var type in articleTypes)  48  {  49                     string url = AppSetting.WEB_HOME_URL + "/bk/" + type;  50                     var list = GetArticles(url);  51                     foreach (var article in list)  52  {  53                         AddComment(article, new Comment(AppSetting.commentContent));  54                         System.Threading.Thread.Sleep(AppSetting.waitSecond * 1000);  55                         if (Stop)  56                             break;  57  }  58                     if (Stop)  59                         break;  60  }  61  }  62  }  63 
 64         public void StopAutoComment()  65  {  66             this.Stop = true;  67  }  68 
 69         /// <summary>
 70         /// 獲取頻道頁下全部最新發布的文章  71         /// </summary>
 72         /// <param name="typeUrl">玄幻,軍事等頻道頁URL</param>
 73         /// <returns></returns>
 74         public List<Article> GetArticles(string typeUrl)  75  {  76             var html = HttpHelper.GetString(typeUrl);  77             html = Regex.Match(html, "<div class=\"update_list\">.*?(?=</div>)</div>").Value;  78             var arcticleUrlMatch = "<a class='gray2' title='(?<title>[^']*)' href='(?<url>[^']*)'>";  79             MatchCollection matches = Regex.Matches(html, arcticleUrlMatch);  80             List<Article> articles = new List<Article>();  81             if (matches != null)  82  {  83                 foreach (Match match in matches)  84  {  85                     if (match != null)  86  {  87                         string url = match.Groups["url"].Value;  88                         string subTitle = match.Groups["title"].Value;  89                         string title = match.Groups["title"].Value;  90                         if (string.IsNullOrEmpty(url) == false)  91  {  92                             Article article = new Article(title,subTitle,url);  93  articles.Add(article);  94  }  95  }  96  }  97  }  98             return articles;  99  } 100         
101         /// <summary>
102         /// 提交評論 103         /// </summary>
104         /// <param name="article"></param>
105         /// <param name="comment"></param>
106         /// <returns></returns>
107         public bool AddComment(Article article, Comment comment) 108  { 109             bool successed = false; 110             var html = HttpHelper.GetString(article.Url); 111             article.BID = Regex.Match(html, "var bid = \"(?<bid>[\\d]+)\"").Groups["bid"].Value; 112             article.UUID = Regex.Match(html, "uuid = \"(?<uuid>[\\d]+)\";").Groups["uuid"].Value; 113             article.Title = Regex.Match(html, "<title>(?<title>[^<]+)</title>").Groups["title"].Value.Replace("_創世中文", ""); 114             dal.CommentDal dal = new dal.CommentDal(); 115             if (dal.CanComment(article)) 116  { 117                 HttpRequestParam param = new HttpRequestParam(); 118                 string url = "http://chuangshi.qq.com/bookcomment/replychapterv2"; 119                 param.Cookie = AppSetting.Cookie; 120                 param.Method = "post"; 121                 string token = AppSetting.Token; 122                 string body = string.Format("bid={0}&uuid={1}&content={2}&_token={3}", article.BID, article.UUID, HttpHelper.UrlEncode(comment.Content), token); 123                 param.Body = body; 124                 var result = HttpHelper.GetHtml(url, param); 125                 comment.Result = result.UnicodeToChinese(); 126                 successed = result.Contains("status\":true"); 127                 if (successed) 128  { 129                     comment.Successed = 1; 130  dal.AddComment(comment, article); 131  } 132                 else
133  { 134                     comment.Successed = 0; 135  } 136 
137                 if (Commented != null) 138  { 139  Commented(article, comment); 140  } 141  } 142             return successed; 143  } 144 
145     }

  其餘的刷贊、和刷收藏方法都相似,都是找到接口,而後再模擬請求。

  但大部分網站的這種相似登陸,評論,刷贊等接口都是有必定的反機器人策略的。

  好比常見的策略:驗證碼、IP限制、帳號限制、接口調用頻次限制。

     但作數據挖掘,作爬蟲和這種自動刷評論和系統方老是不斷博弈。一方攻,一方守,也都有應對的策略,那就簡單談下攻守方式吧。

 

1、驗證碼:

驗證碼(CAPTCHA)是「Completely Automated Public Turing test to tell Computers and Humans Apart」(全自動區分計算機和人類的圖靈測試)的縮寫,是一種區分用戶是計算機仍是人的公共全自動程序
防止惡意破解密碼、刷票、論壇灌水、刷頁。

固然,種類繁多啊

 

 

 

簡單驗證碼自動識別:

灰化》二值化》去噪》分割 》字符識別

第一步:灰化

就是把圖片變成黑白色

第二步:二值化

經過指定篩選的閾值,將特定灰度的像素點轉化成黑白兩色。

中值二值化:中值127爲閾值

均值二值化 :圖片全部像素的平均值
直方圖二值化:使用直方圖方法來尋找二值化閾值
維納濾波二值化:最小均方偏差

第三步:去噪

刪除掉干擾的冗餘像素點,即爲去噪

 

第四步:分割

將驗證碼根據邊界切割成單個字符

 

第五步:字符識別

根據匹配字符庫中的樣本,取類似度最高的字符來實現識別。

 

相關開源的ORC字符識別模塊可參考google開源的

 

2、IP限制

這個的話,使用多臺服務器、或者使用IP代理解決。

 

3、帳號限制

那就多個帳號唄,萬能的淘寶,啥都有賣。兩元一個的QQ號,幾十塊錢一大把的郵箱都是有的。有了帳號後再使用代碼實現自動登陸,自動切換帳號。

其實自動切換帳號,這個挺折騰的,尤爲是大公司的網站。腳本寫的很是複雜,你要想實現自動登陸,你就必須先得看懂它的代碼,提取它的登陸邏輯就行封裝。好比騰訊的WEB自動登陸密碼加密的方法:

它會hash,MD5,位移,編碼來來回回加密十來次,封裝起來仍是有點費勁的。

function getEncryption(password, salt, vcode, isMd5) {
        vcode = vcode || '';
        password = password || '';
        var md5Pwd = isMd5 ? password : md5(password),
        h1 = hexchar2bin(md5Pwd),
        s2 = md5(h1 + salt),
        rsaH1 = $pt.RSA.rsa_encrypt(h1),
        rsaH1Len = (rsaH1.length / 2).toString(16),
        hexVcode = TEA.strToBytes(vcode.toUpperCase(), true),
        vcodeLen = Number(hexVcode.length / 2).toString(16);
        while (vcodeLen.length < 4) {
            vcodeLen = '0' + vcodeLen
        }
        while (rsaH1Len.length < 4) {
            rsaH1Len = '0' + rsaH1Len
        }
        TEA.initkey(s2);
        var saltPwd = TEA.enAsBase64(rsaH1Len + rsaH1 + TEA.strToBytes(salt) + vcodeLen + hexVcode);
        TEA.initkey('');
        setTimeout(function () {
            __monitor(488358, 1)
        }, 0);
        return saltPwd.replace(/[\/\+=]/g, function (a) {
            return {
                '/': '-',
                '+': '*',
                '=': '_'
            }
            [
                a
            ]
        })
    }

  

4、接口次數限制

下降接口調用速度再配合多帳號能夠解決問題。

 

那麼本身的網站怎麼防止爬蟲和惡意接口調用呢?

驗證碼:使用更復雜的驗證碼,字母重疊的,連到一塊的。

IP限制:這個算了,限制沒啥用。

帳號限制:一旦監測到機器人行爲,根據狀況封號,先封1小時、還敢調用封它一天,還敢?那永久封號,這招很狠的。

核心接口使用HTTPS協議

 

固然我遇到過的最牛逼的反爬系統則是阿里的釘釘了,聽說是採用阿里最牛的加密技術作的。好奇的朋友能夠去抓下包看看,真的是啥線索都沒有。

相關文章
相關標籤/搜索