ホームページ  >  記事  >  バックエンド開発  >  ロボットカールによるページのクロールを防ぐ良い方法はありますか?

ロボットカールによるページのクロールを防ぐ良い方法はありますか?

WBOY
WBOYオリジナル
2016-06-23 14:05:012909ブラウズ

私は過去に他の人のページのコンテンツをクロールすることについて研究していました。経験に基づいて、ページがクロールされないようにする良い方法はありますか?

私は過去に、クロールが難しい 2 つの状況に遭遇しました (プログラムの自動バッチ取得を指します)
1 つ目: 数分ごとに有効期限が切れる複雑な Cookie 検証を生成する場合。 Cookie を CURLOPT_HEADER に手動で貼り付ける必要があります。

2 番目のタイプ: IP が一定期間内に頻繁にクロールされる場合 (GOOGLE などの検索結果ページを指します)、検証コードが時々ポップアップし、手動による検証が必要になります。

その他、コンテンツを js に書き込んでページに出力するなど、クラックしてバッチで取得することができます。

親愛なる先輩方、皆さんの意見を聞きたいのですが、皆で議論して解読できるようにコードを提示するのが最善です。


ディスカッションへの返信 (解決策)

写真....

reboot.txt のようなファイルを Web サイトに配置して、検索エンジン クロール ページを設定できることはわかっています。

誰かが素晴らしい回答をしてくれることを楽しみにしています、そして私はそこから学びます。

curl もブラウザとまったく同じように実行できるようです。ドメイン名へのリンクを含むジャンク コードを大量に追加したり、Dream Weaver のアンチコレクションのように不定期に追加したりするなど、他のアイデアも使用できます。彼があなたのコンテンツを正規表現で一致させることは困難です。たとえ一致がほぼ同じであっても、彼がそれらを収集する気があるのなら、へえ、無料の外部リンクです。リンクも利用できます。

ブラウザが認識できる限り、curl はそれをキャッチできます
CURLOPT_COOKIESESSION、CURLOPT_COOKIE、CURLOPT_COOKIEFILE、CURLOPT_COOKIEJAR を柔軟に使用して Cookie を処理できます。「毎回 CURLOPT_HEADER に Cookie を手動で貼り付ける」必要はありません
JS コード検証を使用できます。そして、curlアクションを防ぐためにジャンプしますが、Linuxでjsコードを実行するためのphp拡張機能のダウンロードはすでに存在します

唯一の実現可能な解決策は、アクセス頻度を検出することです
現在、多くのWebサイトがこの方法を使用していますが、ポップアップダイアログボックスではありません。代わりに、無効なページ コンテンツが出力され、無駄な作業になります

唯一の実現可能な解決策は、訪問頻度を検出することです
現在、多くの Web サイトがこの方法を使用していますが、ダイアログ ボックスは表示されません。代わりに、無効なページ コンテンツが出力され、無駄な作業になります

グレート マスター バンブー、私の弟が学ぶためのサンプル コードはありますか?ありがとう。

私も学びにここに来ています

ロボットがウェブページを巡回するのを防ぐことは不可能なはずです 唯一の実現可能な解決策は、アクセス頻度を検出することです~~~

最も経済的な方法でアクセス頻度を検出する方法。 ?一時データテーブル?セッションを作成しますか?

数年ほど前に航空会社のウェブサイトに出会いましたが、そのアプローチは私を困惑させました。

もう一度思い出したので、みんなで一緒に話し合うために投稿しました。
もちろん、すべての詳細を完全に理解することはできませんが、当時の調査に基づいていくつかの推測をしただけです。

最初にページが読み込まれた後、いくつかの基本的な HTML を読み込み、js は ajax リクエストのキーデータを ajax 経由で返します。返されるデータは json であり、ページ js を通じて json を解析してページ上に描画します。問題の鍵は、ajax リクエストを行うときに、データを正しく取得するために特別なパラメーターを指定する必要があることです。また、このパラメータを通じてデータを取得した後は、このパラメータは無効になります。このパラメータには特定のアルゴリズムがあり、読み込み中にこの動的ページによって生成される必要があります。


