SEO , Web Development • 8 λεπτά ανάγνωση Δημιουργία ενός SEO Spider με το Puppeteer Posted by Παναγιώτης 23 Απριλίου, 2025 Κατά τη διάρκεια της θητείας μου στην Double Dot,είχα την ευκαιρία να παρατηρήσω στενά τους συναδέλφους μου καθώς περιηγούνταν στον κόσμο των εργαλείων SEO. Τους είδα να χρησιμοποιούν κορυφαία εργαλεία όπως το Screaming Frog για crawling, εξαγωγή metadata, εντοπισμό broken links, και διεξαγωγή λεπτομερών audits σε ιστοσελίδες. Ήταν συναρπαστικό να βλέπω πώς αυτά τα εργαλεία μπορούσαν να παρέχουν μια εις βάθος ματιά στη δομή και την απόδοση ενός ιστότοπου. Ωστόσο, ως κάποιος που αγαπά να πειραματίζεται και να χτίζει πράγματα από την αρχή, βρέθηκα να σκέφτομαι: “Τι θα γινόταν αν μπορούσα να φτιάξω κάτι παρόμοιο;” Εμπνευσμένος από αυτή την περιέργεια και το ενδιαφέρον μου για την αυτοματοποίηση εργασιών SEO, αποφάσισα να δοκιμάσω να δημιουργήσω το δικό μου SEO Spider χρησιμοποιώντας το Puppeteer. Ο στόχος ήταν να αντιγράψω ορισμένες από τις βασικές λειτουργίες εργαλείων όπως το Screaming Frog, εστιάζοντας σε εργασίες όπως το crawling ιστοσελίδων, η εξαγωγή SEO metadata και ο έλεγχος για προβλήματα όπως broken links και redirects. Σε αυτόν τον οδηγό, θα σας καθοδηγήσω στο πώς έφτιαξα αυτό το απλό SEO Spider με το Puppeteer. Μέχρι το τέλος αυτού του έργου, θα έχετε ένα εργαλείο που μπορεί: Να εξάγει Title & Meta Descriptions Να ελέγχει τα Canonical & Open Graph Tags Να αναλύει τη Δομή H1-H6 Να εντοπίζει Broken Links & Redirects Ας δούμε πώς μπορείτε να φτιάξετε το δικό σας SEO Spider από το μηδέν! 1. Εγκατάσταση του Puppeteer Πριν ξεκινήσουμε να γράφουμε το σενάριο, πρέπει να εγκαταστήσουμε το Puppeteer, το οποίο είναι μια βιβλιοθήκη Node.js που μας επιτρέπει να ελέγχουμε headless Chrome ή Chromium browsers. Το Puppeteer μπορεί να προσομοιώσει τις ενέργειες του χρήστη σε μια ιστοσελίδα, καθιστώντας το ιδανικό για εργασίες SEO όπως το crawling και η εξαγωγή δεδομένων. Για να ξεκινήσετε, εγκαταστήστε το Puppeteer χρησιμοποιώντας το npm: npm install puppeteer Μετά την εγκατάσταση του Puppeteer, δημιουργήστε ένα νέο αρχείο με όνομα index.js. Εδώ θα γράψουμε το σενάριό μας για να αλληλεπιδράσουμε με τις ιστοσελίδες και να εξαγάγουμε τα δεδομένα SEO. Για να εκτελέσουμε το σενάριο, απλά πρέπει να πληκτρολογήσουμε: npm index.js 2. Εξαγωγή SEO Metadata Ένα βασικό μέρος του ελέγχου SEO είναι η συλλογή metadata όπως title tags, meta descriptions, canonical URLs και Open Graph tags. Αυτά είναι απαραίτητα για την κατανόηση του τρόπου με τον οποίο οι μηχανές αναζήτησης αντιλαμβάνονται μια σελίδα. Δείτε πώς μπορούμε να εξαγάγουμε αυτά τα metadata χρησιμοποιώντας το Puppeteer. Αυτό το σενάριο πλοηγείται σε μια ιστοσελίδα, συλλέγει βασικά δεδομένα SEO και στη συνέχεια τα καταγράφει στην κονσόλα: const puppeteer = require("puppeteer"); (async () => { const browser = await puppeteer.launch(); const page = await browser.newPage(); await page.goto("https://wearedoubledot.com", { waitUntil: "domcontentloaded", }); const seoData = await page.evaluate(() => { return { canonical: document.querySelector('link[rel="canonical"]')?.href || "No Canonical", title: document.title || "No Title", metaDescription: document.querySelector('meta[name="description"]')?.content || "No Meta Description", openGraphTitle: document.querySelector('meta[property="og:title"]')?.content || "No OG Title", openGraphImage: document.querySelector('meta[property="og:image"]')?.content || "No OG Image", }; }); console.log("Extracted SEO Data:", seoData); await browser.close(); })(); Στο παραπάνω απόσπασμα κώδικα: document.querySelector('link[rel="canonical"]')?.href: Συλλαμβάνει το canonical URL. document.title: Εξάγει τον τίτλο της σελίδας. document.querySelector('meta[name="description"]')?.content: Λαμβάνει τη meta description. document.querySelector('meta[property="og:title"]')?.content: Ανακτά τον τίτλο Open Graph. document.querySelector('meta[property="og:image"]')?.content: Λαμβάνει το URL της εικόνας Open Graph. Αυτό το σενάριο διασφαλίζει ότι μπορούμε εύκολα να εξαγάγουμε βασικά metadata από οποιαδήποτε ιστοσελίδα. 3. Crawling Πολλαπλών Σελίδων και Ανάλυση της Δομής H1-H6 Ενώ το crawling μιας μόνο σελίδας είναι χρήσιμο, οι έλεγχοι SEO απαιτούν συνήθως το crawling πολλαπλών σελίδων ενός ιστότοπου για να διασφαλιστεί η συνέπεια σε ολόκληρο τον ιστότοπο. Για να το κάνουμε αυτό, πρέπει να ανακτήσουμε δυναμικά όλους τους εσωτερικούς συνδέσμους αντί να ορίσουμε χειροκίνητα μια λίστα URLs. Σε πραγματικά σενάρια, η σκληρή κωδικοποίηση των URLs δεν είναι πρακτική. Αντίθετα, θα πρέπει να ξεκινήσουμε από μια σελίδα προορισμού, να εξαγάγουμε όλους τους εσωτερικούς συνδέσμους και να τους κάνουμε crawl αναδρομικά. Ωστόσο, για λόγους απλότητας σε αυτό το παράδειγμα, θα χρησιμοποιήσουμε μια στατική λίστα URLs. Δείτε πώς μπορούμε να επεκτείνουμε το σενάριό μας για να χειριστούμε πολλαπλές σελίδες: const puppeteer = require("puppeteer"); const urls = [ "https://wearedoubledot.com", "https://wearedoubledot.com/stories", "https://wearedoubledot.com/who-we-are", ]; (async () => { const browser = await puppeteer.launch(); const page = await browser.newPage(); for (let url of urls) { await page.goto(url, { waitUntil: "domcontentloaded" }); const seoData = await page.evaluate(() => { let headings = {}; document.querySelectorAll("h1, h2, h3, h4, h5, h6").forEach((h) => { if (!headings[h.tagName]) { headings[h.tagName] = []; } headings[h.tagName].push(h.innerText.trim()); }); const sortedHeadings = Object.keys(headings) .sort((a, b) => { const order = { H1: 1, H2: 2, H3: 3, H4: 4, H5: 5, H6: 6 }; return order[a] - order[b]; }) .reduce((obj, key) => { obj[key] = headings[key]; return obj; }, {}); headings = sortedHeadings; return { canonical: document.querySelector('link[rel="canonical"]')?.href || "No Canonical", title: document.title || "No Title", metaDescription: document.querySelector('meta[name="description"]') ?.content || "No Meta Description", openGraphTitle: document.querySelector('meta[property="og:title"]') ?.content || "No OG Title", openGraphImage: document.querySelector('meta[property="og:image"]') ?.content || "No OG Image", headings, }; }); console.log(`SEO Data for ${url}:`, seoData); } await browser.close(); })(); Επεξήγηση Ορίζουμε ένα πίνακα urls που περιέχει τα URLs των σελίδων που θέλουμε να κάνουμε crawl. Το σενάριο στη συνέχεια επαναλαμβάνει κάθε URL, ανοίγει τη σελίδα, εξάγει τα metadata SEO και τα καταγράφει. Προσθέσαμε επίσης λειτουργικότητα στον κώδικα που εξάγει αποτελεσματικά τις επικεφαλίδες από τη σελίδα, τις οργανώνει ανά tag και διασφαλίζει ότι παρουσιάζονται στη σωστή ιεραρχική σειρά (H1, H2, H3, κ.λπ.). Δυναμική Εξαγωγή Εσωτερικών Συνδέσμων Εάν θέλαμε να δημιουργήσουμε δυναμικά τη λίστα των URLs αντί να χρησιμοποιήσουμε έναν στατικό πίνακα, θα μπορούσαμε να εξαγάγουμε όλους τους εσωτερικούς συνδέσμους από τη σελίδα προορισμού και να τους κάνουμε crawl αναδρομικά. Για να επιτύχουμε αυτό, θα ορίζαμε μια συνάρτηση crawlPage(), η οποία θα: Βρίσκει όλους τους εσωτερικούς συνδέσμους χρησιμοποιώντας: const links = await page.evaluate(() => { return Array.from(document.querySelectorAll('a')) .map(link => link.href) .filter(href => href.startsWith(window.location.origin)); }); Επαναλαμβάνει τους εξαγόμενους συνδέσμους και καλεί αναδρομικά το crawlPage(page, currentUrl) για καθέναν (currentUrl). Αυτή η προσέγγιση διασφαλίζει ότι το SEO Spider μας ανακαλύπτει και ελέγχει δυναμικά όλες τις σελίδες μέσα σε έναν ιστότοπο, καθιστώντας το πιο πρακτικό για την ανάλυση SEO στον πραγματικό κόσμο. 4. Εντοπισμός Broken Links & Redirects Τα broken links και περιττά redirects μπορούν να επηρεάσουν σημαντικά το SEO ενός ιστότοπου. Ας επεκτείνουμε το spider μας για να ελέγξουμε για broken links και redirects. (async () => { const browser = await puppeteer.launch(); const page = await browser.newPage(); await page.goto("https://wearedoubledot.com", { waitUntil: "domcontentloaded", }); const links = await page.evaluate(() => { return Array.from(document.querySelectorAll("a")).map( (link) => link.href ); }); console.log(`Checking ${links.length} links...`); for (let link of links) { if (link.includes("mailto:") || link.includes("tel:")) { console.log(`Skipping link: ${link}`); continue; } try { const response = await page.goto(link, { waitUntil: "domcontentloaded", }); console.log(`${link} -> Status: ${response.status()}`); } catch (error) { console.log(`${link} -> Error: ${error.message}`); } } await browser.close(); })(); Επεξήγηση: Χρησιμοποιούμε το document.querySelectorAll('a') για να συλλέξουμε όλα τα στοιχεία <a> στη σελίδα και να εξαγάγουμε το χαρακτηριστικό href τους (το URL). Στη συνέχεια, επισκεπτόμαστε κάθε σύνδεσμο, ελέγχουμε την κατάσταση HTTP του και καταγράφουμε το αποτέλεσμα. Εάν υπάρχει πρόβλημα με τον σύνδεσμο, όπως σφάλμα 404 ή redirect, θα καταγραφεί και θα καταγραφεί. Αυτός είναι ένας εξαιρετικός τρόπος για να εντοπιστούν broken links και redirects που θα μπορούσαν να επηρεάσουν την εμπειρία του χρήστη και το SEO. 5. Συνδυάζοντας τα Πάντα: Το Πλήρες SEO Spider Τώρα, ας συνδυάσουμε όλα όσα έχουμε δημιουργήσει σε ένα ενιαίο ισχυρό SEO Spider που κάνει crawl πολλαπλές URLs, εξάγει metadata και εντοπίζει broken links & redirects. const puppeteer = require("puppeteer"); const urls = [ "https://wearedoubledot.com", "https://wearedoubledot.com/stories", "https://wearedoubledot.com/who-we-are", ]; (async () => { const browser = await puppeteer.launch(); const page = await browser.newPage(); for (let url of urls) { await page.goto(url, { waitUntil: "domcontentloaded" }); const seoData = await page.evaluate(() => { let headings = {}; document.querySelectorAll("h1, h2, h3, h4, h5, h6").forEach((h) => { if (!headings[h.tagName]) { headings[h.tagName] = []; } headings[h.tagName].push(h.innerText.trim()); }); const sortedHeadings = Object.keys(headings) .sort((a, b) => { const order = { H1: 1, H2: 2, H3: 3, H4: 4, H5: 5, H6: 6 }; return order[a] - order[b]; }) .reduce((obj, key) => { obj[key] = headings[key]; return obj; }, {}); headings = sortedHeadings; return { canonical: document.querySelector('link[rel="canonical"]')?.href || "No Canonical", title: document.title || "No Title", metaDescription: document.querySelector('meta[name="description"]') ?.content || "No Meta Description", openGraphTitle: document.querySelector('meta[property="og:title"]') ?.content || "No OG Title", openGraphImage: document.querySelector('meta[property="og:image"]') ?.content || "No OG Image", headings, }; }); console.log(`SEO Data for ${url}:`, seoData); const links = await page.evaluate(() => { return Array.from(document.querySelectorAll("a")).map( (link) => link.href ); }); console.log(`Checking ${links.length} links on ${url}...`); for (let link of links) { if (link.includes("mailto") || link.includes("tel")) { console.log(`Skipping link: ${link}`); continue; } try { const response = await page.goto(link, { waitUntil: "domcontentloaded", }); console.log(`${link} -> Status: ${response.status()}`); } catch (error) { console.log(`${link} -> Error: ${error.message}`); } } } await browser.close(); })(); Αυτό το script συνδυάζει όλα τα προηγούμενα βήματα σε ένα, έτσι θα κάνει crawl πολλαπλά URLs, θα εξάγει metadata και θα ελέγξει την κατάσταση όλων των εσωτερικών συνδέσμων. Συμπέρασμα Η δημιουργία του δικού μας SEO Spider με το Puppeteer μας επέτρεψε να αντιγράψουμε μερικά από τα ισχυρά χαρακτηριστικά που βρίσκονται σε εργαλεία όπως το Screaming Frog. Αυτό το σενάριο μας παρέχει έναν απλό τρόπο για: Εξαγωγή Title & Meta Descriptions Έλεγχο Canonical Έλεγχο Open Graph Tags Ανάλυση Δομής H1-H6 Εντοπισμό Broken Links & Redirects Με την αυτοματοποίηση αυτών των εργασιών, μπορούμε να βελτιώσουμε τα SEO audits μας, να εντοπίσουμε προβλήματα πιο αποτελεσματικά και να διασφαλίσουμε ότι οι ιστότοποι είναι βελτιστοποιημένοι για τις μηχανές αναζήτησης. Αυτή είναι μόνο η αρχή. Μπορείτε να επεκτείνετε αυτό το spider προσθέτοντας περισσότερες λειτουργίες, όπως εξαγωγή δεδομένων σε CSV/JSON, εφαρμογή ενός sitemap crawler ή ακόμα και εκτέλεση σε χρονοδιάγραμμα για αυτοματοποιημένα audits. Tags Puppeteer SEO spider Share if you like! Related Posts Posted by Άννα 4 Απριλίου, 2025 Google Ads , Project Management , SEO , Social Media Ads • 8 λεπτά ανάγνωση Τι σχέση έχει το μανικιούρ με μια επιτυχημένη digital στρατηγική Περισσότερα Posted by Νάσια 16 Δεκεμβρίου, 2024 Project Management , Web Development • 6 λεπτά ανάγνωση Ο ρόλος του Project Manager στα Web Dev projects Περισσότερα Posted by Παναγιώτης 13 Απριλίου, 2024 Web Development • 11 λεπτά ανάγνωση Web Development: Χρήση των Laravel, Vue.js, Nuxt.js, GraphQL, Apollo & Tailwind CSS Περισσότερα Posted by Δημήτρης 19 Μαρτίου, 2025 Web Development • 3.5 λεπτά ανάγνωση Custom Post Types and Taxonomies: Ξεκλειδώνοντας τις Πραγματικές Δυνατότητες του WordPress Περισσότερα Posted by Νίκος 29 Οκτωβρίου, 2024 SEO • 8 λεπτά ανάγνωση Πώς επηρεάζουν τα Subdomains το SEO; Περισσότερα Posted by Γιώργος 25 Μαΐου, 2024 Web Development • 4 λεπτά ανάγνωση 12 Καρουζέλ Φτιαγμένα με Δημοφιλή Πρόσθετα JavaScript Περισσότερα
Posted by Άννα 4 Απριλίου, 2025 Google Ads , Project Management , SEO , Social Media Ads • 8 λεπτά ανάγνωση Τι σχέση έχει το μανικιούρ με μια επιτυχημένη digital στρατηγική Περισσότερα
Posted by Νάσια 16 Δεκεμβρίου, 2024 Project Management , Web Development • 6 λεπτά ανάγνωση Ο ρόλος του Project Manager στα Web Dev projects Περισσότερα
Posted by Παναγιώτης 13 Απριλίου, 2024 Web Development • 11 λεπτά ανάγνωση Web Development: Χρήση των Laravel, Vue.js, Nuxt.js, GraphQL, Apollo & Tailwind CSS Περισσότερα
Posted by Δημήτρης 19 Μαρτίου, 2025 Web Development • 3.5 λεπτά ανάγνωση Custom Post Types and Taxonomies: Ξεκλειδώνοντας τις Πραγματικές Δυνατότητες του WordPress Περισσότερα
Posted by Νίκος 29 Οκτωβρίου, 2024 SEO • 8 λεπτά ανάγνωση Πώς επηρεάζουν τα Subdomains το SEO; Περισσότερα
Posted by Γιώργος 25 Μαΐου, 2024 Web Development • 4 λεπτά ανάγνωση 12 Καρουζέλ Φτιαγμένα με Δημοφιλή Πρόσθετα JavaScript Περισσότερα