让 Web 后端简单方便的区别对待爬虫请求

爬虫的一些通俗规范

通常知名的 Web 爬虫/蜘蛛/机器人 都会按照一定的规范或者约定来做事情,例如 robots.txt 协议。一般来讲各大搜索引擎都有相关的 Web 抓取程序说明页面,例如:

综合各种爬虫说明,总结出判断请求来源是否为爬虫也有好几种方法:

  • 一部分爬虫有规范的请求头(匹配请求头)
  • 一部分爬虫的 IP 范围固定(匹配来源 ip)
  • 绝大多数的爬虫在 User-Agent 中存在特殊字段(匹配 UA)

比较通用的是匹配 UA 的方式,通常这个用得也最多。因为匹配 UA 可以精确识别爬虫类型,例如谷歌的 Googlebot 又区分出了 Googlebot-News、Googlebot-Mobile、Googlebot-Vidoe、Googlebot-Image 等适用于不同类型的数据源的爬虫。

另外,匹配 UA 用得比较多的还有对用户请求来源的判断,来自 PC 或是 手机/平板,来自 IE 还是 Chrome 。

虽然能通过 UA 轻松判断请求是否来自于爬虫,但是全世界爬虫程序实在不少,因为不仅仅是那几个知名的搜索引擎而已,还有例如:

  • Python-urllib
  • Commons-HttpClient
  • nutch
  • crawler4j

等这类知名的抓取工具默认 UA,以及:

  • Twitterbot
  • facebookexternalhit
  • Applebot

等这些非搜索引擎业务公司的外部数据抓取功能,甚至连知乎都有爬虫。

注:知乎爬虫体现很明显的一个功能就是当你在知乎编辑器输入网址的时候服务端爬虫开始工作,抓取该网址页面的 title 数据响应回来用于填充链接文字。

相关库

在 NodeJs 上,这个项目能方便的根据 UA 字符串判断请求来源是否为爬虫:

isBot(req.headers['user-agent'])
isBot("Googlebot/2.1 (+http://www.google.com/bot.html)") // true
isBot("Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36") // false

在 Ruby 上,https://github.com/Hentioe/isbot 也提供同样的功能(感受下 Ruby 代码的自由度吧):

require 'isbot'

user_agent = 'Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)'

# 三种方式使用:

# 1. 利用 is_bot 函数:
puts is_bot user_agent # true

# 2. 利用 String 对象的猴子补丁方法:
puts user_agent.is_bot? # true

# 3. 利用 is_bot 函数回调代码块:
is_bot user_agent do |match_bot|
  puts match_bot # Googlebot/
end

针对爬虫响应结果

require 'sinatra'

before '/*' do
  if request.user_agent.is_bot?
    redirect '/bot.html'
  end
end

get '/' do
    # Your index page forward
end

如上,爬虫请求访问任何 URL 都会被重定向到 bot.html 页面。当然,一般来讲针对爬虫请求特殊处理是为了 SEO,而不是禁止抓取。

对于 SPA 应用可以返回一个服务端渲染结果,例如我的博客(可以将 UA 伪装成爬虫访问试试看)。

伪装 UA 的恶意爬虫

很多人在写数据抓取程序的时候,大量抓取数据据为己用,又担心服务端和谐自己的 IP 或者请求,会特意将 UA 改成某搜索引擎的爬虫。
通常网站后端对待来自于爬虫的请求会放宽很多,这也正是可能被人恶意利用的原因。但是针对这种爬虫程序并不是没有办法,例如 DNS 反查。

举个例子:在这个在线工具页面输入 157.55.33.18 ,查询到的 Name Server 是:

msnbot-157-55-33-18.search.msn.com

可以看到以 search.msn.com 结尾,毫无疑问这是真实的来自 Bingbot 的请求,不是伪装的。只要不定时将记录在库的爬虫 ip 进行 DNS 反查,就可以封杀那些伪装成搜索引擎的恶意爬虫了。

附加:Googlebot 请求来源 ip 反查结果一定是以 googlebot.com 结尾的域名。

相关官方说明:

最后

Ruby 库用的爬虫 User-Agent 数据来源,也欢迎大家去这个项目上提交没有记录的小众爬虫 UA 。