Вот и все.. конец мучениям, чекаем массово DR . Ключ берем в панельке ahrefs. ВСе бесплатно и без всяких левых сервисов.
.txt
* Каждая запись — одна строка формата: d.m.Y\tDR\n
* Запись выполняется ТОЛЬКО если:
* - файла ещё нет (первая проверка), ИЛИ
* - DR изменился по сравнению с последней записью в файле.
*
* Требования:
* - PHP 7.4+ с расширением cURL
* - Бесплатный API-ключ Ahrefs
*/
// ================= НАСТРОЙКИ =================
$ahrefsApiKey = 'ВАШ_API_КЛЮЧ_AHREFS'; // Замените на ваш ключ
$domainsFile = __DIR__ . '/domains.txt'; // Путь к файлу со списком доменов
$dataDir = __DIR__ . '/data'; // Папка для результатов
$drVersion = 'dr3'; // dr3 или dr4
$pauseMs = 300; // Пауза между запросами (мс)
// =============================================
/**
* Читает домены из файла, очищает и валидирует их.
*
* @return array{valid: string[], invalid: array}
*/
function readDomainsFromFile(string $filePath): array
{
if (!is_readable($filePath)) {
fwrite(STDERR, "Не удалось прочитать файл: {$filePath}\n");
exit(1);
}
$valid = [];
$invalid = [];
$seen = [];
$lineNo = 0;
$handle = fopen($filePath, 'r');
if ($handle === false) {
fwrite(STDERR, "Не удалось открыть файл: {$filePath}\n");
exit(1);
}
while (($line = fgets($handle)) !== false) {
$lineNo++;
$line = trim($line);
if ($line === '' || $line[0] === '#') {
continue;
}
$domain = preg_replace('#^https?://#i', '', $line);
$domain = rtrim($domain, '/');
$domain = strtolower($domain);
if (!preg_match('/^(?=.{1,253}$)(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z]{2,63}$/', $domain)) {
$invalid[] = ['line' => $lineNo, 'value' => $line];
continue;
}
if (isset($seen[$domain])) {
continue;
}
$seen[$domain] = true;
$valid[] = $domain;
}
fclose($handle);
return ['valid' => $valid, 'invalid' => $invalid];
}
/**
* Получает DR для одного домена.
*
* @return array{success: bool, domain_rating: float|null, error: string|null}
*/
function getDomainRating(string $domain, string $apiKey, string $version = 'dr3'): array
{
$url = 'https://api.ahrefs.com/v3/public/domain-rating-free?' . http_build_query([
'target' => $domain,
'version' => $version,
'output' => 'json',
]);
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $apiKey,
'Accept: application/json',
],
CURLOPT_TIMEOUT => 15,
CURLOPT_SSL_VERIFYPEER => true,
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$curlError = curl_error($ch);
curl_close($ch);
if ($curlError) {
return ['success' => false, 'domain_rating' => null, 'error' => 'cURL: ' . $curlError];
}
$data = json_decode($response, true);
if ($httpCode === 429) {
return ['success' => false, 'domain_rating' => null, 'error' => 'HTTP 429 (превышен лимит запросов)'];
}
if ($httpCode !== 200) {
$errorMsg = $data['error'] ?? "HTTP $httpCode";
return ['success' => false, 'domain_rating' => null, 'error' => $errorMsg];
}
if (!isset($data['domain_rating']['domain_rating'])) {
return ['success' => false, 'domain_rating' => null, 'error' => 'Некорректный ответ API'];
}
return [
'success' => true,
'domain_rating' => (float) $data['domain_rating']['domain_rating'],
'error' => null,
];
}
/**
* Возвращает последнее сохранённое значение DR из файла домена,
* либо null, если файла нет или в нём нет валидной записи.
*/
function getLastStoredDr(string $filePath): ?float
{
if (!is_file($filePath) || !is_readable($filePath)) {
return null;
}
$lines = file($filePath, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
if ($lines === false || empty($lines)) {
return null;
}
$last = trim(end($lines));
// Ожидаемый формат: d.m.YDR
if (!preg_match('/^\d{2}\.\d{2}\.\d{4}\t([0-9]+(?:\.[0-9]+)?)$/', $last, $m)) {
return null;
}
return (float) $m[1];
}
/**
* Форматирует DR для записи в файл: один знак после точки, без хвостовых нулей.
*/
function formatDr(float $dr): string
{
return rtrim(rtrim(number_format($dr, 1, '.', ''), '0'), '.');
}
/**
* Дописывает строку результата в файл домена, только если DR изменился
* или файла ещё нет.
*
* @return string 'created' | 'updated' | 'unchanged'
*/
function saveIfChanged(string $dataDir, string $domain, float $dr): string
{
$filePath = $dataDir . DIRECTORY_SEPARATOR . $domain . '.txt';
$lastDr = getLastStoredDr($filePath);
if ($lastDr !== null && abs($lastDr - $dr) < 1e-9) {
return 'unchanged';
}
$line = date('d.m.Y') . "\t" . formatDr($dr) . "\n";
if (file_put_contents($filePath, $line, FILE_APPEND | LOCK_EX) === false) {
throw new RuntimeException("Не удалось записать в файл: {$filePath}");
}
return $lastDr === null ? 'created' : 'updated';
}
// ================= ВЫПОЛНЕНИЕ =================
if (!is_dir($dataDir)) {
if (!mkdir($dataDir, 0755, true) && !is_dir($dataDir)) {
fwrite(STDERR, "Не удалось создать папку: {$dataDir}\n");
exit(1);
}
}
$parsed = readDomainsFromFile($domainsFile);
if (!empty($parsed['invalid'])) {
echo "Пропущены некорректные строки:\n";
foreach ($parsed['invalid'] as $bad) {
echo " строка {$bad['line']}: \"{$bad['value']}\"\n";
}
echo "\n";
}
$domains = $parsed['valid'];
$total = count($domains);
if ($total === 0) {
echo "В файле {$domainsFile} не найдено валидных доменов.\n";
exit(0);
}
echo "Проверка Domain Rating (версия: {$drVersion})\n";
echo "Доменов к проверке: {$total}\n";
echo "Папка результатов: {$dataDir}\n";
echo str_repeat('-', 80) . "\n";
printf("%-38s | %-8s | %s\n", 'Домен', 'DR', 'Действие');
echo str_repeat('-', 80) . "\n";
$stats = ['created' => 0, 'updated' => 0, 'unchanged' => 0, 'error' => 0];
foreach ($domains as $i => $domain) {
$result = getDomainRating($domain, $ahrefsApiKey, $drVersion);
if (!$result['success']) {
$stats['error']++;
printf("%-38s | %-8s | Ошибка: %s\n", $domain, '-', $result['error']);
} else {
try {
$action = saveIfChanged($dataDir, $domain, $result['domain_rating']);
$stats[$action]++;
$labels = [
'created' => 'записано (первая проверка)',
'updated' => 'записано (DR изменился)',
'unchanged' => 'пропущено (DR не изменился)',
];
printf("%-38s | %-8s | %s\n", $domain, formatDr($result['domain_rating']), $labels[$action]);
} catch (RuntimeException $e) {
$stats['error']++;
printf("%-38s | %-8s | Ошибка записи: %s\n", $domain, formatDr($result['domain_rating']), $e->getMessage());
}
}
if ($i < $total - 1 && $pauseMs > 0) {
usleep($pauseMs * 1000);
}
}
echo str_repeat('-', 80) . "\n";
echo "Итоги:\n";
echo " новых файлов создано: {$stats['created']}\n";
echo " обновлено (DR изменился): {$stats['updated']}\n";
echo " без изменений (пропущено): {$stats['unchanged']}\n";
echo " ошибок: {$stats['error']}\n";