メソッドは大まかに次のとおりです:
1 ページ a.php をリクエストします。ブラウザに返す必要がある HTML を生成する際、a.php ページは特定のアルゴリズムに従って検証文字列 abc123 を生成します (およびリクエストごとに生成される文字列は異なります) をデータベースまたはサードパーティの記憶媒体に書き込みます。

2 a.php の HTML がブラウザに返された後、ajax リクエストを必要とする URL が結合され、生成された検証文字列 abc123 である最後のパラメータが追加されます。次に、ajax リクエストを実行します。 Ajax によって要求されたページを受信し、データベースにクエリを実行して、abc123 が存在するかどうかを確認します。存在する場合は、正しい json データを返します。存在しない場合は、返さないか、例外を返します。


収集パーティーのためにこれを行います。その a.php を取得すると、ajax が自動的に 1 回実行されます。このとき、キャプチャしたページのa.phpにはajaxリクエストで取得したデータが表示されていますが、ソースコードには存在していないことがわかります。そして、a.php の HTML ソース コードで ajax URL を使用して再度リクエストしようとすると、生成された abc123 検証文字列の有効期限が切れていることがわかります。


ajax 検証文字列の問題を無視して、実験をしてみましょう:
1.php (つまり、クローラーのスクリプト)

<?phpfunction request( $url, $header = '', $postfields = '' ){		$ch = curl_init();		$options = array(			CURLOPT_URL => $url,			CURLOPT_HEADER => 0,			//CURLOPT_HTTPHEADER => $header,			CURLOPT_NOBODY => 0,			CURLOPT_PORT => 80,			CURLOPT_POST => 1,			CURLOPT_POSTFIELDS => $postfields,			CURLOPT_RETURNTRANSFER => 1,			CURLOPT_FOLLOWLOCATION => 1,			//CURLOPT_COOKIEJAR => $cookie_jar,			//CURLOPT_COOKIEFILE => $cookie_jar,			//CURLOPT_SSL_VERIFYPEER => 0,			//CURLOPT_SSL_VERIFYHOST => 1,			CURLOPT_TIMEOUT => 30		);		curl_setopt_array($ch, $options);		$code = curl_exec($ch);		curl_close($ch);		return $code;}$url = 'http://www.angryfrog.com/2.php';echo request($url);



2.php (クローラーのページ)
<script src="./js/jquery-1.7.1.min.js"></script><script>	$(document).ready(function(){		$.get('http://www.angryfrog.com/3.php', '', function(data){ d=$.parseJSON(data);$('#tmp').html(d.node1);});	});</script><a id="tmp"></a>



3. php (キャプチャされた側の ajax インターフェイス)
<?php$a = array(	'node1' => 'data1',	'node2' => 'data2');echo json_encode($a);



1.php を実行すると、ページに次の結果が表示されました:


しかし、1.php のソース コードを確認すると、次のことがわかりました:


, 1.phpページのどこにdata1が表示されているのでしょうか?

1.php を変更し、クロールされた結果を一時ファイルに書き込みます。つまり、
echo request($url); を
file_put_contents('./tmp', request($url);); に変更します

1.php を再度実行した後、ファイル tmp を確認します。結果は同じで、data1 が取得できません



上記の例は、相手のスクリプトページを一度リクエストしただけでは、ブラウザ上では欲しいデータが表示されることを証明しています。ソースコード内で。そのデータは 2 番目の ajax リクエストを通じて取得されるためです。

それでは、その ajax をシミュレートして、別のリクエストを作成してみましょう?

私の最初の考えによれば、Ajax リクエスト アドレスの 1 つのパラメーターが検証文字列である場合、2.php のソース コードを見ると、Ajax シミュレーション リクエストの URL は
http://www.angryfrog.com になります。 /3.php ?vcode=123abc

ajax をシミュレートして別のリクエストを行う場合、3.php はデータベースにアクセスして 123abc の検証文字列をチェックし、123abc の有効期限が切れている (データベースに存在しない) ことを検出します。なぜなら、最初のリクエストが成功した後、3.php がそれをデータベースから削除するからです。したがって、有効期限が切れたので、3.php は正しいデータを返さないことを選択できます。


これでは矛盾が生じます。2.php をリクエストしないと、検証文字列を生成できません。しかし、2.php をリクエストすると、自動的に 3.php がリクエストされ、生成された検証文字列が破棄されてしまいます。

だから、その時はうまくいかなかったし、この状況を解決する方法がわかりません。誰か良いアイデアはありますか? 2.php を正常にリクエストして検証文字列を生成させることはできますが、生成された文字列が破棄されないように自動的に ajax リクエストを行うことはできず、取得後にそれを使用して ajax リクエストを行うことはできますか?

申し訳ありませんが、私のアイデアにバグがあることに突然気づきました。

同じドメインのみをテストしました。実際の状況では、ajax リクエストは自動的に正常に実行されません。クロスドメインだから。

自分のサーバーから相手のページをリクエストすると、それらのajaxを含むhtmlとjsが得られます。ブラウザに戻った後。このとき、ドメインは独自のサーバーになり、ページ上の ajax はドメインを越えて相手の ajax インターフェイスを正常にリクエストできません。生成された検証コードが自動的に破棄される状況については説明する必要はありません。この方法はうまくいかないようです。

改めてじっくり思い出してみました(昔すぎました)。その時、相手のページでajaxを見たところ、怪しいパラメータが含まれていましたが、リクエストごとに異なっていました(そしてキャッシュを防ぐために使用されていないことは確認されました)が、作成しようとしたときにこのパラメータを指定したリクエスト。この URL を使用すると、結果は得られません。ただし、そのページを通じてこのアドレスを要求すると、データが返されることがあります。理由はわかりませんが、リファラーとユーザーエージェントもシミュレートしました。

これは可能ですか? a.php ページが検証文字列を生成してデータベースに書き込んだ後、この文字列は短期間で無効になります。たとえば、1秒です。これは、redis または memcached を使用して簡単に実行でき、キーに有効期限を与えます。

スクリプトを通じて a.php を取得すると、そのソース コードを分析し、Ajax リクエストのアドレスを見つけてリクエストを行う必要があります。このプロセスには 1 秒以上かかる場合があります。検証文字列の有効期限が切れているため、ajax インターフェイスはデータを正常に返しません。そのページに通常どおりアクセスすると、ページは ajax をより高速に実行し、1 秒を超えないため、データを正常に取得できます。


明日時間があれば、完全なコードを書き留めて試してみます。

php_v8js の機能は、php で js コードを実行することです
そして、上記の説明では、php を使用して js の動作をシミュレートしています

これは明らかに同じことではありません

実際、この質問は、どちらの側が努力を惜しまないのかについてです
と守る側 費用は惜しまず、捕まえる側は費用対効果を考えて断念
捕まえる側は費用を惜しまず、守る側はユーザーの損失を考えて断念

あなたはそれらを見ていませんまだ頭がおかしい人たち

一般的に、ウェブ時代では、捕まった側のコストははるかに低くなります

劉明、様子見

比較的複雑な認証マークを生成するために暗号化アルゴリズムが使用されています これだけで。マークを付けると、アクセスできるようになります。同時に、入り口に認証コードが表示されます。
そして、確認コードの認識はユーザーエクスペリエンスを低下させます。
複雑な認証フラグを使用するだけで、生成されたアルゴリズムが解読された後でも、バッチ リクエストを開始できます。
一般に、人間がブラウザ経由でアクセスできるのは http リクエストを送信することだけであり、マシンでも同じことができますが、マシンはまずデータを収集し、アクセス プロセスを明確に分析する必要があります。

@ShadowSniper、非常に良い例です。考え方が広がります。
これが頭に浮かびます:
ブラウザがページ A にアクセスすると、ランダム コードが生成され、それが ajax パラメータとしてページ B に渡されます。ページ B は、ランダム コードの正当性を検証してから、データをページ A に返す必要があります。 。
したがって、ページ A を直接カールしても、何も得られません。
ページ B を直接カールします (ajax ページの場合)。正当なランダム コードがないため、それでも何も得られません。

@ShadowSniper、非常に良い例です。考え方が広がります。
これが頭に浮かびます:
ブラウザがページ A にアクセスすると、ランダム コードが生成され、それが ajax パラメータとしてページ B に渡されます。ページ B は、ランダム コードの正当性を検証してから、データをページ A に返す必要があります。 。
したがって、ページ A を直接カールしても、何も得られません。
ページ B を直接カールします (ajax ページの場合)。正当なランダム コードがないため、それでも何も得られません。

違う?
curlA にランダム コードを取得するように指示し、次に、先ほどのランダム コードを使用して CurlB をシミュレートし、最終的に必要なデータを取得します。
同時に、「ページ B はこのランダム コードの正当性を検証してから、データをページ A に返す必要がある」と言ったとき、このデータが最終的に必要なデータであり、このデータにはランダム コードが伴うだけで済みます。コード。

@ShadowSniper、非常に良い例です。考え方が広がります。
これが頭に浮かびます:
ブラウザがページ A にアクセスすると、ランダム コードが生成され、それが ajax パラメータとしてページ B に渡されます。ページ B は、ランダム コードの正当性を検証してから、データをページ A に返す必要があります。 。
したがって、ページ A を直接カールしても、何も得られません。
ページ B を直接カールします (ajax ページの場合)。正当なランダム コードがないため、それでも何も得られません。

あなたが警戒しているのはカールだけですか?そうすると、シールドを構築するという考え方全体が間違っています
あなたが守る必要があるのはこれです
現在、Webkit に基づいたブラウザ (非 GUI ブラウザ) は、curl よりもはるかに多くあります。


csdn 
都被抓取 
http://s.yanghao.org/program/viewdetail.php?i=393421

引用 18 楼 changjay 的回复:@ShadowSniper, 很好的实例哦,开阔思路了。
这就想到于:
浏览器访问A页面时,生成一个随机码,该随机码作为ajax参数传递到B页面,B页面需要验证这个随机码的合法性,然后返回数据到A页面。
所以直接curl A页面的话,什么也得不到。
直接curl B页面(ajax页面的话),由于没有合法的随机码,所以还是什……


我说的那个方法,大概思路是对的。但我一开始没考虑跨域的问题。

a页面生成验证码,写入db。a带着这个验证码去请求b接口,b接口拿到a传过来的验证码,去db里查询是否存在,如果存在,就返回正确数据,并且从db中清除掉这个验证码。

所以由a页面生成的验证码,只能使用一次。

当你模拟请求a页面,a不光会生成一个验证码,同时会把这个流程走完,并且销毁掉这个验证码。也会返回数据,但这一次你无法得到a页面返回的数据(只能看到,但得不到。不信拿我的那几个例子去试验下)

而一般来说,页面中含有ajax的二次请求,我们应该在第一次请求得到页面中ajax请求的地址后,用正则分析出a页面生成的验证码和他ajax请求的地址,再用php带着这个验证码去请求一次。希望通过这样,来得到正确的数据。但可惜的是,在你第一次模拟请求a页面时,他已经把整个流程走完了,包括页面中的ajax会自动执行。那个生成验证码也被销毁了。所以这里就造成了个矛盾的问题。
这种情况,抓取方和被抓取方处于同域的情况下,是可以实现的。

但实际情况中,抓取方不可能和被抓取方处于同域,所以请求a页面后,可以得到生成的验证码,但是ajax请求不会成功,因为跨域。所以那个生成的验证码也不会被销毁。那么我们就可以拿到验证码后,再用php去请求一下那个ajax地址来获得正确的数据。

引用 18 楼 changjay 的回复:@ShadowSniper, 很好的实例哦,开阔思路了。
这就想到于:
浏览器访问A页面时,生成一个随机码,该随机码作为ajax参数传递到B页面,B页面需要验证这个随机码的合法性,然后返回数据到A页面。
所以直接curl A页面的话,什么也得不到。
直接curl B页面(ajax页面的话),由于没有合法的随机码,所以还是什……


a.php

function request( $url, $header = '', $postfields = '' ){		$ch = curl_init();		$options = array(			CURLOPT_URL => $url,			CURLOPT_HEADER => 0,			//CURLOPT_HTTPHEADER => $header,			CURLOPT_NOBODY => 0,			CURLOPT_PORT => 80,			CURLOPT_POST => 1,			CURLOPT_POSTFIELDS => $postfields,			CURLOPT_RETURNTRANSFER => 1,			CURLOPT_FOLLOWLOCATION => 1,			//CURLOPT_COOKIEJAR => $cookie_jar,			//CURLOPT_COOKIEFILE => $cookie_jar,			//CURLOPT_SSL_VERIFYPEER => 0,			//CURLOPT_SSL_VERIFYHOST => 1,			CURLOPT_TIMEOUT => 30		);		curl_setopt_array($ch, $options);		$code = curl_exec($ch);		curl_close($ch);		return $code;}$url = 'http://www.angryfrog.com/b.php';echo request($url);


b.php
<script>alert(123);</script>



执行一下a.php,b.php中的js返回后会被自动执行。

ShadowSniper研究的比较深,谢谢。好好再琢磨一下。

抓数据,一般只抓页面,页面里的图片,CSS,JS等等都是不会继续向服务器请求的。所以很容易判断哪些用户的请求是爬虫,哪些不是:)

访问频率检查方案方面,请问大家有什么经验指点?

//第一步:入口文件检测IP黑名单实现禁止访问

//第二步:访问频率检测
$ip = get_client_ip();    //获取访问者IP
$ipCode = md5($ip);
$次数 = intval($cache->get($ipCode));  //把null转成0
if($次数 efddf08f3c8698f9f55e8ce5eaf800baset($ipCode, ++$次数, 3000);  //缓存过期时间为3000毫秒=3秒
else{
    //将该IP加入黑名单,N天/N个小时后解除黑名单
}

建议在 .htaccess直接屏蔽对方的 IP地址段。
当然,也可以考虑iptables;

用js joson可以增加难度

抓数据,一般只抓页面,页面里的图片,CSS,JS等等都是不会继续向服务器请求的。所以很容易判断哪些用户的请求是爬虫,哪些不是:)
怎么理解,分析客户端是否下载了CSS,JS文件?这个怎么判断?还有怎么可以分辨出是搜索引擎爬虫还是不良爬虫?

25 階の LuciferStar からの返信を引用: データをキャプチャするとき、通常はページのみがキャプチャされ、ページ内の画像、CSS、JS などはサーバーに要求し続けません。したがって、どのユーザーリクエストがクローラーであり、どのユーザーリクエストがクローラーではないかを判断するのは簡単です:)
クライアントが CSS ファイルと JS ファイルをダウンロードしたかどうかを理解し、分析するにはどうすればよいでしょうか?これをどう判断するか?そして、それが検索エンジンのクローラーであるか、悪いクローラーであるかをどうやって判断できるのでしょうか? これは、収集を防ぐためのサーバー上の戦略である必要があります。
サーバー ソフトウェアが動作を制御する必要があると推定されます。

マーク 私もそのような問題に遭遇しました。それらのほとんどはサーバーによって処理されているようです

申し訳ありませんが、私の考えにバグがあることに突然気づきました。

同じドメインのみをテストしました。実際の状況では、ajax リクエストは自動的に正常に実行されません。クロスドメインだから。

自分のサーバーから相手のページをリクエストすると、それらのajaxを含むhtmlとjsが得られます。ブラウザに戻った後。このとき、ドメインは独自のサーバーになり、ページ上の ajax はドメインを越えて相手の ajax インターフェイスを正常にリクエストできません。生成された検証コードが自動的に破棄されることについて話す必要はありません...
ダニエル、Tencent News にはこの種の高度な方法があるようです。主要なコンテンツを含むすべての JS は動的であり、あらゆる種類のものが含まれています。ひどい頭痛

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。