- 最近做廣告聯盟的一個項目,在頁面插入廣告代碼時被廣告插件給攔截了,這里簡單的記錄下解決方案。
方案一、代碼直接寫在頁面上,不使用引入的方式。
<script src="http://xxxxxxx"> </script>
<script type="text/javascript">
//..................這里寫src="http://xxxxxxx"那段js廣告代碼
</script>
- 測試了下這種是沒有被插件攔截的(不過老板說代碼量太大了,人家站長不會復制的,所以我放棄了這種);
方案二、廣告代碼使用websocket方式返回,然后追加到頁面上(我們使用的這個方案)。
- 我在網上查到目前廣告插件對websocket攔截的不是那么嚴,也有的網站實現過了,所以自己也來試試。
- 首先來寫段websocket代碼,做服務端 webSocket.php:
<?phperror_reporting(E_ALL ^ E_NOTICE);
ob_implicit_flush();//地址與接口,即創建socket時需要服務器的IP和端口
$sk=new Sock('192.168.0.111',9090);//對創建的socket循環進行監聽,處理數據
$sk->run();/*** 模擬post進行url請求* @param string $url* @param array $post_data*/function request_post($url = '', $post_data = array()) {//url為必傳 如果該地址不需要參數就不傳if (empty($url)) {return false;}if(!empty($post_data)){$params = '';foreach ( $post_data as $k => $v ) { $params.= "$k=" . urlencode($v). "&" ;// $params.= "$k=" . $v. "&" ;}$params = substr($params,0,-1);} $ch = curl_init();//初始化curlcurl_setopt($ch, CURLOPT_URL,$url);//抓取指定網頁curl_setopt($ch, CURLOPT_HEADER, 0);//設置headercurl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);//要求結果為字符串且輸出到屏幕上//curl_setopt($ch, CURLOPT_POST, 1);//post提交方式 linux不傳參數會返回400 Bad Request 錯誤所以暫時注釋掉 ,windows不會if(!empty($post_data))curl_setopt($ch, CURLOPT_POSTFIELDS, $params);$data = curl_exec($ch);//運行curlcurl_close($ch);return $data;}//下面是sock類
class Sock{public $sockets; //socket的連接池,即client連接進來的socket標志public $users; //所有client連接進來的信息,包括socket、client名字等public $master; //socket的resource,即前期初始化socket時返回的socket資源private $sda=array(); //已接收的數據private $slen=array(); //數據總長度private $sjen=array(); //接收數據的長度private $ar=array(); //加密keyprivate $n=array();public function __construct($address, $port){//創建socket并把保存socket資源在$this->master$this->master=$this->WebSocket($address, $port);error_log("Sock __construct ");//創建socket連接池$this->sockets=array($this->master);}//對創建的socket循環進行監聽,處理數據 function run(){//死循環,直到socket斷開while(true){$changes=$this->sockets;$write=NULL;$except=NULL;/*//這個函數是同時接受多個連接的關鍵,我的理解它是為了阻塞程序繼續往下執行。socket_select ($sockets, $write = NULL, $except = NULL, NULL);$sockets可以理解為一個數組,這個數組中存放的是文件描述符。當它有變化(就是有新消息到或者有客戶端連接/斷開)時,socket_select函數才會返回,繼續往下執行。 $write是監聽是否有客戶端寫數據,傳入NULL是不關心是否有寫變化。 $except是$sockets里面要被排除的元素,傳入NULL是”監聽”全部。 最后一個參數是超時時間 如果為0:則立即結束 如果為n>1: 則最多在n秒后結束,如遇某一個連接有新動態,則提前返回 如果為null:如遇某一個連接有新動態,則返回*/socket_select($changes,$write,$except,NULL);foreach($changes as $sock){//如果有新的client連接進來,則if($sock==$this->master){//接受一個socket連接$client=socket_accept($this->master);//給新連接進來的socket一個唯一的ID$key=uniqid();$this->sockets[]=$client; //將新連接進來的socket存進連接池$this->users[$key]=array('socket'=>$client, //記錄新連接進來client的socket信息'shou'=>false //標志該socket資源沒有完成握手);//否則1.為client斷開socket連接,2.client發送信息}else{$len=0;$buffer='';//讀取該socket的信息,注意:第二個參數是引用傳參即接收數據,第三個參數是接收數據的長度do{$l=socket_recv($sock,$buf,1000,0);$len+=$l;$buffer.=$buf;}while($l==1000);//根據socket在user池里面查找相應的$k,即健ID$k=$this->search($sock);//如果接收的信息長度小于7,則該client的socket為斷開連接if($len<7){//給該client的socket進行斷開操作,并在$this->sockets和$this->users里面進行刪除$this->send2($k);continue;}//判斷該socket是否已經握手if(!$this->users[$k]['shou']){//如果沒有握手,則進行握手處理$this->woshou($k,$buffer);}else{//走到這里就是該client發送信息了,對接受到的信息進行uncode處理$buffer = $this->uncode($buffer,$k);if($buffer==false){continue;}//error_log(" received buffer " . $buffer);//如果不為空,則進行消息推送操作$this->send($k,$buffer);}}}}}//指定關閉$k對應的socketfunction close($k){//斷開相應socketsocket_close($this->users[$k]['socket']);//刪除相應的user信息unset($this->users[$k]);//重新定義sockets連接池$this->sockets=array($this->master);foreach($this->users as $v){$this->sockets[]=$v['socket'];}//輸出日志$this->e("key:$k close");}//根據sock在users里面查找相應的$kfunction search($sock){foreach ($this->users as $k=>$v){if($sock==$v['socket'])return $k;}return false;}//傳相應的IP與端口進行創建socket操作function WebSocket($address,$port){$server = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);socket_set_option($server, SOL_SOCKET, SO_REUSEADDR, 1);//1表示接受所有的數據包socket_bind($server, $address, $port);socket_listen($server);$this->e('Server Started : '.date('Y-m-d H:i:s'));$this->e('Listening on : '.$address.' port '.$port);return $server;}/** 函數說明:對client的請求進行回應,即握手操作* @$k clien的socket對應的健,即每個用戶有唯一$k并對應socket* @$buffer 接收client請求的所有信息*/function woshou($k,$buffer){//截取Sec-WebSocket-Key的值并加密,其中$key后面的一部分258EAFA5-E914-47DA-95CA-C5AB0DC85B11字符串應該是固定的$buf = substr($buffer,strpos($buffer,'Sec-WebSocket-Key:')+18);$key = trim(substr($buf,0,strpos($buf,"\r\n")));$new_key = base64_encode(sha1($key."258EAFA5-E914-47DA-95CA-C5AB0DC85B11",true));//按照協議組合信息進行返回$new_message = "HTTP/1.1 101 Switching Protocols\r\n";$new_message .= "Upgrade: websocket\r\n";$new_message .= "Sec-WebSocket-Version: 13\r\n";$new_message .= "Connection: Upgrade\r\n";$new_message .= "Sec-WebSocket-Accept: " . $new_key . "\r\n\r\n";socket_write($this->users[$k]['socket'],$new_message,strlen($new_message));//對已經握手的client做標志$this->users[$k]['shou']=true;return true;}//解碼函數function uncode($str,$key){$mask = array(); $data = ''; $msg = unpack('H*',$str);$head = substr($msg[1],0,2); if ($head == '81' && !isset($this->slen[$key])) { $len=substr($msg[1],2,2);$len=hexdec($len);//把十六進制的轉換為十進制if(substr($msg[1],2,2)=='fe'){$len=substr($msg[1],4,4);$len=hexdec($len);$msg[1]=substr($msg[1],4);}else if(substr($msg[1],2,2)=='ff'){$len=substr($msg[1],4,16);$len=hexdec($len);$msg[1]=substr($msg[1],16);}$mask[] = hexdec(substr($msg[1],4,2)); $mask[] = hexdec(substr($msg[1],6,2)); $mask[] = hexdec(substr($msg[1],8,2)); $mask[] = hexdec(substr($msg[1],10,2));$s = 12;$n=0;}else if($this->slen[$key] > 0){$len=$this->slen[$key];$mask=$this->ar[$key];$n=$this->n[$key];$s = 0;}$e = strlen($msg[1])-2;for ($i=$s; $i<= $e; $i+= 2) { $data .= chr($mask[$n%4]^hexdec(substr($msg[1],$i,2))); $n++; } $dlen=strlen($data);if($len > 255 && $len > $dlen+intval($this->sjen[$key])){$this->ar[$key]=$mask;$this->slen[$key]=$len;$this->sjen[$key]=$dlen+intval($this->sjen[$key]);$this->sda[$key]=$this->sda[$key].$data;$this->n[$key]=$n;return false;}else{unset($this->ar[$key],$this->slen[$key],$this->sjen[$key],$this->n[$key]);$data=$this->sda[$key].$data;unset($this->sda[$key]);return $data;}}//與uncode相對function code($msg){$frame = array(); $frame[0] = '81'; $len = strlen($msg);if($len < 126){$frame[1] = $len<16?'0'.dechex($len):dechex($len);}else if($len < 65025){$s=dechex($len);$frame[1]='7e'.str_repeat('0',4-strlen($s)).$s;}else{$s=dechex($len);$frame[1]='7f'.str_repeat('0',16-strlen($s)).$s;}$frame[2] = $this->ord_hex($msg); $data = implode('',$frame); return pack("H*", $data); }function ord_hex($data) { $msg = ''; $l = strlen($data); for ($i= 0; $i<$l; $i++) { $msg .= dechex(ord($data{$i})); } return $msg; }//用戶加入或client發送信息function send($k,$msg){//將查詢字符串解析到第二個參數變量中,以數組的形式保存如:parse_str("name=Bill&age=60",$arr)parse_str($msg,$g);$ar=array();$fromDate = json_decode($msg);error_log("json_decode(msg)[text] " . $fromDate->text);if($g['type']=='add'){//第一次進入添加聊天名字,把姓名保存在相應的users里面$this->users[$k]['name']=$g['ming'];$ar['type']='add';$ar['name']=$g['ming'];$key='all';}else{//發送信息行為,其中$g['key']表示面對大家還是個人,是前段傳過來的信息$ar['nrong']=$g['nr'];$key=$g['key'];}$ar["requestUrl"] = $fromDate->text;//推送信息$this->send1($k,$ar,$key);}//對新加入的client推送已經在線的clientfunction getusers(){$ar=array();foreach($this->users as $k=>$v){$ar[]=array('code'=>$k,'name'=>$v['name']);}return $ar;}//$k 發信息人的socketID $key接受人的 socketID ,根據這個socketID可以查找相應的client進行消息推送,即指定client進行發送function send1($k,$ar,$key='all'){$ar['code1']=$key;$ar['code']=$k;$ar['time']=date('m-d H:i:s');//對發送信息進行編碼處理$str = $this->code(json_encode($ar));//面對大家即所有在線者發送信息error_log("ar value " . json_encode($ar));if($key=='all'){$users=$this->users;//如果是add表示新加的clientif($ar['type']=='add'){$ar['type']='madd';$ar['users']=$this->getusers(); //取出所有在線者,用于顯示在在線用戶列表中$str1 = $this->code(json_encode($ar)); //單獨對新client進行編碼處理,數據不一樣//對新client自己單獨發送,因為有些數據是不一樣的socket_write($users[$k]['socket'],$str1,strlen($str1));//上面已經對client自己單獨發送的,后面就無需再次發送,故unsetunset($users[$k]);}//除了新client外,對其他client進行發送信息。數據量大時,就要考慮延時等問題了foreach($users as $v){socket_write($v['socket'],$str,strlen($str));}}else{//單獨對個人發送信息,即雙方聊天//socket_write($this->users[$k]['socket'],$str,strlen($str));error_log(" ar[requestUrl]" .$ar["requestUrl"]);//發起請求得到廣告$responseBody = request_post($ar["requestUrl"], array());$arrays = array();$arrays["responseBody"] = $responseBody;$str = $this->code(json_encode($arrays));//error_log("responseBody ".$str["responseBody"]);socket_write($this->users[$k]['socket'],$str,strlen($str));//socket_write($this->users[$key]['socket'],$str,strlen($str));}}//用戶退出向所用client推送信息function send2($k){$this->close($k);$ar['type']='rmove';$ar['nrong']=$k;$this->send1(false,$ar,'all');}//記錄日志function e($str){//$path=dirname(__FILE__).'/log.txt';$str=$str."\n";//error_log($str,3,$path);//編碼處理echo iconv('utf-8','gbk//IGNORE',$str);}}echo "1";
?>
這代碼是抄的,然后改了點東西。
//這段代碼需要引入jQuery<script type="text/javascript">//ws連接var websocket;/****zhouzhongqing* 2018年6月1日14:50:02* 發送消息* */function sendHeartMessage(message) {console.log("發送消息");var data = {};data["to"] = 0;data["text"] = message;websocket.send(JSON.stringify(data));}/*** zhouzhongqing* 2018年10月23日15:58:09* 創建websocket連接* **/function createWebSocket() {//webSocket地址var wsLocation = "ws://192.168.0.111:9090";try {// 指定websocket路徑if ('WebSocket' in window) {websocket = new WebSocket(wsLocation);} else if ('MozWebSocket' in window) {websocket = new MozWebSocket(wsLocation);} else {websocket = new SockJS(wsLocation);}initEventHandle();}catch (e){console.log("createWebSocket error " + e);}}function initEventHandle(){websocket.onopen = function (event) {console.log("open start");//這是把廣告地址發給websocketsendHeartMessage("http://zyiis.xxxx.com/s.php?id=12");console.log("open end");};websocket.onclose = function () {console.log("ws 關閉 !" + new Date().toUTCString());};websocket.onerror = function () {console.log(" ws連接錯誤!" + new Date().toUTCString());};websocket.onmessage = function (event) {var data = JSON.parse(event.data);//console.log(data);var responseBody = data.responseBody;//返回的js追加到body標簽里$("body").append("<script>"+responseBody+"<\/script>");websocket.close();};}$(document).ready(function () {createWebSocket();});</script>
- 基本思路就是這樣實現的,下面一步就是封裝代碼。
- 封裝web_socket.js
//ws連接
var websocket;//任務個數
var taskCount = 0;//判斷是否存在websocket連接
var isExistenceWs = false;/**** 有可能有多個廣告,所有后面的稍等下再發送* */
function createWebSocketTask(message) {taskCount++;if(isExistenceWs){setTimeout("sendHeartMessage('"+message+"')",taskCount + 1000);}else {createWebSocket(message );}
}setInterval("closeWebSocketConnection()",3000);/**** 關閉socket連接* */
function closeWebSocketConnection() {if(isExistenceWs && taskCount == 0){setTimeout(" websocket.close()",3000);}
}/****zhouzhongqing* 2018年6月1日14:50:02* 發送 消息* */
function sendHeartMessage(message) {console.log("發送消息");var data = {};data["to"] = 0;data["text"] = message;websocket.send(JSON.stringify(data));
}/*** zhouzhongqing* 2018年10月23日15:58:09* 創建websocket連接* **/
function createWebSocket(message) {//webSocket地址var wsLocation = "ws://192.168.0.111:9090";try {// 指定websocket路徑if ('WebSocket' in window) {websocket = new WebSocket(wsLocation);} else if ('MozWebSocket' in window) {websocket = new MozWebSocket(wsLocation);} else {websocket = new SockJS(wsLocation);}initEventHandle(message);isExistenceWs = true;}catch (e){console.log("createWebSocket error " + e);isExistenceWs = false;}
}function initEventHandle(message){websocket.onopen = function (event) {console.log("open start");sendHeartMessage(message);console.log("open end");};websocket.onclose = function () {console.log("ws 關閉 !" + new Date().toUTCString());};websocket.onerror = function () {console.log(" ws連接錯誤!" + new Date().toUTCString());};websocket.onmessage = function (event) {//收到消息則減-taskCount--;var data = JSON.parse(event.data);//console.log(data);var responseBody = data.responseBody;//考慮到有的網站網頁有可能不支持jQuery所以用這種方式追加var newScript = document.createElement("script");newScript.setAttribute("type","text/javascript");newScript.innerHTML = responseBody;document.getElementsByTagName("body")[0].appendChild(newScript);//$("body").append("<script>"+responseBody+"<\/script>");//websocket.close();};
}
<!--注意這個web_socket.js一個頁面只引入一次-->
<script src="http://xxxxxxx/js/web_socket.js"></script><script type="text/javascript">createWebSocketTask("http://zyiis.xxxxx.com/s.php?id=12");</script><script type="text/javascript">createWebSocketTask("http://zyiis.xxxxx.com/s.php?id=11");</script>
總結
以上是生活随笔為你收集整理的绕过广告拦截插件的解决方案的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。