学习目标
读完这一讲,你能:
- 用
curl -v拆解一个爬虫请求的完整协议栈 - 理解同样的 GET 请求,为什么技术上一样,法律上不同
- 运行一个"合规探测脚本",自动检查目标站点的法律声明
技术原理
很多教程教爬虫的第一行代码是这样的:
import requests
resp = requests.get('https://测试网站.cn')
print(resp.status_code)
看起来人畜无害。但当你把这行代码放进一个 for 循环里,让它每秒跑十次、一百次,同时把响应存进数据库的时候,这件事的法律性质就变了。
我们用 curl -v 看一个请求的完整链路:
curl -v https://测试网站.cn
输出里你能看到:DNS 解析 → TCP 三次握手 → TLS 握手 → HTTP 请求发送 → 服务器响应 → TCP 连接关闭。整个过程大约几百毫秒。浏览器做这件事和你用 Python 做这件事,在协议层面几乎没有任何区别。都是发一个 HTTP GET 请求,都带了 Host 头,都收到了 200 OK 响应。
区别在哪里?在请求的元数据里。
打开 Chrome DevTools,看一个正常浏览器访问测试网站时的请求头:
GET / HTTP/2
Host: 测试网站.cn
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) ...
Accept: text/html,application/xhtml+xml,application/xml;q=0.9
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Accept-Encoding: gzip, deflate, br
Cookie: _ga=...; _gid=...; sessionid=...
这些头部信息在技术上叫"请求元数据",在法律上叫行为证据。
User-Agent 声明了你的身份:我是一个 macOS 上的 Chrome 浏览器。Accept-Language 声明了你的语言偏好。Cookie 携带了你的会话状态。服务器根据这些信息,决定给你返回什么内容、要不要让你访问、要不要对你限流。
现在看一个典型爬虫的请求头:
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
'Accept': 'text/html,application/xhtml+xml,*/*;q=0.8',
}
resp = requests.get('https://example.com', headers=headers)
这个 User-Agent 是从网上抄的,目的是让服务器以为这是一个正常浏览器。但你的请求行为暴露了你——每秒十次、请求间隔固定到毫秒级、从不点击内链、从来不加载 CSS 和 JS。服务器端的反爬系统一眼就能识别出来。
然后服务器可能会返回 429(Too Many Requests),可能会封禁你的 IP,可能会弹出验证码。这时候如果你选择:换代理 IP、继续请求、破解验证码——你就从技术上的"自动化访问",滑向了法律上的"突破安全措施"。
真实判例
上海晟品网络科技有限公司案,(2017)京0108刑初2384号,北京海淀区人民法院2017年11月判决。
被告单位晟品公司,被告人张某、宋某、侯某某、郭某。案情是:用爬虫技术抓取字节跳动服务器中的视频数据。技术手段包括:伪造 device_id 绕过服务器的身份校验,伪造 User-Agent 和 IP 地址绕过访问频率限制。
法院认定:被告人采用"其他技术手段",获取计算机信息系统中存储的数据,造成被害单位经济损失两万元,构成非法获取计算机信息系统数据罪。
两万元的经济损失——技术服务费。换来的是几个人的刑事案底。
这个案子的核心争议点是:抓取的视频数据是公开的,普通用户不登录也能看到。被告人辩护说,这和用户用浏览器看视频没有区别。法院没有采纳这个辩护理由。
法院的认定逻辑是:
- 目标网站设置了身份校验(
device_id验证)和频率限制(IP 限流) - 被告人伪造了身份信息,绕过了这些措施
- 绕过措施的行为 = "采用其他技术手段"
- 经济损失超过一万元 = 情节严重
- 罪名成立
这个逻辑链条里,数据是不是公开的,在定罪环节没有被考虑。法院更关注的是手段,不是对象。
法律分析
刑法第285条第二款:
违反国家规定,侵入前款规定以外的计算机信息系统或者采用其他技术手段,获取该计算机信息系统中存储、处理或者传输的数据,或者对该计算机信息系统实施非法控制,情节严重的,处三年以下有期徒刑或者拘役,并处或者单处罚金;情节特别严重的,处三年以上七年以下有期徒刑,并处罚金。
"采用其他技术手段"是这里的关键。司法解释没有穷尽列举,但司法实践中已经形成了相对稳定的认定范围:
- 破解密码或身份验证
- 伪造身份标识(
device_id、User-Agent、IP 地址) - 绕过访问频率限制
- 利用系统漏洞
伪造 User-Agent 在技术人眼里就是改一个字符串。但在法庭上,这个字符串是你"身份声明"的一部分。你把"我是 Python requests"改成了"我是 Chrome 浏览器"——这是虚假身份声明。再结合你绕过了频率限制这个事实,法院就会认定你有"突破安全措施"的主观故意。
实战输出:合规探测脚本
以下是一个可以直接运行的脚本,输入 URL 后自动检查目标站点的 robots.txt、响应头安全策略、页面法律声明:
#!/usr/bin/env python3
"""
爬虫合规探测脚本 v1.0
用法: python crawler_legal_check.py https://example.com
"""
import sys
import urllib.robotparser
from urllib.parse import urlparse, urljoin
import requests
def check_robots_txt(base_url):
"""检查并解析 robots.txt"""
parsed = urlparse(base_url)
robots_url = f"{parsed.scheme}://{parsed.netloc}/robots.txt"
rp = urllib.robotparser.RobotFileParser(robots_url)
try:
rp.read()
print(f"\n[+] robots.txt 找到: {robots_url}")
# 检查是否允许通用爬虫
can_fetch = rp.can_fetch('*', '/')
print(f" 是否允许根路径抓取: {'是' if can_fetch else '否'}")
# 获取 crawl-delay
delay = rp.crawl_delay('*')
if delay:
print(f" 建议抓取间隔: {delay} 秒")
return rp
except Exception as e:
print(f"\n[-] robots.txt 读取失败: {e}")
return None
def check_security_headers(url):
"""检查响应头中的安全策略"""
try:
resp = requests.get(url, timeout=10, headers={
'User-Agent': 'CrawlerLegalCheck/1.0 (+https://your-site.com/bot)'
})
print(f"\n[+] HTTP 响应状态: {resp.status_code}")
# 检查关键响应头
headers_of_interest = [
'X-Robots-Tag',
'X-Frame-Options',
'Content-Security-Policy',
'X-RateLimit-Limit',
'Retry-After',
]
for h in headers_of_interest:
val = resp.headers.get(h)
if val:
print(f" {h}: {val}")
return resp.text
except Exception as e:
print(f"\n[-] 请求失败: {e}")
return None
def check_page_legal_notice(html):
"""扫描页面中的法律声明关键词"""
if not html:
return
keywords = [
'爬虫', 'spider', 'crawler', 'robots',
'禁止', '未经授权', '用户协议', '服务条款',
'数据抓取', '数据爬取', '自动化访问'
]
found = []
html_lower = html.lower()
for kw in keywords:
if kw in html_lower:
found.append(kw)
if found:
print(f"\n[!] 页面中发现法律相关关键词: {', '.join(found)}")
print(" ⚠ 建议仔细阅读目标站点的用户协议和法律声明")
else:
print(f"\n[+] 页面中未发现明显的爬虫限制声明")
def main():
if len(sys.argv) < 2:
print("用法: python crawler_legal_check.py <URL>")
sys.exit(1)
url = sys.argv[1]
print(f"=== 爬虫合规探测: {url} ===")
rp = check_robots_txt(url)
html = check_security_headers(url)
check_page_legal_notice(html)
print("\n=== 探测完成 ===")
print("建议: 在正式抓取前,务必阅读目标站点的 robots.txt 和用户协议")
if __name__ == '__main__':
main()
运行示例:
python crawler_legal_check.py https://测试网站.cn
输出会告诉你:
- 目标站点有没有 robots.txt,允不允许抓取
- HTTP 响应头里有没有安全策略或限流声明
- 页面内容里有没有"禁止爬虫"之类的法律关键词
这个脚本的法律价值在于:它留下了合规审查的记录。如果你后来因爬虫问题被调查,能证明你在抓取之前做过合规检查,是一个对你有利的证据。