13.4. urllib.robotparser — 互联网爬虫访问控制
目标:解析用于控制网络怕爬虫的 robots.txt 文件
robotparser
实现了一个用于分析 robots.txt
文件格式的解析器, 它含有一个检查给定用户代理是否可以访问给定资源的函数。它的目的是给那些品行端正的爬虫用的,或用来指导需要节流,否则就会被限制访问的其他抓取器。
robots.txt
robots.txt
文件是一个简单的基于文本的访问控制系统,用于控制那些自动访问网络资源的程序(如「爬虫」,「抓取器」,等等)。文件由特定的用户代理程序标识的记录以及代理不允许访问的 URLs (或 URL 前缀) 的一个列表组成。
以下是 https://pymotw.com/
的 robots.txt
文件
robots.txt
Sitemap: https://pymotw.com/sitemap.xml
User-agent: *
Disallow: /admin/
Disallow: /downloads/
Disallow: /media/
Disallow: /static/
Disallow: /codehosting/
它阻止访问网站的某些部分,因为如果一个搜索引擎对该部分进行索引将需要大量计算且容易导致服务器过载。更多完整的 robots.txt
例子,请参考 The Web Robots Page 。
测试访问许可
使用前面呈现过的数据,一个简单的抓取器可以用 RobotFileParser.can_fetch()
测试它是否被允许下载一个页面。
urllib_robotparser_simple.py
from urllib import parse
from urllib import robotparser
AGENT_NAME = 'PyMOTW'
URL_BASE = 'https://pymotw.com/'
parser = robotparser.RobotFileParser()
parser.set_url(parse.urljoin(URL_BASE, 'robots.txt'))
parser.read()
PATHS = [
'/',
'/PyMOTW/',
'/admin/',
'/downloads/PyMOTW-1.92.tar.gz',
]
for path in PATHS:
print('{!r:>6} : {}'.format(
parser.can_fetch(AGENT_NAME, path), path))
url = parse.urljoin(URL_BASE, path)
print('{!r:>6} : {}'.format(
parser.can_fetch(AGENT_NAME, url), url))
print()
can_fetch()
函数的 URL 参数可以是相对网站根目录的相对路径或是完整的 URL 。
$ python3 urllib_robotparser_simple.py
True : /
True : https://pymotw.com/
True : /PyMOTW/
True : https://pymotw.com/PyMOTW/
False : /admin/
False : https://pymotw.com/admin/
False : /downloads/PyMOTW-1.92.tar.gz
False : https://pymotw.com/downloads/PyMOTW-1.92.tar.gz
长寿爬虫
那些需要很长时间来处理下载好的资源或者为了节流在两次下载之间会有停顿的应用,应该基于已下载内容的时长来周期检查新的 robots.txt
文件。虽然不能自动管理时长,但要跟踪它,却有易用的方法可以让这件事变简单。
urllib_robotparser_longlived.py
from urllib import robotparser
import time
AGENT_NAME = 'PyMOTW'
parser = robotparser.RobotFileParser()
# Using the local copy
parser.set_url('file:robots.txt')
parser.read()
parser.modified()
PATHS = [
'/',
'/PyMOTW/',
'/admin/',
'/downloads/PyMOTW-1.92.tar.gz',
]
for path in PATHS:
age = int(time.time() - parser.mtime())
print('age:', age, end=' ')
if age > 1:
print('rereading robots.txt')
parser.read()
parser.modified()
else:
print()
print('{!r:>6} : {}'.format(
parser.can_fetch(AGENT_NAME, path), path))
# Simulate a delay in processing
time.sleep(1)
print()
在这个极端的例子中,每当已获取的 robots.txt
文件存在超过一秒就会重新下载一个新的。
$ python3 urllib_robotparser_longlived.py
age: 0
True : /
age: 1
True : /PyMOTW/
age: 2 rereading robots.txt
False : /admin/
age: 1
False : /downloads/PyMOTW-1.92.tar.gz
针对长寿应用的一个更好的版本也许应该在下载整个文件之前询问一下文件最后修改的时间。但另一方面, robots.txt
文件通常都很小,所以即使再次获取整个文件也不会多太多代价。
参考
- 标准库 urllib.robotparser 文档
- The Web Robots Page --
robots.txt
文件格式说明.
本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。