web-dev-qa-db-ja.com

正直なWebクローラーの検出

ボットからのリクエストを(サーバー側で)検出したいと思います。現時点では、悪意のあるボットは気にせず、Niceをプレイしているボットだけを気にします。ユーザーエージェントの文字列を「bot」などのキーワードと照合することを主に含むいくつかのアプローチを見てきました。しかし、それは厄介で、不完全で、維持できないようです。それで、誰かがこれ以上しっかりしたアプローチを持っていますか?そうでない場合は、すべてのフレンドリーなユーザーエージェントを最新の状態に保つために使用するリソースはありますか?

興味があれば:私は検索エンジンのポリシーに対して何もしようとはしていません。サイトには、わずかに異なるバージョンのページの1つがユーザーにランダムに表示されるセクションがあります。ただし、Webクローラーが検出された場合は、インデックスの一貫性を保つために、常に同じバージョンを提供します。

また、私はJavaを使用していますが、このアプローチはどのサーバーサイドテクノロジーでも同様であると思います。

36
JavadocMD

Robotstxt.org Robots Database で、既知の「優れた」Webクローラーに関するデータの非常に完全なデータベースを見つけることができます。このデータを利用することは、ユーザーエージェントでbotを照合するよりもはるかに効果的です。

26
Sparr

「ボット」でのユーザーエージェントのマッチングは厄介かもしれないとおっしゃいましたが、かなり良いマッチングであることがわかりました。私たちの調査によると、ヒット数の約98%をカバーすることがわかっています。また、誤検出の一致もまだ発生していません。これを99.9%まで上げたい場合は、「クローラー」、「baiduspider」、「ia_archiver」、「curl」など、他のいくつかの有名な一致を含めることができます。これは、数百万を超える本番システムでテストされています。ヒット数。

ここにあなたのためのいくつかのc#ソリューションがあります:

1)最も単純

ミスを処理するときに最速です。つまり、ボット以外からのトラフィック–通常のユーザー。クローラーの99%以上をキャッチします。

bool iscrawler = Regex.IsMatch(Request.UserAgent, @"bot|crawler|baiduspider|80legs|ia_archiver|voyager|curl|wget|yahoo! Slurp|mediapartners-google", RegexOptions.IgnoreCase);

2)中

ヒットを処理するときに最速です。つまり、ボットからのトラフィックです。ミスに対してもかなり速い。クローラーの100%近くをキャッチします。 「ボット」、「クローラー」、「スパイダー」に事前に一致します。他の既知のクローラーを追加できます。

List<string> Crawlers3 = new List<string>()
{
    "bot","crawler","spider","80legs","baidu","yahoo! Slurp","ia_archiver","mediapartners-google",
    "lwp-trivial","nederland.zoek","ahoy","anthill","appie","arale","araneo","ariadne",            
    "atn_worldwide","atomz","bjaaland","ukonline","calif","combine","cosmos","cusco",
    "cyberspyder","digger","grabber","downloadexpress","ecollector","ebiness","esculapio",
    "esther","felix ide","hamahakki","kit-fireball","fouineur","freecrawl","desertrealm",
    "gcreep","golem","griffon","gromit","gulliver","gulper","whowhere","havindex","hotwired",
    "htdig","ingrid","informant","inspectorwww","iron33","teoma","ask jeeves","jeeves",
    "image.kapsi.net","kdd-Explorer","label-grabber","larbin","linkidator","linkwalker",
    "lockon","marvin","mattie","mediafox","merzscope","nec-meshexplorer","udmsearch","moget",
    "motor","muncher","muninn","muscatferret","mwdsearch","sharp-info-agent","webmechanic",
    "netscoop","newscan-online","objectssearch","orbsearch","Packrat","pageboy","parasite",
    "patric","pegasus","phpdig","piltdownman","pimptrain","plumtreewebaccessor","getterrobo-plus",
    "raven","roadrunner","robbie","robocrawl","robofox","webbandit","scooter","search-au",
    "searchprocess","senrigan","shagseeker","site valet","skymob","Slurp","snooper","speedy",
    "curl_image_client","suke","www.sygol.com","tach_bw","templeton","titin","topiclink","udmsearch",
    "urlck","valkyrie libwww-Perl","verticrawl","victoria","webscout","voyager","crawlpaper",
    "webcatcher","t-h-u-n-d-e-r-s-t-o-n-e","webmoose","pagesinventory","webquest","webreaper",
    "webwalker","winona","occam","robi","fdse","jobo","rhcs","gazz","dwcp","yeti","fido","wlm",
    "wolp","wwwc","xget","legs","curl","webs","wget","sift","cmc"
};
string ua = Request.UserAgent.ToLower();
bool iscrawler = Crawlers3.Exists(x => ua.Contains(x));

3)パラノイド

かなり高速ですが、オプション1および2よりも少し遅くなります。これは最も正確であり、必要に応じてリストを維持できます。将来、誤検知が懸念される場合は、「ボット」を含む名前の個別のリストを維持できます。短い一致が見つかった場合は、ログに記録して誤検知がないかチェックします。

// crawlers that have 'bot' in their useragent
List<string> Crawlers1 = new List<string>()
{
    "googlebot","bingbot","yandexbot","ahrefsbot","msnbot","linkedinbot","exabot","compspybot",
    "yesupbot","paperlibot","tweetmemebot","semrushbot","gigabot","voilabot","adsbot-google",
    "botlink","alkalinebot","araybot","undrip bot","borg-bot","boxseabot","yodaobot","admedia bot",
    "ezooms.bot","confuzzledbot","coolbot","internet cruiser robot","yolinkbot","diibot","musobot",
    "dragonbot","elfinbot","wikiobot","twitterbot","contextad bot","hambot","iajabot","news bot",
    "irobot","socialradarbot","ko_yappo_robot","skimbot","psbot","rixbot","seznambot","careerbot",
    "simbot","solbot","mail.ru_bot","spiderbot","blekkobot","bitlybot","techbot","void-bot",
    "vwbot_k","diffbot","friendfeedbot","archive.org_bot","woriobot","crystalsemanticsbot","wepbot",
    "spbot","tweetedtimes bot","mj12bot","who.is bot","psbot","robot","jbot","bbot","bot"
};

