在深入讨论爬取一个网站之前,我们首先需要对目标站点的规模和结构进行一定程度的了解。网站自身的 robots.txt 和 Sitemap 文件都可以为我们提供一定的帮助,此外还有一些能提供更详细信息的外部工具,比如Google 搜索和 WHOIS。
检查robots.txt
大多数网站都会定义 robots.txt 文件,这样可以让爬虫了解爬取该网站时存在哪些限制。这些限制虽然是仅仅作为建议给出,但是良好的网络公民都应当遵守这些限制。在爬取之前,检查 robots.txt 文件这一宝贵资源可以将爬虫被封禁的可能性降至最低,而且还能发现和网站结构相关的线索。
关于 robots.txt 协议的更多信息可以参见 http://www.robotstxt.org。下面的代码是我们的示例文件 robots.txt 中的内容, 可以访问
http://example.python-scraping.com/robots.txt 获取。
# section 1
User-agent: BadCrawler
Disallow: /
# section 2
User-agent: *
Crawl-delay: 5
Disallow: /trap
# section 3
Sitemap: http://example.python-scraping.com/sitemap.xml
在 section 1 中,robots.txt 文件禁止用户代理为 BadCrawler 的爬虫爬取该网站,不过这种写法可能无法起到应有的作用,因为恶意爬虫根本不会遵从 robots.txt 的要求。本章后面的一个例子将会展示如何让爬虫自动遵守 robots.txt 的要求。
section 2 规定,无论使用哪种用户代理,都应该在两次下载请求之间给出 5 秒的抓取延迟,我们需要遵从该建议以避免服务器过载。这里还有一个 /trap 链接,用于封禁那些爬取了不允许访问的链接的恶意爬虫。如果你访问了这个链接,服务器就会封禁你的 IP 一分钟!一个真实的网站可能会对你的 IP 封禁更长时间,甚至是永久封禁。不过如果这样设置的话,我们就无法继续这个例子了。
section 3 定义了一个Sitemap 文件,我们将在下一节中了解如何检查该文件。
检查网站地图
网站提供的 Sitemap 文件(即网站地图)可以帮助爬虫定位网站最新的内容,而无须爬取每一个网页。如果想要了解更多信息,可以从 http://www.sitemaps.org/protocol.html 获取网站地图标准的定义。许多网站发布平台都有自动生成网站地图的能力。下面是在 robots.txt 文件中定位到 Sitemap 文件的内容。
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url><loc>http://example.python-scraping.com/view/Afghanistan-1</loc>
</url>
<url><loc>http://example.python-scraping.com/view/Aland-Islands-2</loc>
</url>
<url><loc>http://example.python-scraping.com/view/Albania-3</loc>
</url>
...
</urlset>
估算网站大小
网站地图提供了所有网页的链接,我们会在后面的小节中使用这些信息,用于创建我们的第一个爬虫。虽然Sitemap 文件提供了一种爬取网站的有效方式,但是我们仍需对其谨慎处理,因为该文件可能存在缺失、过期或不完整的问题。
目标网站的大小会影响我们如何进行爬取。如果是像我们的示例站点这样只有几百个URL 的网站,效率并没有那么重要;但如果是拥有数百万个网页的站点,使用串行下载可能需要持续数月才能完成。
估算网站大小的一个简便方法是检查 Google 爬虫的结果,因为Google 很可能已经爬取过我们感兴趣的网站。我们可以通过 Google 搜索的 site 关键词过滤域名结果,从而获取该信息。我们可以从http://www.google.com/advanced_search 了解到该接口及其他高级搜索参数的用法。在域名后面添加 URL 路径,可以对结果进行过滤,仅显示网站的某些部分。
同样,你的结果可能会有所不同;不过,这种附加的过滤条件非常有用,因为在理想情况下,你只希望爬取网站中包含有用数据的部分,而不是爬取网站的每个页面。
识别网站技术
构建网站所使用的技术类型也会对我们如何爬取产生影响。有一个十分有用的工具可以检查网站构建的技术类型——detectem 模块,该模块需要 Python 3.5+ 环境以及 Docker 。如果你还没有安装 Docker , 可以遵照 https://www.docker.com/products/overview 中你使用的操作系统所对应的说明操作。当 Docker 安装好后,你可以运行如下命令。
docker pull scrapinghub/splash
pip install detectem
上述操作将从 ScrapingHub 拉取最新的Docker 镜像,并通过 pip 安装该库。为了确保不受任何更新或改动的影响,推荐使用Python 虚拟环境(https://docs.python.org/3/library/venv.html)或 Conda 环境(https://conda.io/docs/using/envs.html),并查看项目的 ReadMe 页面(https://github.com/spectresearch/detectem)。
detectem 模块基于许多扩展模块,使用一系列请求和响应,来探测网站使用的技术。它使用了Splash,这是由ScrapingHub 开发的一个脚本化浏览器。要想运行该模块,只需使用 det 命令即可。
$ det http://example.python-scraping.com
[('jquery', '1.11.0')]
我们可以看到示例网站使用了通用的 JavaScript 库,因此其内容很可能嵌入在 HTML 当中,相对来说应该比较容易抓取。
detectem 仍然相当年轻,旨在成为Wappalyzer 的Python 对标版本,Wappalyzer 是一个基于Node.js 的项目,支持解析不同后端、广告网络、JavaScript 库以及服务器设置。你也可以在Docker 中运行Wappalyzer。首先需要下载其Docker 镜像,运行如下命令。
$ docker pull wappalyzer/cli
然后,你可以从Docker 实例中运行脚本。
$ docker run wappalyzer/cli http://example.python-scraping.com
输出结果不太容易阅读,不过当我们将其拷贝到JSON 解析器中,可以看
到检测出来的很多库和技术。
{'applications':
[{'categories': ['Javascript Frameworks'],
'confidence': '100',
'icon': 'Modernizr.png',
'name': 'Modernizr',
'version': ''},
{'categories': ['Web Servers'],
'confidence': '100',
'icon': 'Nginx.svg',
'name': 'Nginx',
'version': ''},
{'categories': ['Web Frameworks'],
'confidence': '100',
'icon': 'Twitter Bootstrap.png',
'name': 'Twitter Bootstrap',
'version': ''},
{'categories': ['Web Frameworks'],
'confidence': '100',
'icon': 'Web2py.png',
'name': 'Web2py',
'version': ''},
{'categories': ['Javascript Frameworks'],
'confidence': '100',
'icon': 'jQuery.svg',
'name': 'jQuery',
'version': ''},
{'categories': ['Javascript Frameworks'],
'confidence': '100',
'icon': 'jQuery UI.svg',
'name': 'jQuery UI',
'version': '1.10.3'},
{'categories': ['Programming Languages'],
'confidence': '100',
'icon': 'Python.png',
'name': 'Python',
'version': ''}],
'originalUrl': 'http://example.python-scraping.com',
'url': 'http://example.python-scraping.com'}
从上面可以看出,检测结果认为Python 和 web2py 框架具有很高的可信度。我们还可以看到网站使用了前端 CSS 框架 Twitter Bootstrap。Wappalyzer还检测到网站使用了 Modernizer.js 以及用于后端服务器的 Nginx。由于网站只使用了 JQuery 和 Modernizer,那么网站不太可能全部页面都是通过JavaScript加载的。而如果改用 AngularJS 或 React 构建该网站的话,此时的网站内容很可能就是动态加载的了。另外,如果网站使用了ASP.NET,那么在爬取网页时,就必须要用到会话管理和表单提交了。