本文目录导读:

在编写Python爬虫时,遵守robots.txt协议不仅是技术规范,更是职业道德和法律要求,以下是Python脚本爬虫遵守Robots协议的完整实践指南:
理解Robots协议
robots.txt文件位于网站根目录,https://example.com/robots.txt
主要规则:
User-agent: 指定爬虫名称Disallow: 禁止访问的路径Allow: 允许访问的路径Crawl-delay: 建议的抓取间隔(秒)
Python实现遵守Robots协议
使用robotparser(Python内置库)
import urllib.robotparser
from urllib.parse import urlparse
class RobotsChecker:
def __init__(self, base_url, user_agent='MyScraper/1.0'):
self.base_url = base_url
self.user_agent = user_agent
self.rp = urllib.robotparser.RobotFileParser()
self._load_robots()
def _load_robots(self):
"""加载并解析robots.txt"""
robots_url = f"{self.base_url}/robots.txt"
self.rp.set_url(robots_url)
try:
self.rp.read()
except Exception as e:
print(f"无法读取robots.txt: {e}")
# 保守策略:如果无法读取,默认允许所有访问
self.rp.allow_all = True
def can_fetch(self, url):
"""检查是否可以抓取指定URL"""
return self.rp.can_fetch(self.user_agent, url)
def get_crawl_delay(self):
"""获取推荐的抓取延迟"""
delay = self.rp.crawl_delay(self.user_agent)
return delay if delay else 1 # 默认1秒
# 使用示例
checker = RobotsChecker('https://example.com')
url = 'https://example.com/products'
if checker.can_fetch(url):
delay = checker.get_crawl_delay()
print(f"允许抓取 {url},建议延迟 {delay}秒")
else:
print(f"禁止抓取 {url}")
使用requests-robots第三方库(更便捷)
# 安装: pip install requests-robots
from requests_robots import RobotsTxt
robots = RobotsTxt('https://example.com')
# 检查URL
if robots.allowed('https://example.com/products', 'MyScraper'):
print("允许抓取")
else:
print("禁止抓取")
# 获取延迟
delay = robots.delay('MyScraper')
print(f"建议延迟: {delay}秒")
集成到爬虫框架中
Scrapy框架示例
import scrapy
from urllib.robotparser import RobotFileParser
class CompliantSpider(scrapy.Spider):
name = 'compliant_spider'
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.robots_parser = RobotFileParser()
self.robots_parser.set_url(f"{self.start_urls[0]}/robots.txt")
self.robots_parser.read()
def start_requests(self):
for url in self.start_urls:
if self.robots_parser.can_fetch(self.name, url):
yield scrapy.Request(url, callback=self.parse)
else:
self.logger.warning(f"Robots协议禁止访问: {url}")
def parse(self, response):
# 解析逻辑
pass
自定义通用爬虫类
import time
import requests
from urllib.robotparser import RobotFileParser
class CompliantCrawler:
def __init__(self, base_url, user_agent='MyCrawler/1.0'):
self.base_url = base_url.rstrip('/')
self.user_agent = user_agent
self.session = requests.Session()
self.session.headers.update({'User-Agent': user_agent})
self.robots = RobotFileParser()
self._init_robots()
self.last_request_time = 0
def _init_robots(self):
"""初始化robots解析器"""
robots_url = f"{self.base_url}/robots.txt"
self.robots.set_url(robots_url)
try:
self.robots.read()
print(f"已加载robots.txt: {robots_url}")
except:
print(f"无法加载robots.txt,采用保守策略")
self.robots.allow_all = True
def _respect_crawl_delay(self):
"""遵守抓取延迟"""
delay = self.robots.crawl_delay(self.user_agent)
if delay:
time.sleep(delay)
else:
time.sleep(1) # 默认延迟
def fetch(self, url):
"""安全抓取URL"""
if not self.robots.can_fetch(self.user_agent, url):
print(f"禁止访问: {url}")
return None
self._respect_crawl_delay()
try:
response = self.session.get(url, timeout=10)
response.raise_for_status()
# 检查响应中的meta robots标签
if 'noindex' in response.text.lower():
print(f"页面包含noindex指令: {url}")
return response
except Exception as e:
print(f"请求失败: {e}")
return None
# 使用示例
crawler = CompliantCrawler('https://httpbin.org')
response = crawler.fetch('https://httpbin.org/')
if response:
print(response.status_code)
高级处理策略
处理特殊情况
class AdvancedRobotsHandler:
def __init__(self, base_url):
self.base_url = base_url
self.site_maps = [] # 存储sitemap信息
self._parse_sitemaps()
def _parse_sitemaps(self):
"""从robots.txt中提取sitemap"""
try:
response = requests.get(f"{self.base_url}/robots.txt")
for line in response.text.split('\n'):
if line.lower().startswith('sitemap:'):
sitemap_url = line.split(':')[1].strip()
self.site_maps.append(sitemap_url)
except:
pass
def get_allowed_urls(self, user_agent):
"""获取允许访问的URL列表(通过sitemap)"""
allowed_urls = []
for sitemap_url in self.site_maps:
try:
# 解析sitemap XML
response = requests.get(sitemap_url)
# 这里可以使用XML解析器提取URL
# ...
except:
continue
return allowed_urls
def is_url_allowed(self, url, user_agent='*'):
"""更全面的检查"""
# 1. 检查robots.txt
# 2. 检查页面meta标签
# 3. 检查X-Robots-Tag头部
# ...
pass
最佳实践清单
class RobotsComplianceChecklist:
"""
遵守Robots协议的检查清单
"""
@staticmethod
def validate_crawler_behavior():
checks = [
"✅ 启动时读取并解析robots.txt",
"✅ 使用自定义User-Agent(非默认爬虫)",
"✅ 每次请求前检查robots.txt权限",
"✅ 遵守Crawl-delay指令",
"✅ 不在禁止路径下抓取",
"✅ 尊重Disallow中的路径模式",
"✅ 定期重新读取robots.txt(如每日一次)",
"✅ 处理Allow例外规则",
"✅ 检查页面meta robots标签",
"✅ 设置合理的请求间隔",
"✅ 不违反robots.txt中隐含的规则"
]
print("Robots协议遵守检查清单:")
for check in checks:
print(f" {check}")
return checks
# 使用
RobotsComplianceChecklist.validate_crawler_behavior()
注意事项
- 缓存策略:将
robots.txt内容缓存以减少重复请求,但需设置过期时间 - 动态网站:有些网站使用JavaScript渲染内容,但robots.txt规则仍然适用
- 法律风险:即使遵守robots.txt,某些网站仍可能禁止爬虫
- 道德考量:遵守robots.txt是基本的互联网礼仪
完整示例代码
#!/usr/bin/env python3
"""
遵守Robots协议的爬虫示例
"""
import time
import requests
from urllib.robotparser import RobotFileParser
from urllib.parse import urljoin
class EthicalCrawler:
def __init__(self, base_url, user_agent='EthicalBot/1.0'):
self.base_url = base_url.rstrip('/')
self.user_agent = user_agent
self.session = requests.Session()
self.session.headers.update({'User-Agent': user_agent})
self.robots_parser = RobotFileParser()
self._init_robots()
self.last_request_time = 0
def _init_robots(self):
"""初始化并读取robots.txt"""
robots_url = urljoin(self.base_url, '/robots.txt')
self.robots_parser.set_url(robots_url)
try:
self.robots_parser.read()
print(f"✅ 已加载robots.txt: {robots_url}")
except Exception as e:
print(f"⚠️ 无法加载robots.txt: {e}")
print(" 采用保守策略:默认允许所有访问")
self.robots_parser.allow_all = True
def can_fetch(self, url):
"""检查是否允许抓取"""
return self.robots_parser.can_fetch(self.user_agent, url)
def get_delay(self):
"""获取推荐的抓取延迟"""
delay = self.robots_parser.crawl_delay(self.user_agent)
return max(delay, 1) if delay else 1 # 至少1秒
def fetch(self, url, respect_robots=True):
"""安全抓取URL"""
full_url = urljoin(self.base_url, url)
# 步骤1: 检查robots.txt权限
if respect_robots and not self.can_fetch(full_url):
print(f"❌ 禁止访问: {full_url}")
return None
# 步骤2: 遵守Crawl-Delay
delay = self.get_delay()
time_since_last = time.time() - self.last_request_time
if time_since_last < delay:
wait_time = delay - time_since_last
print(f"⏳ 等待 {wait_time:.2f} 秒...")
time.sleep(wait_time)
# 步骤3: 发送请求
try:
print(f"➡️ 正在抓取: {full_url}")
self.last_request_time = time.time()
response = self.session.get(full_url, timeout=10)
response.raise_for_status()
# 步骤4: 检查页面级meta robots标签
if 'noindex' in response.text.lower()[:5000]:
print(f"⚠️ 页面包含noindex指令: {full_url}")
# 可根据策略决定是否处理
print(f"✅ 成功抓取: {response.status_code}")
return response
except requests.exceptions.RequestException as e:
print(f"❌ 请求失败: {e}")
return None
# 使用示例
if __name__ == "__main__":
crawler = EthicalCrawler('https://httpbin.org')
# 抓取允许的页面
response = crawler.fetch('/')
if response:
print(response.text[:200])
# 抓取禁止的页面(会失败)
crawler.fetch('/deny-page')
通过以上方法,你的Python爬虫可以正确遵守Robots协议,既尊重网站规则,又能高效合法地获取数据,记得始终将遵守协议放在首位!
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播