// crawlers that don't have 'bot' in their useragent
List<string> Crawlers2 = new List<string>()
{
    "baiduspider","80legs","baidu","yahoo! Slurp","ia_archiver","mediapartners-google","lwp-trivial",
    "nederland.zoek","ahoy","anthill","appie","arale","araneo","ariadne","atn_worldwide","atomz",
    "bjaaland","ukonline","bspider","calif","christcrawler","combine","cosmos","cusco","cyberspyder",
    "cydralspider","digger","grabber","downloadexpress","ecollector","ebiness","esculapio","esther",
    "fastcrawler","felix ide","hamahakki","kit-fireball","fouineur","freecrawl","desertrealm",
    "gammaspider","gcreep","golem","griffon","gromit","gulliver","gulper","whowhere","portalbspider",
    "havindex","hotwired","htdig","ingrid","informant","infospiders","inspectorwww","iron33",
    "jcrawler","teoma","ask jeeves","jeeves","image.kapsi.net","kdd-Explorer","label-grabber",
    "larbin","linkidator","linkwalker","lockon","logo_gif_crawler","marvin","mattie","mediafox",
    "merzscope","nec-meshexplorer","mindcrawler","udmsearch","moget","motor","muncher","muninn",
    "muscatferret","mwdsearch","sharp-info-agent","webmechanic","netscoop","newscan-online",
    "objectssearch","orbsearch","Packrat","pageboy","parasite","patric","pegasus","perlcrawler",
    "phpdig","piltdownman","pimptrain","pjspider","plumtreewebaccessor","getterrobo-plus","raven",
    "roadrunner","robbie","robocrawl","robofox","webbandit","scooter","search-au","searchprocess",
    "senrigan","shagseeker","site valet","skymob","slcrawler","Slurp","snooper","speedy",
    "spider_monkey","spiderline","curl_image_client","suke","www.sygol.com","tach_bw","templeton",
    "titin","topiclink","udmsearch","urlck","valkyrie libwww-Perl","verticrawl","victoria",
    "webscout","voyager","crawlpaper","wapspider","webcatcher","t-h-u-n-d-e-r-s-t-o-n-e",
    "webmoose","pagesinventory","webquest","webreaper","webspider","webwalker","winona","occam",
    "robi","fdse","jobo","rhcs","gazz","dwcp","yeti","crawler","fido","wlm","wolp","wwwc","xget",
    "legs","curl","webs","wget","sift","cmc"
};

string ua = Request.UserAgent.ToLower();
string match = null;

if (ua.Contains("bot")) match = Crawlers1.FirstOrDefault(x => ua.Contains(x));
else match = Crawlers2.FirstOrDefault(x => ua.Contains(x));

if (match != null && match.Length < 5) Log("Possible new crawler found: ", ua);

bool iscrawler = match != null;

注:

  • 正規表現オプション1に名前を追加し続けるのは魅力的ですが、これを行うと遅くなります。より完全なリストが必要な場合は、ラムダを使用したlinqの方が高速です。
  • .ToLower()がlinqメソッドの外部にあることを確認してください。メソッドはループであり、各反復中に文字列を変更することに注意してください。
  • 常に最も重いボットをリストの先頭に配置して、より早く一致するようにします。
  • リストを静的クラスに入れて、すべてのページビューで再構築されないようにします。

ハニーポット

これに対する唯一の実際の代替手段は、ボットだけが到達する「ハニーポット」リンクをサイトに作成することです。次に、ハニーポットページにヒットしたユーザーエージェント文字列をデータベースに記録します。次に、それらのログに記録された文字列を使用して、クローラーを分類できます。

Postives:自分自身を宣言していないいくつかの未知のクローラーと一致します。

Negatives:すべてのクローラーがサイト上のすべてのリンクにヒットするほど深く掘り下げているわけではないため、ハニーポットに到達しない可能性があります。

84
Dave Sumter

1つの提案は、ボットだけが従う空のアンカーをページに作成することです。通常のユーザーにはリンクが表示されず、スパイダーとボットがたどります。たとえば、サブフォルダーを指す空のアンカータグは、取得要求をログに記録します...

<a href="dontfollowme.aspx"></a>

多くの人がHoneyPotの実行中にこのメソッドを使用して、robots.txtファイルをフォローしていない悪意のあるボットをキャッチします。 ASP.NETハニーポットソリューション で空のアンカーメソッドを使用します。これらの不気味なクローラーをトラップしてブロックするために作成しました...

9
Dscoduc

エントリページが/robots.txtである訪問者は、おそらくボットです。

5
Sparr

このような迅速で汚いものは良いスタートかもしれません:

return if request.user_agent =~ /googlebot|msnbot|baidu|curl|wget|Mediapartners-Google|Slurp|ia_archiver|Gigabot|libwww-Perl|lwp-trivial/i

注:Railsコードですが、正規表現は一般的に適用可能です。

4
Brian Armstrong

ボットの大部分がrobots.txtを使用していないことは間違いありませんが、それが私の最初の考えでした。

ボットを検出する最良の方法は、リクエスト間の時間であるように思われます。リクエスト間の時間が一貫して速い場合は、ボットです。

0
Stewart McKee