Releases: smmnn/anti-scraper
Releases · smmnn/anti-scraper
Release list
anti-scraper.php
1,
'rate_limit' => 1,
'max_requests' => 30,
'time_window' => 60,
'disable_right_click' => 1,
'disable_text_selection' => 1,
'block_headless_browsers' => 1,
'custom_user_agents' => "example-bot\nbad-bot"
);
// 仅在无配置时添加,避免覆盖已有设置
if (!get_option('anti_scraper_options')) {
add_option('anti_scraper_options', $default_options);
}
}
// 插件停用时的操作
register_deactivation_hook(__FILE__, 'anti_scraper_deactivate');
function anti_scraper_deactivate() {
// 保留配置供下次使用,如需清理可取消注释
// delete_option('anti_scraper_options');
}
// 添加管理菜单(中文)
add_action('admin_menu', 'anti_scraper_add_admin_menu');
function anti_scraper_add_admin_menu() {
add_options_page(
'防爬虫设置',
'防爬虫防护',
'manage_options',
'anti-scraper',
'anti_scraper_render_settings_page'
);
}
// 注册设置
add_action('admin_init', 'anti_scraper_register_settings');
function anti_scraper_register_settings() {
register_setting('anti_scraper_group', 'anti_scraper_options', 'anti_scraper_sanitize_options');
}
// 验证和清理设置
function anti_scraper_sanitize_options($input) {
$output = array();
// 布尔值处理
$output['block_common_bots'] = isset($input['block_common_bots']) ? 1 : 0;
$output['rate_limit'] = isset($input['rate_limit']) ? 1 : 0;
$output['disable_right_click'] = isset($input['disable_right_click']) ? 1 : 0;
$output['disable_text_selection'] = isset($input['disable_text_selection']) ? 1 : 0;
$output['block_headless_browsers'] = isset($input['block_headless_browsers']) ? 1 : 0;
// 数值范围限制
$output['max_requests'] = isset($input['max_requests']) ? intval($input['max_requests']) : 30;
$output['max_requests'] = max(1, min(1000, $output['max_requests']));
$output['time_window'] = isset($input['time_window']) ? intval($input['time_window']) : 60;
$output['time_window'] = max(10, min(3600, $output['time_window']));
// 文本域清洗
$output['custom_user_agents'] = isset($input['custom_user_agents']) ? sanitize_textarea_field($input['custom_user_agents']) : '';
return $output;
}
// 渲染设置页面(中文)
function anti_scraper_render_settings_page() {
if (!current_user_can('manage_options')) {
wp_die(__('你没有足够的权限访问此页面。'));
}
$options = get_option('anti_scraper_options');
?>
Read more
<div class="wrap">
<h1>防爬虫防护设置</h1>
<form method="post" action="options.php">
<?php settings_fields('anti_scraper_group'); ?>
<table class="form-table">
<tr>
<th scope="row"><label for="block_common_bots">阻止恶意爬虫</label></th>
<td>
<input type="checkbox" id="block_common_bots" name="anti_scraper_options[block_common_bots]"
value="1" <?php checked(1, $options['block_common_bots']); ?>>
<p class="description">仅阻止恶意爬虫(已豁免百度/谷歌/必应等合法搜索引擎)</p>
</td>
</tr>
<tr>
<th scope="row"><label for="block_headless_browsers">阻止无头浏览器</label></th>
<td>
<input type="checkbox" id="block_headless_browsers" name="anti_scraper_options[block_headless_browsers]"
value="1" <?php checked(1, $options['block_headless_browsers']); ?>>
<p class="description">阻止无头浏览器(如Headless Chrome),常用于批量抓取内容</p>
</td>
</tr>
<tr>
<th scope="row"><label for="rate_limit">启用访问频率限制</label></th>
<td>
<input type="checkbox" id="rate_limit" name="anti_scraper_options[rate_limit]"
value="1" <?php checked(1, $options['rate_limit']); ?>>
<p class="description">限制同一IP的访问频率,防止快速批量抓取</p>
</td>
</tr>
<tr>
<th scope="row"><label for="max_requests">最大请求数</label></th>
<td>
<input type="number" id="max_requests" name="anti_scraper_options[max_requests]"
value="<?php echo esc_attr($options['max_requests']); ?>" min="1" max="1000">
<p class="description">在指定时间窗口内允许的最大请求数(建议30-100)</p>
</td>
</tr>
<tr>
<th scope="row"><label for="time_window">时间窗口(秒)</label></th>
<td>
<input type="number" id="time_window" name="anti_scraper_options[time_window]"
value="<?php echo esc_attr($options['time_window']); ?>" min="10" max="3600">
<p class="description">请求计数的时间窗口(建议60-300秒)</p>
</td>
</tr>
<tr>
<th scope="row"><label for="disable_right_click">禁用右键菜单</label></th>
<td>
<input type="checkbox" id="disable_right_click" name="anti_scraper_options[disable_right_click]"
value="1" <?php checked(1, $options['disable_right_click']); ?>>
<p class="description">防止普通用户通过右键复制内容(可被技术手段绕过)</p>
</td>
</tr>
<tr>
<th scope="row"><label for="disable_text_selection">禁用文本选择</label></th>
<td>
<input type="checkbox" id="disable_text_selection" name="anti_scraper_options[disable_text_selection]"
value="1" <?php checked(1, $options['disable_text_selection']); ?>>
<p class="description">防止普通用户选择/复制文本(可被技术手段绕过)</p>
</td>
</tr>
<tr>
<th scope="row"><label for="custom_user_agents">自定义要阻止的User-Agent</label></th>
<td>
<textarea id="custom_user_agents" name="anti_scraper_options[custom_user_agents]"
rows="5" cols="50"><?php echo esc_textarea($options['custom_user_agents']); ?></textarea>
<p class="description">每行一个User-Agent关键词,将阻止包含这些关键词的请求</p>
</td>
</tr>
</table>
<?php submit_button('保存设置'); ?>
</form>
<div style="margin-top:20px; padding:10px; background:#f1f1f1; border-left:4px solid #2196F3;">
<h3>使用提示</h3>
<ul>
<li>该插件仅能防护基础爬虫,无法阻止专业级爬虫(如定制化爬虫)</li>
<li>如需配置可信代理IP段,请修改插件中 <code>anti_scraper_get_user_ip</code> 函数内的 <code>$trusted_proxies</code> 数组</li>
<li>拦截日志可在WordPress后台「工具→站点健康→日志」中查看PHP错误日志</li>
</ul>
</div>
</div>
<?php
}
// 核心防护功能
add_action('init', 'anti_scraper_protect_content');
function anti_scraper_protect_content() {
// 不限制管理员
if (current_user_can('manage_options')) {
return;
}
$options = get_option('anti_scraper_options');
// 1. 阻止恶意爬虫(豁免搜索引擎)
if ($options['block_common_bots']) {
anti_scraper_block_common_bots();
}
// 2. 阻止无头浏览器
if ($options['block_headless_browsers']) {
anti_scraper_block_headless_browsers();
}
// 3. 阻止自定义User-Agent
if (!empty($options['custom_user_agents'])) {
anti_scraper_block_custom_user_agents($options['custom_user_agents']);
}
// 4. 访问频率限制
if ($options['rate_limit']) {
anti_scraper_enforce_rate_limit($options['max_requests'], $options['time_window']);
}
}
// 阻止恶意爬虫(修复:豁免合法搜索引擎)
function anti_scraper_block_common_bots() {
$user_agent = $_SERVER['HTTP_USER_AGENT'] ?? '';
// 合法搜索引擎爬虫白名单(核心修复:避免误封SEO)
$whitelist_bots = array(
'BaiduSpider', // 百度
'Googlebot', // 谷歌
'Bingbot', // 必应
'360Spider', // 360搜索
'Sogou Spider', // 搜狗
'YisouSpider', // 神马搜索
'YandexBot', // 俄罗斯Yandex
'DuckDuckBot' // DuckDuckGo
);
// 先检查白名单,命中则直接放行
foreach ($whitelist_bots as $white_bot) {
if (stripos($user_agent, $white_bot) !== false) {
return;
}
}
// 仅拦截恶意爬虫关键词(剔除合法的bot/crawl等)
$malicious_bot_keywords = array(
'scraper', 'grabber', 'harvest', 'parser', 'worm',
'linkchecker', 'webzip', 'teleport', 'httrack', 'offline'
);
foreach ($malicious_bot_keywords as $keyword) {
if (stripos($user_agent, $keyword) !== false) {
anti_scraper_block_request('恶意爬虫关键词匹配: ' . $keyword);
}
}
}
// 阻止无头浏览器
function anti_scraper_block_headless_browsers() {
$user_agent = $_SERVER['HTTP_USER_AGENT'] ?? '';
$headless_indicators = array(
'HeadlessChrome',
'PhantomJS',
'Selenium',
'webdriver',
'puppeteer'
);
foreach ($headless_indicators as $indicator) {
if (stripos($user_agent, $indicator) !== false) {
...