Λίγα πράγματα είναι πιο εκνευριστικά από το να γράφεις 30 γραμμές Python, να τρέχεις τον Goodreads scraper σου και να βλέπεις να επιστρέφει []. Μια άδεια λίστα. Τίποτα. Μόνο εσύ και ο κέρσορας που αναβοσβήνει.
Το έχω δει να συμβαίνει δεκάδες φορές — στα δικά μας εσωτερικά πειράματα στο , σε developer forums και στα GitHub issues που μαζεύονται σε εγκαταλελειμμένα scraper repos. Τα παράπονα είναι σχεδόν πάντα τα ίδια: "η ενότητα με τις κορυφαίες κριτικές είναι άδεια, απλώς μου δείχνει []", "όποιον αριθμό σελίδας κι αν βάλω, κάνει scrape πάντα την πρώτη σελίδα", "ο κώδικάς μου δούλευε πέρυσι, τώρα έχει χαλάσει." Και σαν να μην έφτανε αυτό, το Goodreads API καταργήθηκε τον Δεκέμβριο του 2020, οπότε η συμβουλή «χρησιμοποίησε απλώς το API» που θα βρεις σε παλιότερα tutorials δεν οδηγεί πουθενά.
Αν θέλετε σήμερα δομημένα δεδομένα βιβλίων από το Goodreads — τίτλους, συγγραφείς, βαθμολογίες, κριτικές, είδη, ISBN — το scraping είναι η βασική λύση. Αυτός ο οδηγός θα σας δείξει μια πλήρη, πρακτική προσέγγιση για να κάνετε scrape το Goodreads με Python, καλύπτοντας περιεχόμενο που αποδίδεται με JS, pagination, αποφυγή μπλοκαρίσματος και εξαγωγές. Και αν η Python δεν είναι το δυνατό σας σημείο, θα σας δείξω και μια no-code εναλλακτική που κάνει τη δουλειά σε περίπου δύο κλικ.
Τι είναι το Goodreads Scraping (και γιατί να το κάνετε με Python);
Το Goodreads scraping σημαίνει ότι εξάγετε αυτόματα δεδομένα βιβλίων — τίτλους, συγγραφείς, βαθμολογίες, αριθμό κριτικών, είδη, ISBN, αριθμό σελίδων, ημερομηνίες έκδοσης και άλλα — από τις σελίδες του Goodreads, χρησιμοποιώντας κώδικα αντί για χειροκίνητο copy-paste.
Το Goodreads είναι μία από τις μεγαλύτερες βάσεις βιβλίων στον κόσμο, με πάνω από και περίπου . Κάθε μήνα προστίθενται πάνω από 18 εκατομμύρια βιβλία στις λίστες "Want to Read". Αυτό το είδος συνεχώς ενημερούμενων, δομημένων δεδομένων είναι ακριβώς ο λόγος που εκδότες, data scientists, βιβλιοπώλες και ερευνητές επιστρέφουν ξανά και ξανά.
Η Python είναι η προτιμώμενη γλώσσα για τέτοιες δουλειές — τροφοδοτεί περίπου το όλων των scraping projects. Οι βιβλιοθήκες της είναι ώριμες (requests, BeautifulSoup, Selenium, Playwright, pandas), η σύνταξη είναι φιλική για αρχάριους και η κοινότητα τεράστια.
Αν δεν έχετε κάνει ποτέ scrape σε ιστοσελίδα, η Python είναι το καλύτερο σημείο για να ξεκινήσετε.
Γιατί να κάνετε Scrape το Goodreads με Python; Πρακτικές χρήσεις
Πριν μπούμε στον κώδικα, αξίζει να ρωτήσουμε: ποιος χρειάζεται αυτά τα δεδομένα και τι τα κάνει;
| Χρήση | Ποιον ωφελεί | Τι κάνετε scrape |
|---|---|---|
| Έρευνα αγοράς εκδοτικών | Εκδότες, λογοτεχνικοί ατζέντηδες | Δημοφιλή είδη, υψηλόβαθμοι τίτλοι, ανερχόμενοι συγγραφείς, βαθμολογίες ανταγωνιστών |
| Συστήματα προτάσεων βιβλίων | Data scientists, χομπίστες, δημιουργοί εφαρμογών | Βαθμολογίες, είδη, ράφια χρηστών, συναισθηματική ανάλυση κριτικών |
| Παρακολούθηση τιμών & αποθεμάτων | E-commerce βιβλιοπώλες | Δημοφιλείς τίτλοι, όγκος κριτικών, πλήθος "Want to Read" |
| Ακαδημαϊκή έρευνα | Ερευνητές, φοιτητές | Κείμενο κριτικών, κατανομές βαθμολογιών, ταξινομήσεις ειδών |
| Ανάλυση αναγνωστικής συμπεριφοράς | Book bloggers, προσωπικά projects | Δεδομένα προσωπικών ραφιών, ιστορικό ανάγνωσης, στατιστικά χρονιάς |
Μερικά συγκεκριμένα παραδείγματα: Το UCSD Book Graph — ένα από τα πιο συχνά αναφερόμενα ακαδημαϊκά datasets στην έρευνα συστημάτων προτάσεων — περιλαμβάνει , όλα συλλεγμένα από δημόσια προσβάσιμα Goodreads shelves. Πολλά Kaggle datasets (goodbooks-10k, Best Books Ever κ.ά.) ξεκίνησαν από Goodreads scraping. Και μια μελέτη του 2025 στο Big Data and Society συγκέντρωσε υπολογιστικά για να αναλύσει πώς οι sponsored κριτικές διαμορφώνουν την πλατφόρμα.
Στην εμπορική πλευρά, η Bright Data πουλά pre-scraped Goodreads datasets με μόλις $0,50 ανά 1.000 εγγραφές — απόδειξη ότι αυτά τα δεδομένα έχουν πραγματική αξία στην αγορά.
Το Goodreads API έχει φύγει — τι το αντικατέστησε
Αν ψάξατε πρόσφατα για "Goodreads API", πιθανότατα πέσατε πάνω σε ένα ξεπερασμένο tutorial. Στις 8 Δεκεμβρίου 2020, το Goodreads σταμάτησε αθόρυβα να εκδίδει νέα developer API keys. Δεν υπήρξε blog post, ούτε email μαζικής ενημέρωσης — μόνο ένα μικρό banner στη σελίδα της τεκμηρίωσης και πολλοί μπερδεμένοι developers.

