seotools

200) { http_response_code(429); die('

Rate limit reached. Try later.

'); } // ---------------------- helpers ---------------------- function safe_url($url) { $url = trim($url); if (!preg_match('#^https?://#i', $url)) return false; $parts = parse_url($url); if (!$parts || !isset($parts['host'])) return false; $host = $parts['host']; // resolve host IP and refuse private ranges $ip = gethostbyname($host); if (!$ip) return false; $private_prefixes = ['10.', '172.16.', '172.17.', '172.18.', '172.19.', '172.20.', '172.21.', '172.22.', '172.23.', '172.24.', '172.25.', '172.26.', '172.27.', '172.28.', '172.29.', '172.30.', '172.31.', '192.168.', '127.']; foreach ($private_prefixes as $p) { if (strpos($ip, $p) === 0) return false; } return $url; } function fetch_url($url, &$info=null) { $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); curl_setopt($ch, CURLOPT_USERAGENT, 'MiniSEO/1.0 (+https://example.com)'); curl_setopt($ch, CURLOPT_TIMEOUT, 15); curl_setopt($ch, CURLOPT_HEADER, true); $start = microtime(true); $resp = curl_exec($ch); $end = microtime(true); $info = curl_getinfo($ch); $info['time_total_calc'] = $end - $start; curl_close($ch); if ($resp === false) return false; $header_size = $info['header_size'] ?? 0; $headers = substr($resp, 0, $header_size); $body = substr($resp, $header_size); return ['headers'=>$headers, 'body'=>$body, 'info'=>$info]; } function extract_onpage($html) { $out = ['title'=>'','meta_description'=>'','h1'=>[],'links'=>[]]; libxml_use_internal_errors(true); $dom = new DOMDocument(); $dom->loadHTML(mb_convert_encoding($html,'HTML-ENTITIES','UTF-8')); $titles = $dom->getElementsByTagName('title'); if ($titles->length) $out['title'] = trim($titles->item(0)->textContent); $metas = $dom->getElementsByTagName('meta'); foreach ($metas as $m) { $name = strtolower($m->getAttribute('name')); $prop = strtolower($m->getAttribute('property')); if ($name == 'description' || $prop == 'og:description') { $out['meta_description'] = trim($m->getAttribute('content')); break; } } $h1s = $dom->getElementsByTagName('h1'); foreach ($h1s as $h) $out['h1'][] = trim($h->textContent); // links $anchors = $dom->getElementsByTagName('a'); foreach ($anchors as $a) { $href = trim($a->getAttribute('href')); $text = trim($a->textContent); if ($href == '') continue; $out['links'][] = ['href'=>$href, 'text'=>$text]; } return $out; } function keyword_density($text, $top=20) { $text = mb_strtolower($text,'UTF-8'); $text = preg_replace('/<[^>]+>/', ' ', $text); $text = preg_replace('/[\\p{P}\\p{S}]+/u', ' ', $text); $words = preg_split('/\\s+/u', $text, -1, PREG_SPLIT_NO_EMPTY); $total = count($words); $stopwords_arr = array_map('trim', explode(',', 'the,of,and,to,in,a,is,that,it,for,on,with,as,are,was,be,by,or,an')); $stopwords=[]; foreach ($stopwords_arr as $s) $stopwords[$s]=true; $counts=[]; foreach ($words as $w) { $w = trim($w); if ($w=='' || isset($stopwords[$w])) continue; if (!isset($counts[$w])) $counts[$w]=0; $counts[$w]++; } arsort($counts); $result=[]; $i=0; foreach ($counts as $k=>$v) { $result[]=['word'=>$k,'count'=>$v, 'density'=> ($total>0?round(100*$v/$total,3):0)]; $i++; if ($i>=$top) break; } return ['total_words'=>$total,'top'=>$result]; } function save_result($tool, $input, $result) { $id = time().'_'.bin2hex(random_bytes(4)); $file = DATA_DIR . '/' . $id . '.json'; $obj = ['id'=>$id,'tool'=>$tool,'input'=>$input,'result'=>$result,'created'=>date('c')]; file_put_contents($file, json_encode($obj, JSON_PRETTY_PRINT|JSON_UNESCAPED_UNICODE)); return $id; } function load_result($id) { $file = DATA_DIR . '/' . $id . '.json'; if (!file_exists($file)) return false; return json_decode(file_get_contents($file), true); } function list_results($limit=50) { $files = glob(DATA_DIR . '/*.json'); usort($files, function($a,$b){ return filemtime($b)-filemtime($a); }); $files = array_slice($files,0,$limit); $out=[]; foreach ($files as $f) $out[] = json_decode(file_get_contents($f), true); return $out; } // ---------------------- routing & UI ---------------------- $action = $_REQUEST['action'] ?? 'home'; ?> SEO Tools — أدوات سيو متكاملة (MVP)

SEO Tools — أدوات سيو متكاملة (MVP)

مقدمة سريعة

هذه نسخة MVP من منصة أدوات SEO. اختر أداة من أعلى أو استخدم الواجهة لتشغيل التحليلات. النتائج تحفظ مؤقتاً في مجلد data/.

  • تحسين أمني: تمنع الطلبات إلى عناوين داخلية (SSRF protection).
  • قابلة للتوسيع: يمكنك تحويلها لاحقاً إلى نظام Laravel مع Queue وAuth.

تحليل صفحة (On-page Analyzer)

رابط غير صالح أو ممنوع (محلي/خاص).

'; else { $res = fetch_url($safe, $info); if (!$res) echo '

فشل جلب الصفحة.

'; else { $on = extract_onpage($res['body']); $saved = save_result('onpage', ['url'=>$safe], ['info'=>$info, 'onpage'=>$on]); echo '

النتيجة

'; echo '

HTTP: '.htmlspecialchars($info['http_code']).' — زمن الاستجابة: '.round($info['time_total_calc'],3).'s

'; echo '

العنوان: '.htmlspecialchars($on['title']).'

'; echo '

Meta description: '.htmlspecialchars($on['meta_description']).'

'; echo '

H1(s):

    '; foreach ($on['h1'] as $h) echo '
  • '.htmlspecialchars($h).'
  • '; echo '
'; echo '

رؤية النتيجة المحفوظة

'; } } } ?>

كثافة الكلمات (Keyword Density)

رابط غير صالح.

'; else { $res = fetch_url($safe,$info); if (!$res) echo '

فشل جلب الصفحة.

'; else $content = strip_tags($res['body']); } } else $content = $input; if ($content) { $kd = keyword_density($content,$top); $id = save_result('density', ['input'=>$input,'top'=>$top], $kd); echo '

مجموع الكلمات: '.htmlspecialchars($kd['total_words']).'

'; echo ''; foreach ($kd['top'] as $r) { echo ''; } echo '
الكلمةالعددالنسبة (%)
'.htmlspecialchars($r['word']).''.htmlspecialchars($r['count']).''.htmlspecialchars($r['density']).'
'; echo '

رؤية النتيجة المحفوظة

'; } } ?>

استخراج الروابط داخل الصفحة (داخلية / خارجية)

رابط غير صالح.

'; else { $res = fetch_url($safe,$info); if (!$res) echo '

فشل جلب الصفحة.

'; else { $on = extract_onpage($res['body']); // classify links $parsed = parse_url($safe); $host = $parsed['host'] ?? ''; $internal=[]; $external=[]; foreach ($on['links'] as $l) { $href = $l['href']; // normalise relative if (strpos($href,'//')===0) $href = $parsed['scheme'] . ':' . $href; if (!preg_match('#^https?://#i',$href)) { // build absolute $base = $parsed['scheme'].'://'.$host; $href = rtrim($base,'/').'/'.ltrim($href,'/'); } $hparts = parse_url($href); $hhost = $hparts['host'] ?? ''; if ($hhost === $host) $internal[] = $href; else $external[] = $href; } $resid = save_result('links', ['url'=>$safe], ['internal'=>$internal,'external'=>$external]); echo '

روابط داخلية: '.count($internal).' — روابط خارجية: '.count($external).'

'; echo '
عرض روابط داخلية
'.htmlspecialchars(implode(\"\\n\",array_slice(array_unique($internal),0,200))).'
'; echo '
عرض روابط خارجية
'.htmlspecialchars(implode(\"\\n\",array_slice(array_unique($external),0,200))).'
'; echo '

رؤية النتيجة المحفوظة

'; } } } ?>

فحص robots.txt

دومين غير صالح.

'; else { $res = fetch_url($safe,$info); if (!$res) echo '

لا يوجد robots.txt أو فشل الوصول.

'; else { $id = save_result('robots', ['domain'=>$d], ['body'=>$res['body']]); echo '

محتوى robots.txt

'.htmlspecialchars($res['body']).'
'; echo '

حفظ النتيجة

'; } } } ?>

فحص sitemap.xml

رابط غير صالح.

'; else { $res = fetch_url($safe,$info); if (!$res) echo '

فشل جلب الـ sitemap.

'; else { // extract urls from sitemap preg_match_all('/(.*?)<\\/loc>/i', $res['body'], $m); $urls = $m[1] ?? []; $id = save_result('sitemap', ['surl'=>$safe], ['count'=>count($urls),'urls'=>$urls]); echo '

عدد الروابط في sitemap: '.count($urls).'

'; echo '
عرض الروابط (حتى 200)
'.htmlspecialchars(implode(\"\\n\",array_slice($urls,0,200))).'
'; echo '

رؤية النتيجة

'; } } } ?>

فحص جماعي (Bulk URL Checker)

أدخل قائمة عناوين (واحد في كل سطر). السكربت سيجري فحص GET لكل رابط ويعيد حالة HTTP ووقت الاستجابة. للمواقع الكبيرة استخدم نسخة سيرفرية مع Queue حقيقية.

'invalid_or_private']; continue; } $res = fetch_url($safe, $info); if (!$res) { $results[$l]=['error'=>'fetch_failed']; continue; } $results[$l]=['http'=>$info['http_code'] ?? 0,'time'=>round($info['time_total_calc'],3)]; // small sleep to be polite usleep(200000); } $id = save_result('bulk', ['count'=>count($lines)], $results); echo '

تم الفحص — النتائج: '.count($results).'

'; echo '
'.htmlspecialchars(json_encode($results, JSON_PRETTY_PRINT|JSON_UNESCAPED_UNICODE)).'
'; echo '

حفظ النتيجة

'; } ?>

النتائج المحفوظة

لا توجد نتائج محفوظة حتى الآن.

'; else { echo '
    '; foreach ($all as $r) { echo '
  • '.htmlspecialchars($r['tool']).' — '.htmlspecialchars($r['created']).' — عرض
  • '; } echo '
'; } ?>

لم يتم العثور على النتيجة.

'; else { ?>

نتيجة —

وقت الإنشاء:

عودة

ملاحظة: هذه أداة تعليمية/أولية. لتحويلها لمنصة احترافية نحتاج قاعدة بيانات، نظام مستخدمين واشتراكات، Redis queues، وتحسين أمني إضافي.

Comments