站点防⽌爬⾍通常涉及⼀系列技术和策略的组合。
robots.txt
`# 示例:禁止所有爬虫访问
User-agent: *
Disallow: /
# 示例:允许特定爬虫访问,禁止其他
User-agent: Googlebot
Allow: /
User-agent: *
Disallow: /`
使用 CAPTCHA
CAPTCHA 通常是在服务器端实现的,这里不直接展示代码,但通常会涉及前端表单提交时包含一个隐藏的或动态生成的验证码字段,并在服务器端验证。
检查用户代理字符串
在服务器端(以 Node.js Express 为例),您可以通过检查请求头中的 User-Agent
来决定是否接受请求:
`app.use((req, res, next) => {
const userAgent = req.headers['user-agent'];
// 检查 userAgent 是否合法或是否为已知爬虫
if (isSuspiciousUserAgent(userAgent)) {
return res.status(403).send('Access Forbidden');
}
next();
});
function isSuspiciousUserAgent(userAgent) {
// 这里实现具体的判断逻辑
// 例如,检查是否包含某些关键词
return userAgent.includes('Scrapy');
}`
分析流量行为
这通常涉及日志收集和分析,不直接通过代码实现,但可以通过设置如 Nginx 的访问日志,然后使用如 Logstash, Splunk 或自定义脚本来分析日志。
使用 Web 应用防火墙(WAF)
WAF 的配置通常不在应用代码中,而是在服务器或云服务的配置中设置。例如,在 AWS WAF 中,您可以设置自定义规则来检测和阻止恶意流量。
服务端渲染和动态 Token
服务端渲染通常涉及 JavaScript 在服务器端执行,然后将生成的 HTML 发送给客户端。动态 Token 可以在服务器端生成并嵌入到页面中:
``// 假设这是 Node.js 中的一个路由处理函数
app.get('/protected-page', (req, res) => {
const token = generateToken(); // 假设这是生成动态令牌的函数
const html = `
<html>
<body>
<h1>Protected Content</h1>
<script>
var token = '${token}'; // 注意:实际应用中应避免这种方式,以防 XSS
// 使用 token 进行其他操作
</script>
</body>
</html>
`;
res.send(html);
});``
添加额外的 HTTP 头
这通常在服务器配置中设置,如 Nginx 配置文件中添加自定义的 HTTP 头:
`server {
...
add_header X-Custom-Header "SomeValue";
...
}`
IP 黑名单
这通常结合防火墙规则或应用中的中间件来实现:
`const ipBlacklist = ['123.123.123.123', '456.456.456.456'];
app.use((req, res, next) => {
if (ipBlacklist.includes(req.ip)) {
return res.status(403).send('IP is blacklisted');
}
next();
});`
限制访问速度
这可以使用如 express-rate-limit
这样的中间件来实现:
`const rateLimit = require("express-rate-limit");
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15分钟
max: 100, // 限制每个IP每15分钟最多100次请求
});
app.use(limiter);`
API 限流
与访问速度限制类似,但可能针对 API 调用者进行更细粒度的控制。
1. 确定限流策略
首先,你需要确定你的限流策略。这通常包括:
- 时间窗口:比如每分钟、每小时或每天。
- 请求次数:在指定的时间窗口内允许的最大请求次数。
- 限流对象:根据IP地址、用户认证信息(如OAuth令牌)、API密钥等进行限流。
2. 选择限流工具或库
根据你的技术栈选择合适的限流工具或库。例如,如果你使用Node.js,你可以考虑使用express-rate-limit
这样的中间件。如果你使用的是Nginx,你可以利用Nginx的limit_req_zone
和limit_req
指令来限流。
3. 配置限流
在你的服务器或应用代码中配置限流策略。以下是一个使用express-rate-limit
的Node.js示例:
`const express = require('express');
const rateLimit = require('express-rate-limit');
const app = express();
// 创建限流器实例
// 这里以IP地址为基础,每分钟最多100次请求
const limiter = rateLimit({
windowMs: 1 * 60 * 1000, // 1分钟
max: 100, // 最多100次请求
standardHeaders: true, // 返回剩余的请求次数等头部信息
legacyHeaders: false, // 禁用旧版本的头部信息
handler: (req, res, next) => {
// 自定义的限流处理函数
res.status(429).json({
message: 'Too many requests, please try again later.',
resetTime: res.getHeader('X-RateLimit-Reset')
});
}
});
// 应用限流器到所有请求
app.use(limiter);
// 你的路由处理函数...
app.listen(3000, () => {
console.log('Server is running on port 3000');
});`
4. 监控和调整
实施限流后,你应该监控你的API使用情况,并根据需要调整限流策略。如果爬虫找到了一种绕过限流的方法,你可能需要更新你的策略或采取其他防爬措施。
5. 其他防爬措施
虽然API限流是一种有效的防爬策略,但它并不是万能的。你可能还需要结合其他措施,如:
- 检查请求头 :验证请求头中的
User-Agent
、Referer
等信息,以识别爬虫请求。 - 使用CAPTCHA:对于需要登录或提交表单的页面,使用验证码可以防止自动化脚本。
- IP黑名单:将已知的恶意IP地址加入黑名单,拒绝其访问。
- 动态内容:通过JavaScript动态加载内容,使得爬虫难以直接抓取数据。
使用 HTTPS
这通常在服务器配置中设置,如 Nginx 的 SSL/TLS 配置。
更改网站结构和内容
这通常涉及开发过程中的决策,而不是直接通过代码片段来展示。您应该定期审查和优化网站的结构和内容,以增加爬虫的抓取难度。
举例
创建一个简单的服务器,如下所示:
``const express = require('express');
const rateLimit = require('express-rate-limit');
const app = express();
const PORT = 3000;
// 创建一个简单的限流器
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15分钟
max: 100, // 限制每个IP在15分钟内最多100次请求
standardHeaders: true, // 返回剩余的请求次数等头部信息
legacyHeaders: false, // 禁用旧版本的头部信息
message: "Too many requests from this IP, please try again later" // 自定义响应消息
});
// 中间件来检查User-Agent
function checkUserAgent(req, res, next) {
const userAgent = req.headers['user-agent'];
// 这里只是简单地检查User-Agent是否包含"Bot"或"Crawler",实际情况可能需要更复杂的逻辑
if (userAgent && (userAgent.includes('Bot') || userAgent.includes('Crawler'))) {
return res.status(403).send('Access denied for bots and crawlers.');
}
next();
}
// 应用限流器和User-Agent检查中间件
app.use(limiter);
app.use(checkUserAgent);
// 定义一个简单的路由
app.get('/', (req, res) => {
res.send('Hello, World!');
});
// 启动服务器
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`);
});``
在这个例子中,我们创建了一个简单的Node.js服务器,它使用express-rate-limit
来限制每个IP地址在15分钟内的请求次数。此外,我们还定义了一个自定义中间件checkUserAgent
,用于检查请求头中的User-Agent
字符串,如果包含"Bot"或"Crawler",则拒绝访问。
然而,需要注意的是,User-Agent
是可以被伪造的,因此这种方法并不是完全可靠的。此外,一些高级爬虫可能会模拟正常的浏览器行为来绕过这种检查。