Οι συνέπειες ήταν άμεσες. Ένας developer, ο Kyle K, είχε φτιάξει ένα Discord bot για κοινή χρήση προτάσεων βιβλίων — "ξαφνικά ΠΟΥΦ, σταματά να δουλεύει." Ένας άλλος, ο Matthew Jones, έχασε την πρόσβαση στο API μία εβδομάδα πριν από την ψηφοφορία για τα Reddit r/Fantasy Stabby Awards, και αναγκάστηκε να επιστρέψει σε Google Forms. Μια μεταπτυχιακή φοιτήτρια, η Elena Neacsu, είδε το thesis project της να εκτροχιάζεται στη μέση της ανάπτυξης.
Τι απομένει λοιπόν; Το τοπίο σήμερα είναι το εξής:
| Προσέγγιση | Διαθέσιμα δεδομένα | Ευκολία χρήσης | Όρια ρυθμού | Κατάσταση |
|---|---|---|---|---|
| Goodreads API | Πλήρη metadata, κριτικές | Εύκολη (ήταν) | 1 αίτημα/δευτ. | Καταργημένο (Δεκ. 2020) — χωρίς νέα keys |
| Open Library API | Τίτλοι, συγγραφείς, ISBN, εξώφυλλα (~30M τίτλοι) | Εύκολη | 1-3 αιτήματα/δευτ. | Ενεργό, δωρεάν, χωρίς auth |
| Google Books API | Metadata, previews | Εύκολη | 1.000/ημέρα δωρεάν | Ενεργό (κενά σε non-English ISBN) |
| Python scraping (requests + BS4) | Ό,τι υπάρχει στο αρχικό HTML | Μέτρια | Διαχειρίζεστε εσείς τα όρια | Λειτουργεί για στατικό περιεχόμενο |
| Python scraping (Selenium/Playwright) | Επίσης και JS-rendered περιεχόμενο | Πιο δύσκολο | Διαχειρίζεστε εσείς τα όρια | Απαραίτητο για κριτικές, κάποιες λίστες |
| Thunderbit (no-code Chrome extension) | Οποιαδήποτε ορατά δεδομένα σελίδας | Πολύ εύκολη (2 κλικ) | Με βάση credits | Ενεργό — χωρίς Python |
Το Open Library είναι πολύ καλό συμπλήρωμα, ειδικά για αναζητήσεις ISBN και βασικά metadata. Αλλά αν χρειάζεστε βαθμολογίες, κριτικές, tags ειδών ή πλήθος "Want to Read", τότε κάνετε scrape απευθείας από το Goodreads — είτε με Python είτε με ένα εργαλείο όπως το Thunderbit, που μπορεί να κάνει scrape σε σελίδες Goodreads (συμπεριλαμβανομένων subpages με λεπτομέρειες βιβλίων) με AI-suggested πεδία και απευθείας εξαγωγή σε Google Sheets, Notion ή Airtable.
Γιατί ο Goodreads Python scraper σας επιστρέφει κενά αποτελέσματα (και πώς να το διορθώσετε)
Αυτό είναι το τμήμα που θα ήθελα να υπήρχε όταν ξεκίνησα να δουλεύω με δεδομένα Goodreads. Το πρόβλημα των "κενών αποτελεσμάτων" είναι το πιο συχνό παράπονο στα developer forums και έχει αρκετές διαφορετικές αιτίες — καθεμία με τη δική της λύση.
| Σύμπτωμα | Αιτία | Λύση |
|---|---|---|
Οι κριτικές/βαθμολογίες επιστρέφουν [] | Περιεχόμενο που αποδίδεται με JS (React/lazy-load) | Χρησιμοποιήστε Selenium ή Playwright αντί για requests |
| Κάνει πάντα scrape μόνο την πρώτη σελίδα | Οι παράμετροι pagination αγνοούνται ή ελέγχονται από JS | Περάστε σωστά την παράμετρο ?page=N; χρησιμοποιήστε browser automation για infinite scroll |
| Ο κώδικας δούλευε πέρυσι, τώρα αποτυγχάνει | Το Goodreads άλλαξε τα HTML class names | Χρησιμοποιήστε πιο ανθεκτικούς selectors (JSON-LD, data-testid attributes) |
| 403/μπλοκάρισμα μετά από λίγα requests | Λείπουν headers / τα requests είναι πολύ γρήγορα | Προσθέστε User-Agent, time.sleep(), rotate proxies |
| Login wall σε σελίδες shelves/lists | Απαιτείται cookie/session | Χρησιμοποιήστε requests.Session() με cookies ή browser scraping |
Περιεχόμενο που αποδίδεται με JS: οι κριτικές και οι βαθμολογίες εμφανίζονται κενές
Το Goodreads χρησιμοποιεί frontend βασισμένο σε React. Όταν κάνετε requests.get() σε μια σελίδα βιβλίου, παίρνετε το αρχικό HTML — αλλά οι κριτικές, οι κατανομές βαθμολογιών και πολλά τμήματα "περισσότερες πληροφορίες" φορτώνονται ασύγχρονα μέσω JavaScript. Ο scraper σας κυριολεκτικά δεν μπορεί να τα δει.
Η λύση: για κάθε σελίδα όπου χρειάζεστε JS-rendered περιεχόμενο, περάστε σε Selenium ή Playwright. Το Playwright είναι η δική μου πρόταση για νέα projects — είναι χάρη στο WebSocket-based πρωτόκολλό του και έχει καλύτερα ενσωματωμένα stealth και async χαρακτηριστικά.

Pagination που επιστρέφει μόνο την πρώτη σελίδα
Αυτό είναι ύπουλο. Γράφετε ένα loop, αυξάνετε το ?page=N και παρ’ όλα αυτά λαμβάνετε τα ίδια αποτελέσματα κάθε φορά. Στο Goodreads, οι σελίδες shelves επιστρέφουν σιωπηλά το περιεχόμενο της πρώτης σελίδας ανεξάρτητα από την παράμετρο ?page= αν δεν είστε authenticated. Καμία ειδοποίηση, καμία ανακατεύθυνση — απλώς η ίδια πρώτη σελίδα ξανά και ξανά.
Η λύση: προσθέστε ένα authenticated session cookie (συγκεκριμένα το _session_id2). Περισσότερα για αυτό στην ενότητα του pagination παρακάτω.
Κώδικας που δούλευε πέρυσι τώρα αποτυγχάνει
Το Goodreads αλλάζει περιοδικά HTML class names και δομή σελίδων. Το δημοφιλές repo maria-antoniak/goodreads-scraper στο GitHub έχει πλέον μόνιμη σημείωση: "This project is unmaintained and no longer functioning." Η λύση είναι να χρησιμοποιήσετε πιο ανθεκτικούς selectors — JSON-LD structured data (που ακολουθεί τα standards του schema.org και σπάνια αλλάζει) ή attributes data-testid αντί για εύθραυστα class names.
Σφάλματα 403 ή μπλοκάρισμα
Η βιβλιοθήκη requests της Python έχει διαφορετικό TLS fingerprint από τον Chrome. Ακόμα κι αν βάλετε Chrome User-Agent string, συστήματα ανίχνευσης bots όπως το AWS WAF (το οποίο χρησιμοποιεί το Goodreads ως θυγατρική της Amazon) μπορούν να εντοπίσουν τη διαφορά. Η λύση: προσθέστε ρεαλιστικά browser headers, βάλτε καθυστερήσεις time.sleep() 3-8 δευτερολέπτων ανάμεσα στα requests και, για μαζικό scraping, εξετάστε το curl_cffi για αντιστοίχιση TLS fingerprint.
Login walls σε shelves και list pages
Ορισμένες σελίδες shelves και lists του Goodreads απαιτούν authentication για να δείτε όλο το περιεχόμενο, ειδικά μετά την πέμπτη σελίδα. Χρησιμοποιήστε requests.Session() με cookies που έχετε εξάγει από τον browser ή browser scraping με Selenium/Playwright σε logged-in προφίλ. Το Thunderbit το χειρίζεται φυσικά, αφού τρέχει στο δικό σας, ήδη συνδεδεμένο Chrome browser.
Πριν ξεκινήσετε
- Επίπεδο δυσκολίας: Μεσαίο (προϋποτίθεται βασική γνώση Python)
- Απαιτούμενος χρόνος: περίπου 20-30 λεπτά για όλο το walkthrough
- Τι θα χρειαστείτε:
- Python 3.8+
- Chrome browser (για έλεγχο με DevTools και Selenium/Playwright)
- Libraries:
requests,beautifulsoup4,seleniumήplaywright,pandas - (Προαιρετικά)
gspreadγια εξαγωγή σε Google Sheets - (Προαιρετικά) για την no-code εναλλακτική

Βήμα 1: Ρυθμίστε το περιβάλλον Python
Εγκαταστήστε τις απαραίτητες βιβλιοθήκες. Ανοίξτε το τερματικό σας και εκτελέστε:
1pip install requests beautifulsoup4 selenium pandas lxml
Αν προτιμάτε Playwright (το συνιστώ για νέα projects):
1pip install playwright
2playwright install chromium
Για εξαγωγή σε Google Sheets (προαιρετικά):
1pip install gspread oauth2client
Βεβαιωθείτε ότι χρησιμοποιείτε Python 3.8 ή νεότερη. Μπορείτε να το ελέγξετε με python --version.
Μετά την εγκατάσταση, θα πρέπει να μπορείτε να κάνετε import όλες τις βιβλιοθήκες χωρίς σφάλματα. Δοκιμάστε python -c "import requests, bs4, pandas; print('Ready')" για επιβεβαίωση.
Βήμα 2: Στείλτε το πρώτο request με σωστά headers
Μεταβείτε σε ένα Goodreads genre shelf ή list page στον browser σας — για παράδειγμα, https://www.goodreads.com/list/show/1.Best_Books_Ever. Τώρα ας φέρουμε αυτή τη σελίδα με Python.
1import requests
2from bs4 import BeautifulSoup
3headers = {
4 "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 "
5 "(KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36",
6 "Accept-Language": "en-US,en;q=0.9",
7 "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
8}
9url = "https://www.goodreads.com/list/show/1.Best_Books_Ever"
10response = requests.get(url, headers=headers, timeout=15)
11print(f"Status: {response.status_code}")
Θα πρέπει να δείτε Status: 200. Αν πάρετε 403, ελέγξτε ξανά τα headers σας — το AWS WAF του Goodreads ελέγχει για ρεαλιστικό User-Agent και απορρίπτει τα πολύ πρόχειρα requests. Τα παραπάνω headers μιμούνται μια πραγματική συνεδρία Chrome.
Βήμα 3: Επιθεωρήστε τη σελίδα και βρείτε τα σωστά selectors
Ανοίξτε το Chrome DevTools (F12) στη σελίδα λίστας του Goodreads. Κάντε δεξί κλικ σε έναν τίτλο βιβλίου και επιλέξτε "Inspect." Θα δείτε τη δομή DOM για κάθε καταχώριση βιβλίου.
Για τις σελίδες λιστών, κάθε βιβλίο συνήθως βρίσκεται μέσα σε ένα στοιχείο <tr> με itemtype="http://schema.org/Book". Μέσα του θα βρείτε:
- Τίτλο:
a.bookTitle(το link text είναι ο τίτλος, τοhrefδίνει το URL του βιβλίου) - Συγγραφέα:
a.authorName - Βαθμολογία:
span.minirating(περιέχει τον μέσο όρο και τον αριθμό βαθμολογιών) - Εικόνα εξωφύλλου:
imgμέσα στη γραμμή του βιβλίου
Για τις μεμονωμένες σελίδες λεπτομερειών βιβλίου, παραλείψτε τους CSS selectors και πηγαίνετε κατευθείαν στο JSON-LD. Το Goodreads ενσωματώνει δομημένα δεδομένα μέσα σε ένα <script type="application/ld+json"> που ακολουθεί το schema.org Book format. Είναι πολύ πιο σταθερό από τα class names, τα οποία το Goodreads αλλάζει όποτε θέλει.
Βήμα 4: Εξάγετε δεδομένα βιβλίων από μία σελίδα λίστας
Ας κάνουμε parse τη σελίδα λίστας και ας εξάγουμε βασικές πληροφορίες για κάθε βιβλίο:
1import requests
2from bs4 import BeautifulSoup
3headers = {
4 "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 "
5 "(KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36",
6 "Accept-Language": "en-US,en;q=0.9",
7}
8url = "https://www.goodreads.com/list/show/1.Best_Books_Ever"
9response = requests.get(url, headers=headers, timeout=15)
10soup = BeautifulSoup(response.text, "lxml")
11books = []
12rows = soup.select('tr[itemtype="http://schema.org/Book"]')
13for row in rows:
14 title_tag = row.select_one("a.bookTitle")
15 author_tag = row.select_one("a.authorName")
16 rating_tag = row.select_one("span.minirating")
17 title = title_tag.get_text(strip=True) if title_tag else ""
18 book_url = "https://www.goodreads.com" + title_tag["href"] if title_tag else ""
19 author = author_tag.get_text(strip=True) if author_tag else ""
20 rating_text = rating_tag.get_text(strip=True) if rating_tag else ""
21 books.append({
22 "title": title,
23 "author": author,
24 "rating_info": rating_text,
25 "book_url": book_url,
26 })
27print(f"Found {len(books)} books on page 1")
28for b in books[:3]:
29 print(b)
Θα πρέπει να δείτε περίπου 100 βιβλία ανά σελίδα λίστας. Κάθε εγγραφή θα έχει τίτλο, συγγραφέα, μια συμβολοσειρά βαθμολογίας όπως "4.28 avg rating — 9,031,257 ratings," και ένα URL προς τη σελίδα λεπτομερειών του βιβλίου.
Βήμα 5: Κάντε scrape subpages για λεπτομερείς πληροφορίες βιβλίου
Η σελίδα λίστας σας δίνει τα βασικά, αλλά ο πραγματικός θησαυρός — ISBN, πλήρης περιγραφή, tags ειδών, αριθμός σελίδων, ημερομηνία έκδοσης — βρίσκεται στη σελίδα κάθε βιβλίου. Εδώ το JSON-LD λάμπει πραγματικά.
1import json
2import time
3def scrape_book_detail(book_url, headers):
4 """Επισκέπτεται μια σελίδα βιβλίου και εξάγει αναλυμένα metadata μέσω JSON-LD."""
5 resp = requests.get(book_url, headers=headers, timeout=15)
6 if resp.status_code != 200:
7 return {}
8 soup = BeautifulSoup(resp.text, "lxml")
9 script = soup.find("script", {"type": "application/ld+json"})
10 if not script:
11 return {}
12 data = json.loads(script.string)
13 agg = data.get("aggregateRating", {})
14 # Τα genre tags δεν βρίσκονται στο JSON-LD· γι’ αυτό χρησιμοποιούμε fallback στο HTML
15 genres = [g.get_text(strip=True) for g in soup.select('span.BookPageMetadataSection__genreButton a span')]
16 return {
17 "isbn": data.get("isbn", ""),
18 "pages": data.get("numberOfPages", ""),
19 "language": data.get("inLanguage", ""),
20 "format": data.get("bookFormat", ""),
21 "avg_rating": agg.get("ratingValue", ""),
22 "rating_count": agg.get("ratingCount", ""),
23 "review_count": agg.get("reviewCount", ""),
24 "description": data.get("description", "")[:200], # περικόπτεται για προεπισκόπηση
25 "genres": ", ".join(genres[:5]),
26 }
27# Παράδειγμα: εμπλουτίζουμε τα πρώτα 3 βιβλία
28for book in books[:3]:
29 details = scrape_book_detail(book["book_url"], headers)
30 book.update(details)
31 print(f"Scraped: {book['title']} — ISBN: {book.get('isbn', 'N/A')}")
32 time.sleep(4) # σεβασμός στα rate limits
Προσθέστε time.sleep() 3-8 δευτερολέπτων ανάμεσα στα requests. Το rate limiting του Goodreads ενεργοποιείται περίπου στα 20-30 requests το λεπτό από ένα μόνο IP και θα αρχίσετε να βλέπετε 403s ή CAPTCHAs αν πάτε πιο γρήγορα.
Αυτή η προσέγγιση δύο περασμάτων — πρώτα συλλέγετε όλα τα book URLs από τις σελίδες λίστας και μετά επισκέπτεστε κάθε σελίδα λεπτομερειών — είναι πιο αξιόπιστη και πιο εύκολη στο να συνεχιστεί αν διακοπεί. Είναι η στρατηγική που χρησιμοποιούν οι πιο επιτυχημένοι Goodreads scrapers.
Σημείωση: Το μπορεί να το κάνει αυτό αυτόματα με subpage scraping. Το AI επισκέπτεται τη σελίδα λεπτομερειών κάθε βιβλίου και εμπλουτίζει τον πίνακά σας με ISBN, περιγραφή, είδη και άλλα — χωρίς κώδικα, χωρίς loops, χωρίς timers.
Βήμα 6: Χειριστείτε περιεχόμενο που αποδίδεται με JavaScript μέσω Selenium
Για σελίδες όπου το περιεχόμενο που χρειάζεστε φορτώνεται μέσω JavaScript — κριτικές, αναλυτικές βαθμολογίες, ενότητες "περισσότερες λεπτομέρειες" — θα χρειαστείτε ένα εργαλείο browser automation. Ακολουθεί ένα παράδειγμα με Selenium:
1from selenium import webdriver
2from selenium.webdriver.chrome.options import Options
3from selenium.webdriver.common.by import By
4from selenium.webdriver.support.ui import WebDriverWait
5from selenium.webdriver.support import expected_conditions as EC
6options = Options()
7options.add_argument("--headless=new")
8options.add_argument("--disable-blink-features=AutomationControlled")
9options.add_argument("user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
10 "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36")
11driver = webdriver.Chrome(options=options)
12driver.get("https://www.goodreads.com/book/show/5907.The_Hobbit")
13# Περιμένουμε να φορτώσουν οι κριτικές
14try:
15 WebDriverWait(driver, 10).until(
16 EC.presence_of_element_located((By.CSS_SELECTOR, "article.ReviewCard"))
17 )
18except:
19 print("Οι κριτικές δεν φορτώθηκαν — η σελίδα ίσως απαιτεί login ή το JS έληξε")
20# Τώρα κάνουμε parse την πλήρως αποδοσμένη σελίδα
21page_source = driver.page_source
22soup = BeautifulSoup(page_source, "lxml")
23reviews = soup.select("article.ReviewCard")
24for rev in reviews[:3]:
25 text = rev.select_one("span.Formatted")
26 stars = rev.select_one("span.RatingStars")
27 print(f"Rating: {stars.get_text(strip=True) if stars else 'N/A'}")
28 print(f"Review: {text.get_text(strip=True)[:150] if text else 'N/A'}...")
29 print()
30driver.quit()
Πότε να χρησιμοποιήσετε Selenium vs. requests:
- Χρησιμοποιήστε
requests+ BeautifulSoup για metadata βιβλίου (JSON-LD), list pages, shelf pages (page 1) και δεδομένα Choice Awards - Χρησιμοποιήστε Selenium ή Playwright για κριτικές, κατανομές βαθμολογιών και οποιοδήποτε περιεχόμενο δεν εμφανίζεται στο raw HTML
Το Playwright είναι γενικά καλύτερη επιλογή για νέα projects — πιο γρήγορο, με μικρότερη κατανάλωση μνήμης και καλύτερα stealth defaults. Αλλά το Selenium έχει μεγαλύτερη κοινότητα και περισσότερα έτοιμα παραδείγματα για Goodreads.
Pagination που δουλεύει πραγματικά: scrape ολόκληρες λίστες Goodreads
Το pagination είναι το πιο συχνό σημείο αποτυχίας για Goodreads scrapers, και δεν έχω βρει ούτε ένα ανταγωνιστικό tutorial που να το καλύπτει σωστά. Έτσι το κάνετε σωστά.
Πώς δουλεύουν τα pagination URLs του Goodreads
Το Goodreads χρησιμοποιεί μια απλή παράμετρο ?page=N για τις περισσότερες paginated σελίδες:
- Λίστες:
https://www.goodreads.com/list/show/1.Best_Books_Ever?page=2 - Shelves:
https://www.goodreads.com/shelf/show/thriller?page=2 - Αναζήτηση:
https://www.goodreads.com/search?q=fantasy&page=2
Κάθε σελίδα λίστας δείχνει συνήθως 100 βιβλία. Τα shelves δείχνουν 50 ανά σελίδα.
Πώς να γράψετε ένα loop pagination που ξέρει πότε να σταματήσει
1import time
2all_books = []
3base_url = "https://www.goodreads.com/list/show/1.Best_Books_Ever"
4for page_num in range(1, 50): # όριο ασφαλείας στις 50 σελίδες
5 url = f"{base_url}?page={page_num}"
6 resp = requests.get(url, headers=headers, timeout=15)
7 if resp.status_code != 200:
8 print(f"Σελίδα {page_num}: status {resp.status_code}, διακοπή.")
9 break
10 soup = BeautifulSoup(resp.text, "lxml")
11 rows = soup.select('tr[itemtype="http://schema.org/Book"]')
12 if not rows:
13 print(f"Σελίδα {page_num}: δεν βρέθηκαν βιβλία, τέλος της λίστας.")
14 break
15 for row in rows:
16 title_tag = row.select_one("a.bookTitle")
17 author_tag = row.select_one("a.authorName")
18 title = title_tag.get_text(strip=True) if title_tag else ""
19 book_url = "https://www.goodreads.com" + title_tag["href"] if title_tag else ""
20 author = author_tag.get_text(strip=True) if author_tag else ""
21 all_books.append({"title": title, "author": author, "book_url": book_url})
22 print(f"Σελίδα {page_num}: αποθηκεύτηκαν {len(rows)} βιβλία (σύνολο: {len(all_books)})")
23 time.sleep(5) # καθυστέρηση 5 δευτερολέπτων ανάμεσα στις σελίδες
24print(f"\nΟλοκληρώθηκε. Συνολικά βιβλία που συλλέχθηκαν: {len(all_books)}")
Την τελευταία σελίδα την εντοπίζετε ελέγχοντας αν η λίστα αποτελεσμάτων είναι κενή (δεν βρέθηκαν στοιχεία tr[itemtype="http://schema.org/Book"]) ή αν δεν υπάρχει σύνδεσμος "next" (a.next_page).
Edge case: Απαιτείται login μετά την 5η σελίδα
Αυτό είναι η παγίδα που πιάνει σχεδόν όλους: ορισμένες σελίδες shelves και lists του Goodreads επιστρέφουν σιωπηλά το περιεχόμενο της πρώτης σελίδας όταν ζητάτε τη σελίδα 6+ χωρίς authentication. Καμία ειδοποίηση, καμία ανακατεύθυνση — μόνο τα ίδια δεδομένα ξανά.
Για να το διορθώσετε, εξάγετε το cookie _session_id2 από τον browser σας (χρησιμοποιήστε ένα extension για cookie export ή το Chrome DevTools > Application > Cookies) και περάστε το στα requests σας:
1session = requests.Session()
2session.headers.update(headers)
3session.cookies.set("_session_id2", "YOUR_SESSION_COOKIE_VALUE_HERE", domain=".goodreads.com")
4# Τώρα χρησιμοποιήστε session.get() αντί για requests.get()
5resp = session.get(f"{base_url}?page=6", timeout=15)
Το Thunderbit χειρίζεται φυσικά τόσο το click-based όσο και το infinite-scroll pagination, χωρίς κώδικα και χωρίς διαχείριση cookies. Αν η λογική του pagination σας συνεχίζει να σπάει, αξίζει να το σκεφτείτε.
Το πλήρες, έτοιμο για copy-paste script σε Python
Ορίστε το πλήρες, συγκεντρωμένο script. Χειρίζεται headers, pagination, scraping subpages μέσω JSON-LD, rate limiting και εξαγωγή σε CSV. Το έχω δοκιμάσει σε ζωντανές Goodreads σελίδες μέχρι τα μέσα του 2025.
1"""
2goodreads_scraper.py — Scrape a Goodreads list with pagination and book detail enrichment.
3Usage: python goodreads_scraper.py
4Output: goodreads_books.csv
5"""
6import csv, json, time, requests
7from bs4 import BeautifulSoup
8HEADERS = {
9 "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 "
10 "(KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36",
11 "Accept-Language": "en-US,en;q=0.9",
12 "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
13}
14BASE_URL = "https://www.goodreads.com/list/show/1.Best_Books_Ever"
15MAX_PAGES = 3 # προσαρμόστε το όπως χρειάζεται
16DELAY_LISTING = 5 # δευτερόλεπτα ανάμεσα στις σελίδες λίστας
17DELAY_DETAIL = 4 # δευτερόλεπτα ανάμεσα στις σελίδες λεπτομερειών
18OUTPUT_FILE = "goodreads_books.csv"
19def scrape_listing_page(url):
20 """Επιστρέφει λίστα από dicts με title, author, book_url από μία σελίδα λίστας."""
21 resp = requests.get(url, headers=HEADERS, timeout=15)
22 if resp.status_code != 200:
23 return []
24 soup = BeautifulSoup(resp.text, "lxml")
25 rows = soup.select('tr[itemtype="http://schema.org/Book"]')
26 books = []
27 for row in rows:
28 t = row.select_one("a.bookTitle")
29 a = row.select_one("a.authorName")
30 if t:
31 books.append({
32 "title": t.get_text(strip=True),
33 "author": a.get_text(strip=True) if a else "",
34 "book_url": "https://www.goodreads.com" + t["href"],
35 })
36 return books
37def scrape_book_detail(book_url):
38 """Επισκέπτεται μια σελίδα βιβλίου και εξάγει metadata μέσω JSON-LD + HTML fallback."""
39 resp = requests.get(book_url, headers=HEADERS, timeout=15)
40 if resp.status_code != 200:
41 return {}
42 soup = BeautifulSoup(resp.text, "lxml")
43 script = soup.find("script", {"type": "application/ld+json"})
44 if not script:
45 return {}
46 data = json.loads(script.string)
47 agg = data.get("aggregateRating", {})
48 genres = [g.get_text(strip=True)
49 for g in soup.select("span.BookPageMetadataSection__genreButton a span")]
50 return {
51 "isbn": data.get("isbn", ""),
52 "pages": data.get("numberOfPages", ""),
53 "avg_rating": agg.get("ratingValue", ""),
54 "rating_count": agg.get("ratingCount", ""),
55 "review_count": agg.get("reviewCount", ""),
56 "description": (data.get("description", "") or "")[:300],
57 "genres": ", ".join(genres[:5]),
58 "language": data.get("inLanguage", ""),
59 "format": data.get("bookFormat", ""),
60 "published": data.get("datePublished", ""),
61 }
62def main():
63 all_books = []
64 # --- Πέρασμα 1: συλλογή book URLs από τις σελίδες λίστας ---
65 for page in range(1, MAX_PAGES + 1):
66 url = f"{BASE_URL}?page={page}"
67 page_books = scrape_listing_page(url)
68 if not page_books:
69 print(f"Σελίδα {page}: κενή — διακοπή pagination.")
70 break
71 all_books.extend(page_books)
72 print(f"Σελίδα {page}: {len(page_books)} βιβλία (σύνολο: {len(all_books)})")
73 time.sleep(DELAY_LISTING)
74 # --- Πέρασμα 2: εμπλουτισμός κάθε βιβλίου με data από τη σελίδα λεπτομερειών ---
75 for i, book in enumerate(all_books):
76 details = scrape_book_detail(book["book_url"])
77 book.update(details)
78 print(f"[{i+1}/{len(all_books)}] {book['title']} — ISBN: {book.get('isbn', 'N/A')}")
79 time.sleep(DELAY_DETAIL)
80 # --- Εξαγωγή σε CSV ---
81 if all_books:
82 fieldnames = list(all_books[0].keys())
83 with open(OUTPUT_FILE, "w", newline="", encoding="utf-8") as f:
84 writer = csv.DictWriter(f, fieldnames=fieldnames)
85 writer.writeheader()
86 writer.writerows(all_books)
87 print(f"\nΑποθηκεύτηκαν {len(all_books)} βιβλία στο {OUTPUT_FILE}")
88 else:
89 print("Δεν έγινε scrape σε κανένα βιβλίο.")
90if __name__ == "__main__":
91 main()
Με MAX_PAGES = 3, αυτό το script συλλέγει περίπου 300 βιβλία από τη λίστα "Best Books Ever", επισκέπτεται τη σελίδα λεπτομερειών κάθε βιβλίου και γράφει τα πάντα σε CSV. Στον υπολογιστή μου χρειάζεται περίπου 25 λεπτά (κυρίως λόγω των 4 δευτερολέπτων καθυστέρησης ανάμεσα στα detail page requests). Το output CSV θα έχει στήλες όπως title, author, book_url, isbn, pages, avg_rating, rating_count, review_count, description, genres, language, format και published.
Εξαγωγή πέρα από CSV: Google Sheets με gspread
Αν θέλετε τα δεδομένα σε Google Sheets αντί για CSV ή επιπλέον αυτού, προσθέστε αυτό μετά την εξαγωγή σε CSV:
1import gspread
2from oauth2client.service_account import ServiceAccountCredentials
3scope = ["https://spreadsheets.google.com/feeds", "https://www.googleapis.com/auth/drive"]
4creds = ServiceAccountCredentials.from_json_keyfile_name("credentials.json", scope)
5client = gspread.authorize(creds)
6sheet = client.open("Goodreads Scrape").sheet1
7header = list(all_books[0].keys())
8sheet.append_row(header)
9for book in all_books:
10 sheet.append_row([str(book.get(k, "")) for k in header])
11print("Τα δεδομένα στάλθηκαν στο Google Sheets.")
Θα χρειαστείτε ένα Google Cloud service account με ενεργοποιημένα τα Sheets και Drive APIs. Η εξηγεί τη ρύθμιση σε περίπου 5 λεπτά. Χρησιμοποιήστε batch operations (append_rows() με λίστες από λίστες) αν στέλνετε πάνω από μερικές εκατοντάδες γραμμές — το rate limit της Google είναι 300 requests ανά 60 δευτερόλεπτα ανά project.
Φυσικά, αν όλη αυτή η ρύθμιση σας φαίνεται υπερβολική, το Thunderbit κάνει export σε Google Sheets, Airtable, Notion, Excel, CSV και JSON με — χωρίς libraries, χωρίς credentials file, χωρίς API quotas.
Η no-code εναλλακτική: Scrape το Goodreads με Thunderbit
Δεν θέλουν όλοι να συντηρούν ένα Python script. Ίσως είστε εκδότης που κάνει μια εφάπαξ ανάλυση αγοράς, ή ένας βιβλιολόγος που θέλει απλώς ένα spreadsheet με τα bestsellers της χρονιάς. Ακριβώς γι’ αυτές τις περιπτώσεις φτιάξαμε το Thunderbit.
Πώς να κάνετε Scrape το Goodreads με Thunderbit
- Εγκαταστήστε το Thunderbit Chrome extension από το και ανοίξτε μια Goodreads σελίδα λίστας, shelf ή αποτελεσμάτων αναζήτησης.
- Κάντε κλικ στο "AI Suggest Fields" στο sidebar του Thunderbit. Το AI διαβάζει τη σελίδα και προτείνει στήλες — συνήθως title, author, rating, cover image URL και book link.
- Πατήστε "Scrape" — τα δεδομένα εξάγονται σε δομημένο πίνακα μέσα σε δευτερόλεπτα.
- Export σε Google Sheets, Excel, Airtable, Notion, CSV ή JSON.
Για αναλυτικά δεδομένα βιβλίου (ISBN, περιγραφή, είδη, αριθμό σελίδων), η λειτουργία subpage scraping του Thunderbit επισκέπτεται τη σελίδα λεπτομερειών κάθε βιβλίου και εμπλουτίζει αυτόματα τον πίνακα — χωρίς loops, χωρίς timers, χωρίς debugging.
Το Thunderbit χειρίζεται επίσης native τα paginated lists. Του λέτε να κάνει click στο "Next" ή να κάνει scroll, και συγκεντρώνει δεδομένα από όλες τις σελίδες χωρίς κανέναν κώδικα.
Η ανταλλαγή είναι απλή: το Python script σας δίνει απόλυτο έλεγχο και είναι δωρεάν (εκτός από τον χρόνο σας), ενώ το Thunderbit θυσιάζει λίγη ευελιξία για τεράστια εξοικονόμηση χρόνου και μηδενική συντήρηση. Για μια λίστα 300 βιβλίων, το Python script χρειάζεται περίπου 25 λεπτά runtime, συν τον χρόνο που ξοδέψατε για να το γράψετε και να το διορθώσετε. Το Thunderbit παίρνει τα ίδια δεδομένα σε περίπου 3 λεπτά, με δύο κλικ.
Scraping στο Goodreads με υπευθυνότητα: robots.txt, Όροι Χρήσης και δεοντολογία
Αυτό αξίζει μια ξεκάθαρη απάντηση, όχι ένα αδιάφορο παράγραφο-αποποίηση ευθύνης.
Τι λέει πραγματικά το robots.txt του Goodreads
Το live robots.txt του Goodreads είναι εκπληκτικά συγκεκριμένο. Οι σελίδες λεπτομερειών βιβλίων (/book/show/), οι δημόσιες λίστες (/list/show/), τα δημόσια shelves (/shelf/show/) και οι σελίδες συγγραφέων (/author/show/) δεν είναι μπλοκαρισμένες. Αυτό που μπλοκάρεται είναι τα /api, /book/reviews/, /review/list, /review/show, /search και αρκετά άλλα paths. Τα GPTBot και CCBot (Common Crawl) μπλοκάρονται πλήρως με Disallow: /. Υπάρχει οδηγία Crawl-delay: 5 για το bingbot, αλλά όχι global delay.
Οι Όροι Χρήσης του Goodreads σε απλά λόγια
Οι Όροι Χρήσης (τελευταία αναθεώρηση 28 Απριλίου 2021) απαγορεύουν "οποιαδήποτε χρήση εργαλείων data mining, robots ή παρόμοιων εργαλείων συλλογής και εξαγωγής δεδομένων." Αυτή είναι ευρεία διατύπωση και αξίζει να τη λάβετε σοβαρά υπόψη — όμως τα δικαστήρια έχουν επανειλημμένα κρίνει ότι οι παραβιάσεις ToS από μόνες τους δεν συνιστούν ποινική "μη εξουσιοδοτημένη πρόσβαση." Η απόφαση ανέφερε ότι "η ποινικοποίηση των παραβιάσεων όρων χρήσης κινδυνεύει να μετατρέψει κάθε website στη δική του ποινική δικαιοδοσία."
Καλές πρακτικές
- Βάλτε καθυστερήσεις στα requests: 3-8 δευτερόλεπτα ανά request (το ίδιο το robots.txt του Goodreads προτείνει 5 δευτερόλεπτα για bots)
- Μείνετε κάτω από 5.000 requests την ημέρα από ένα μόνο IP
- Κάντε scrape μόνο δημόσια προσβάσιμες σελίδες — αποφύγετε μαζικό scraping δεδομένων που είναι διαθέσιμα μόνο μετά από login
- Μην αναδιανέμετε εμπορικά το ακατέργαστο κείμενο κριτικών — οι κριτικές είναι έργα με πνευματικά δικαιώματα
- Αποθηκεύστε μόνο ό,τι χρειάζεστε και ορίστε πρόγραμμα διατήρησης δεδομένων
- Προσωπική έρευνα vs. εμπορική χρήση: Το scraping δημόσιων δεδομένων για προσωπική ανάλυση ή ακαδημαϊκή έρευνα θεωρείται γενικά αποδεκτό. Ο εμπορικός ανασχεδιασμός/αναδιανομή αυξάνει τον νομικό κίνδυνο.
Η χρήση ενός εργαλείου όπως το Thunderbit (που κάνει scrape μέσω της δικής σας συνεδρίας browser) κάνει την αλληλεπίδραση οπτικά ίδια με τη συνηθισμένη περιήγηση, αλλά οι ίδιες ηθικές αρχές ισχύουν ανεξάρτητα από το εργαλείο που επιλέγετε. Αν θέλετε να εμβαθύνετε περισσότερο στις , έχουμε καλύψει το θέμα ξεχωριστά.
Συμβουλές και συνηθισμένες παγίδες
Συμβουλή: Ξεκινήστε πάντα από το JSON-LD. Πριν γράψετε σύνθετους CSS selectors, ελέγξτε αν τα δεδομένα που χρειάζεστε βρίσκονται στο <script type="application/ld+json">. Είναι πιο σταθερό, πιο εύκολο στο parse και λιγότερο πιθανό να σπάσει όταν το Goodreads ανανεώσει το frontend.
Συμβουλή: Χρησιμοποιήστε τη στρατηγική δύο περασμάτων. Πρώτα συλλέξτε όλα τα book URLs από τις σελίδες λίστας και μετά επισκεφθείτε κάθε σελίδα λεπτομερειών. Έτσι ο scraper σας είναι ευκολότερο να συνεχιστεί αν διακοπεί στη μέση, και μπορείτε να αποθηκεύσετε τη λίστα URLs στο δίσκο ως checkpoint.
Παγίδα: Ξεχνάτε να χειριστείτε πεδία που λείπουν. Δεν έχει κάθε σελίδα βιβλίου ISBN, genre tags ή περιγραφή. Χρησιμοποιείτε πάντα .get() με default τιμή ή ελέγχετε selectors με if. Ένα μόνο NoneType error μπορεί να ρίξει ένα scraping run 3 ωρών.
Παγίδα: Τρέχετε πολύ γρήγορα. Ξέρω ότι είναι δελεαστικό να βάλετε time.sleep(0.5) και να προχωρήσετε με φόρα. Αλλά το Goodreads θα αρχίσει να επιστρέφει 403 μετά από περίπου 20-30 γρήγορα requests, και μόλις σημειωθείτε, ίσως χρειαστεί να περιμένετε ώρες ή να αλλάξετε IP. Μια καθυστέρηση 4-5 δευτερολέπτων είναι το ιδανικό σημείο.
Παγίδα: Εμπιστεύεστε παλιά tutorials. Αν ένας οδηγός αναφέρεται στο Goodreads API ή χρησιμοποιεί class names όπως .field.value ή #bookTitle, πιθανότατα είναι ξεπερασμένος. Πάντα επιβεβαιώνετε τους selectors πάνω στη ζωντανή σελίδα πριν χτίσετε τον scraper σας.
Για περισσότερα σχετικά με το πώς να διαλέξετε τα σωστά εργαλεία και frameworks scraping, δείτε τους οδηγούς μας για τα και το .
Συμπέρασμα και βασικά συμπεράσματα
Το scraping του Goodreads με Python είναι απολύτως εφικτό — απλώς πρέπει να ξέρετε πού είναι οι παγίδες. Η σύντομη εκδοχή:
- Το Goodreads API έχει φύγει (από τον Δεκέμβριο του 2020). Το scraping είναι ο βασικός τρόπος για να πάρετε δομημένα δεδομένα βιβλίων από την πλατφόρμα.
- Τα κενά αποτελέσματα προκαλούνται σχεδόν πάντα από JS-rendered περιεχόμενο, παλιούς selectors, ελλιπή headers ή προβλήματα authentication στο pagination — όχι επειδή ο κώδικάς σας είναι λάθος.
- Το JSON-LD είναι ο καλύτερός σας σύμμαχος για metadata βιβλίου. Είναι σταθερό, δομημένο και αλλάζει σπάνια.
- Το pagination απαιτεί authentication για πολλές σελίδες shelves και lists πέρα από την πέμπτη. Προσθέστε το cookie
_session_id2. - Το rate limiting είναι πραγματικό. Χρησιμοποιήστε καθυστερήσεις 3-8 δευτερολέπτων και μείνετε κάτω από 5.000 requests ανά ημέρα.
- Η στρατηγική δύο περασμάτων (πρώτα URLs, μετά detail pages) είναι πιο αξιόπιστη και επιτρέπει να συνεχίσετε από το σημείο που σταματήσατε.
- Για μη-προγραμματιστές (ή για όποιον εκτιμά το απόγευμά του), το τα αναλαμβάνει όλα αυτά — JS rendering, pagination, enrichment subpages και export — σε περίπου δύο κλικ.
Κάντε scrape με υπευθυνότητα, σεβαστείτε το robots.txt, και μακάρι τα δεδομένα των βιβλίων σας να επιστρέφουν πάντα κάτι παραπάνω από [].
Συχνές Ερωτήσεις
Μπορείτε ακόμα να χρησιμοποιήσετε το Goodreads API;
Όχι. Το Goodreads κατήργησε το δημόσιο API του τον Δεκέμβριο του 2020 και δεν εκδίδει πλέον νέα developer keys. Τα υπάρχοντα keys που έμεναν ανενεργά για 30 ημέρες απενεργοποιούνταν αυτόματα. Το web scraping ή εναλλακτικά APIs (όπως το Open Library ή το Google Books) είναι σήμερα οι διαθέσιμες επιλογές για προγραμματιστική πρόσβαση σε δεδομένα βιβλίων.
Γιατί ο Goodreads scraper μου επιστρέφει κενά αποτελέσματα;
Η πιο συχνή αιτία είναι περιεχόμενο που αποδίδεται με JavaScript. Το Goodreads φορτώνει κριτικές, κατανομές βαθμολογιών και πολλές ενότητες λεπτομερειών μέσω React/JavaScript, κάτι που ένα απλό requests.get() δεν μπορεί να δει. Για αυτές τις σελίδες περάστε σε Selenium ή Playwright. Άλλες αιτίες είναι οι ξεπερασμένοι CSS selectors (το Goodreads άλλαξε το HTML), τα ελλιπή User-Agent headers (που προκαλούν 403 blocks) ή τα unauthenticated requests σε paginated shelf pages.
Είναι νόμιμο να κάνετε scrape το Goodreads;
Το scraping δημοσίως διαθέσιμων δεδομένων για προσωπική ή ερευνητική χρήση θεωρείται γενικά αποδεκτό με βάση τις τρέχουσες νομικές εξελίξεις (hiQ v. LinkedIn, Meta v. Bright Data). Ωστόσο, οι Όροι Χρήσης του Goodreads απαγορεύουν την αυτοματοποιημένη συλλογή δεδομένων, και πρέπει πάντα να ελέγχετε το robots.txt τους. Αποφύγετε την εμπορική αναδιανομή κειμένου κριτικών που προστατεύεται από πνευματικά δικαιώματα και περιορίστε τον όγκο των requests για να μη φορτώνετε τους πόρους του site.
Πώς κάνω scrape πολλές σελίδες στο Goodreads;
Προσθέστε ?page=N στο shelf ή list URL και κάντε loop στους αριθμούς σελίδων. Ελέγξτε για κενά αποτελέσματα ή για την απουσία συνδέσμου "next" ώστε να εντοπίσετε την τελευταία σελίδα. Σημαντικό: ορισμένες σελίδες shelves απαιτούν authentication (το cookie _session_id2) για να επιστρέψουν αποτελέσματα πέρα από την 5η σελίδα — χωρίς αυτό, θα παίρνετε σιωπηλά ξανά τα δεδομένα της πρώτης σελίδας.
Μπορώ να κάνω scrape το Goodreads χωρίς να γράψω κώδικα;
Ναι. Το είναι ένα Chrome extension που σας επιτρέπει να κάνετε scrape το Goodreads σε δύο κλικ — το AI προτείνει τα πεδία δεδομένων, πατάτε "Scrape" και κάνετε export απευθείας σε Google Sheets, Excel, Airtable ή Notion. Χειρίζεται αυτόματα περιεχόμενο που αποδίδεται με JavaScript, pagination και enrichment subpages, χωρίς να χρειάζεται Python ή προγραμματισμός.
Μάθετε περισσότερα