first commit
This commit is contained in:
603
Readme.md
603
Readme.md
@@ -1,88 +1,575 @@
|
||||
# Unoffical Goodreads Book Search
|
||||
# 📚 Unofficial Goodreads Book Search API
|
||||
|
||||
This library allows you to retrieve book information from Goodreads using only the ISBN number, without needing an API key. The library analyzes Goodreads' HTML structure and returns book details in JSON format. It works asynchronously (based on Promises).
|
||||
[](https://badge.fury.io/js/szbk-goodreads-search-book)
|
||||
[](https://opensource.org/licenses/MIT)
|
||||
[](https://nodejs.org/)
|
||||
[](https://github.com/szbk/goodreads-book-search)
|
||||
|
||||
## ✨ Features
|
||||
🔍 **A powerful Node.js library that enables you to retrieve comprehensive book information from Goodreads using only an ISBN number - no API key required!**
|
||||
|
||||
- 📚 Retrieves book information from Goodreads using the ISBN number.
|
||||
- 🖼️ Returns detailed information such as book cover, title, author, genre, and publication date.
|
||||
- 🕒 Customizable delay between requests.
|
||||
- ✅ Tests integrated with Mocha and Chai.
|
||||
- 🌐 Web data is fetched and parsed using Axios and Cheerio.
|
||||
This library intelligently analyzes Goodreads' HTML structure and returns detailed book information in a clean JSON format. Built with modern asynchronous JavaScript patterns and comprehensive error handling.
|
||||
|
||||
## 🎯 Requirements
|
||||
---
|
||||
|
||||
- Node.js (v14 veya üzeri)
|
||||
- NPM
|
||||
- Internet connection
|
||||
- Curiosity
|
||||
## ✨ Key Features
|
||||
|
||||
- 🔑 **No API Key Required** - Search Goodreads without authentication
|
||||
- 📖 **Comprehensive Data** - Extract detailed book information including:
|
||||
- 📕 Title & cover image
|
||||
- ✍️ Author details with profile links
|
||||
- 🌍 Translator information
|
||||
- 📝 Full book descriptions
|
||||
- 📄 Page count
|
||||
- ⭐ Goodreads ratings
|
||||
- 🏷️ Genre classifications
|
||||
- 📅 Publication dates
|
||||
- 🚀 **Modern JavaScript** - Promise-based asynchronous operations
|
||||
- 🛡️ **Error Resilient** - Comprehensive error handling and validation
|
||||
- ⚡ **Performance Optimized** - Configurable request delays and timeouts
|
||||
- 🧪 **Well Tested** - Complete test suite with Mocha and Chai
|
||||
- 📊 **CI/CD Ready** - Jenkins integration with automated testing
|
||||
- 🔧 **Easy Configuration** - Simple, intuitive API
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Prerequisites
|
||||
|
||||
- **Node.js** v14 or higher
|
||||
- **NPM** (usually comes with Node.js)
|
||||
- **Internet connection** (for Goodreads access)
|
||||
- **Basic JavaScript knowledge** (async/await patterns)
|
||||
|
||||
---
|
||||
|
||||
## 📦 Installation
|
||||
|
||||
```bash
|
||||
npm install szbk-goodreads-search-api
|
||||
```
|
||||
## 🚀 Usage
|
||||
# Install via npm
|
||||
npm install szbk-goodreads-search-book
|
||||
|
||||
The following example shows how to use the API:
|
||||
# Or using yarn
|
||||
yarn add szbk-goodreads-search-book
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Quick Start
|
||||
|
||||
### Basic Usage
|
||||
|
||||
```javascript
|
||||
const GoodreadsBookSearch = require("szbk-goodreads-search-api");
|
||||
const GoodreadsBookSearch = require("szbk-goodreads-search-book");
|
||||
|
||||
(async () => {
|
||||
async function searchBook() {
|
||||
try {
|
||||
const BookSearch = new GoodreadsBookSearch();
|
||||
const bookDetails = await BookSearch.getBookDetails("9944824453");
|
||||
|
||||
console.log(bookDetails);
|
||||
console.log("📚 Book Found:", bookDetails);
|
||||
} catch (error) {
|
||||
console.error("Hata:", error.message);
|
||||
console.error("❌ Error:", error.message);
|
||||
}
|
||||
})();
|
||||
}
|
||||
|
||||
searchBook();
|
||||
```
|
||||
|
||||
// Example Output:
|
||||
### Example Output
|
||||
|
||||
```json
|
||||
{
|
||||
title: 'Dövmeli Adam',
|
||||
thumbImage: 'https: //res.cloudinary.com/path/to/image.jpg',
|
||||
authorName: {
|
||||
author: { name: 'Peter V. Brett', profileLink: '/author/show/12345'
|
||||
"title": "Dövmeli Adam",
|
||||
"thumbImage": "https://images.gr-assets.com/books/1348616986m/8631735.jpg",
|
||||
"authorName": {
|
||||
"author": {
|
||||
"name": "Peter V. Brett",
|
||||
"profileLink": "/author/show/306789.Peter_V_Brett"
|
||||
},
|
||||
translators: ['Çevirmen Adı 1', 'Çevirmen Adı 2'
|
||||
]
|
||||
"translators": ["Çevirmen Adı 1", "Çevirmen Adı 2"]
|
||||
},
|
||||
description: 'Kitap açıklaması burada yer alır.',
|
||||
page: '640',
|
||||
isbn: '9944824453',
|
||||
date: '01 Sept 2008',
|
||||
rate: '4.3',
|
||||
genres: ['Fantasy', 'Adventure', 'Action'
|
||||
]
|
||||
"description": "Kitap açıklaması burada yer alır. Kapsamlı kitap özeti...",
|
||||
"page": "640",
|
||||
"isbn": "9944824453",
|
||||
"date": "01 Sept 2008",
|
||||
"rate": "4.3",
|
||||
"genres": ["Fantasy", "Adventure", "Action"]
|
||||
}
|
||||
```
|
||||
|
||||
## 📂 Project Structure
|
||||
---
|
||||
|
||||
## 📖 Advanced Usage
|
||||
|
||||
### Error Handling Best Practices
|
||||
|
||||
```javascript
|
||||
szbk-goodreads-search-book
|
||||
├── config
|
||||
│ └── index.js # Configuration file
|
||||
├── lib
|
||||
│ ├── index.js # GoodreadsBookSearch class
|
||||
│ └── module.js # Data processing and parsing operations
|
||||
├── test
|
||||
│ └── index.js # Integration tests
|
||||
├── index.js # Entry point
|
||||
├── package.json # Dependencies and scripts
|
||||
└── README.md # Documentation
|
||||
const GoodreadsBookSearch = require("szbk-goodreads-search-book");
|
||||
|
||||
async function robustBookSearch(isbn) {
|
||||
const BookSearch = new GoodreadsBookSearch();
|
||||
|
||||
try {
|
||||
const bookDetails = await BookSearch.getBookDetails(isbn);
|
||||
|
||||
// Validate the response
|
||||
if (!bookDetails.title) {
|
||||
throw new Error("Book title not found");
|
||||
}
|
||||
|
||||
return bookDetails;
|
||||
|
||||
} catch (error) {
|
||||
// Handle different error types
|
||||
if (error.message.includes("Detay bilgisi bulunamadı")) {
|
||||
console.log("📭 Book not found for ISBN:", isbn);
|
||||
} else if (error.message.includes("timeout")) {
|
||||
console.log("⏰ Request timeout. Please try again.");
|
||||
} else {
|
||||
console.log("❌ Unexpected error:", error.message);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Usage
|
||||
robustBookSearch("9944824453").then(book => {
|
||||
if (book) {
|
||||
console.log("✅ Successfully retrieved:", book.title);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
## 🧪 Tests
|
||||
To run the tests, follow these steps:
|
||||
1. Install test dependencies:
|
||||
```javascript
|
||||
npm install
|
||||
```
|
||||
2. Run the tests:
|
||||
```javascript
|
||||
npm test
|
||||
```
|
||||
### Multiple Book Search
|
||||
|
||||
```javascript
|
||||
async function searchMultipleBooks(isbnList) {
|
||||
const BookSearch = new GoodreadsBookSearch();
|
||||
const results = [];
|
||||
|
||||
for (const isbn of isbnList) {
|
||||
try {
|
||||
console.log(`🔍 Searching for ISBN: ${isbn}`);
|
||||
const bookDetails = await BookSearch.getBookDetails(isbn);
|
||||
results.push({ isbn, success: true, data: bookDetails });
|
||||
} catch (error) {
|
||||
results.push({ isbn, success: false, error: error.message });
|
||||
}
|
||||
|
||||
// Add delay between requests to be respectful
|
||||
await new Promise(resolve => setTimeout(resolve, 3000));
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
// Example usage
|
||||
const isbnList = ["9944824453", "863173540X", "9780547928227"];
|
||||
searchMultipleBooks(isbnList).then(results => {
|
||||
console.log("📊 Search Results:", results);
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🏗️ Architecture & Project Structure
|
||||
|
||||
```
|
||||
szbk-goodreads-search-book/
|
||||
├── 📁 lib/ # Core library files
|
||||
│ ├── 📄 index.js # Main GoodreadsBookSearch class
|
||||
│ └── 📄 module.js # Data extraction and parsing logic
|
||||
├── 📁 config/ # Configuration files
|
||||
│ └── 📄 index.js # Application configuration
|
||||
├── 📁 test/ # Test suite
|
||||
│ └── 📄 index.js # Integration tests
|
||||
├── 📄 index.js # Library entry point
|
||||
├── 📄 package.json # Dependencies and metadata
|
||||
├── 📄 package-lock.json # Locked dependencies
|
||||
├── 📄 Jenkinsfile # CI/CD pipeline configuration
|
||||
├── 📄 mocha-report-config.json # Test reporting configuration
|
||||
└── 📄 README.md # This documentation
|
||||
```
|
||||
|
||||
### Core Components
|
||||
|
||||
- **`GoodreadsBookSearch` Class**: Main interface for book searches
|
||||
- **HTML Parser**: Uses Cheerio for robust HTML parsing
|
||||
- **Data Extraction**: Specialized methods for different book metadata
|
||||
- **Error Handling**: Comprehensive error catching and user-friendly messages
|
||||
- **Configuration**: Centralized settings for timeouts, headers, and URLs
|
||||
|
||||
---
|
||||
|
||||
## ⚙️ Configuration Options
|
||||
|
||||
The library includes built-in configuration that you can modify:
|
||||
|
||||
```javascript
|
||||
// Default configuration in config/index.js
|
||||
{
|
||||
goodreadsBaseUrl: "https://www.goodreads.com/search?q=",
|
||||
headers: {
|
||||
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36..."
|
||||
},
|
||||
fetchTimeout: 2000 // Delay between requests in milliseconds
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🧪 Testing
|
||||
|
||||
### Run All Tests
|
||||
|
||||
```bash
|
||||
# Install dependencies first
|
||||
npm install
|
||||
|
||||
# Run the test suite
|
||||
npm test
|
||||
```
|
||||
|
||||
### Test Coverage
|
||||
|
||||
The test suite includes:
|
||||
- ✅ ISBN validation
|
||||
- ✅ Title extraction accuracy
|
||||
- ✅ Publication date parsing
|
||||
- ✅ Page count verification
|
||||
- ✅ Error handling scenarios
|
||||
- ✅ Integration testing with live Goodreads data
|
||||
|
||||
### Sample Test Output
|
||||
|
||||
```
|
||||
🧠 Goodreads Book Search Integration Test
|
||||
✓ Is the ISBN "9944824453" 🔥 (1500ms)
|
||||
✓ Is the book title "Dövmeli Adam" 🚀 (1200ms)
|
||||
✓ Is the book's publication date "1 September 2008" ⏰ (1100ms)
|
||||
✓ Is the page count "640" 📋 (1300ms)
|
||||
|
||||
4 passing (5s)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📚 API Reference
|
||||
|
||||
### GoodreadsBookSearch Class
|
||||
|
||||
#### Constructor
|
||||
```javascript
|
||||
const BookSearch = new GoodreadsBookSearch();
|
||||
```
|
||||
|
||||
#### Methods
|
||||
|
||||
##### `getBookDetails(isbn)`
|
||||
Searches for a book using its ISBN number.
|
||||
|
||||
**Parameters:**
|
||||
- `isbn` (string): The ISBN number to search for
|
||||
|
||||
**Returns:**
|
||||
- `Promise<Object>`: Book details object
|
||||
|
||||
**Example:**
|
||||
```javascript
|
||||
const details = await BookSearch.getBookDetails("9944824453");
|
||||
```
|
||||
|
||||
### Response Object Structure
|
||||
|
||||
```typescript
|
||||
interface BookDetails {
|
||||
title: string; // Book title
|
||||
thumbImage: string; // Cover image URL
|
||||
authorName: {
|
||||
author?: {
|
||||
name: string; // Author name
|
||||
profileLink: string; // Goodreads profile URL
|
||||
};
|
||||
translators?: string[]; // Translator names array
|
||||
};
|
||||
description: string; // Book description
|
||||
page: string; // Page count as string
|
||||
isbn: string; // ISBN number
|
||||
date: string; // Publication date (DD MMM YYYY)
|
||||
rate: string; // Goodreads rating
|
||||
genres: string[]; // Array of genre tags
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔄 Integration Examples
|
||||
|
||||
### Express.js Integration
|
||||
|
||||
```javascript
|
||||
const express = require('express');
|
||||
const GoodreadsBookSearch = require('szbk-goodreads-search-book');
|
||||
|
||||
const app = express();
|
||||
app.use(express.json());
|
||||
|
||||
const BookSearch = new GoodreadsBookSearch();
|
||||
|
||||
// API endpoint for book search
|
||||
app.get('/api/books/:isbn', async (req, res) => {
|
||||
try {
|
||||
const { isbn } = req.params;
|
||||
|
||||
if (!isbn || isbn.length < 10) {
|
||||
return res.status(400).json({
|
||||
error: 'Invalid ISBN provided'
|
||||
});
|
||||
}
|
||||
|
||||
const bookDetails = await BookSearch.getBookDetails(isbn);
|
||||
res.json({ success: true, data: bookDetails });
|
||||
|
||||
} catch (error) {
|
||||
res.status(404).json({
|
||||
success: false,
|
||||
error: error.message
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
app.listen(3000, () => {
|
||||
console.log('📚 Book search API running on port 3000');
|
||||
});
|
||||
```
|
||||
|
||||
### React Integration
|
||||
|
||||
```jsx
|
||||
import React, { useState } from 'react';
|
||||
const GoodreadsBookSearch = require('szbk-goodreads-search-book');
|
||||
|
||||
function BookSearchApp() {
|
||||
const [isbn, setIsbn] = useState('');
|
||||
const [book, setBook] = useState(null);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [error, setError] = useState('');
|
||||
|
||||
const searchBook = async () => {
|
||||
if (!isbn) return;
|
||||
|
||||
setLoading(true);
|
||||
setError('');
|
||||
|
||||
try {
|
||||
const BookSearch = new GoodreadsBookSearch();
|
||||
const bookDetails = await BookSearch.getBookDetails(isbn);
|
||||
setBook(bookDetails);
|
||||
} catch (err) {
|
||||
setError(err.message);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<input
|
||||
value={isbn}
|
||||
onChange={(e) => setIsbn(e.target.value)}
|
||||
placeholder="Enter ISBN..."
|
||||
/>
|
||||
<button onClick={searchBook} disabled={loading}>
|
||||
{loading ? 'Searching...' : 'Search'}
|
||||
</button>
|
||||
|
||||
{error && <p style={{color: 'red'}}>{error}</p>}
|
||||
|
||||
{book && (
|
||||
<div>
|
||||
<h2>{book.title}</h2>
|
||||
<p>Author: {book.authorName?.author?.name}</p>
|
||||
<p>Rating: {book.rate}/5</p>
|
||||
<img src={book.thumbImage} alt={book.title} />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Deployment & CI/CD
|
||||
|
||||
### Jenkins Integration
|
||||
|
||||
This project includes a pre-configured Jenkinsfile for automated testing:
|
||||
|
||||
- **Automated Triggers**: Runs every 6 hours
|
||||
- **Smart Dependencies**: Only runs `npm install` when package.json changes
|
||||
- **Test Reporting**: Generates JUnit XML reports
|
||||
- **Slack Integration**: Sends build notifications to Slack channels
|
||||
- **Cleanup**: Automatically removes old test reports
|
||||
|
||||
### Jenkins Pipeline Features
|
||||
|
||||
```groovy
|
||||
// Key features of the Jenkins pipeline
|
||||
- Cron scheduling (H */6 * * *)
|
||||
- Node.js 22.13.0 support
|
||||
- Conditional dependency installation
|
||||
- Automated test execution
|
||||
- Test result publishing
|
||||
- Slack notifications for success/failure
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔧 Development
|
||||
|
||||
### Local Development Setup
|
||||
|
||||
```bash
|
||||
# Clone the repository
|
||||
git clone https://github.com/szbk/goodreads-book-search.git
|
||||
cd goodreads-book-search
|
||||
|
||||
# Install dependencies
|
||||
npm install
|
||||
|
||||
# Run tests in development mode
|
||||
npm test
|
||||
|
||||
# Start development (if applicable)
|
||||
npm run dev
|
||||
```
|
||||
|
||||
### Contributing Guidelines
|
||||
|
||||
1. 🍴 Fork the repository
|
||||
2. 🌿 Create a feature branch (`git checkout -b feature/amazing-feature`)
|
||||
3. 📝 Make your changes with proper testing
|
||||
4. ✅ Ensure all tests pass
|
||||
5. 📤 Commit your changes (`git commit -m 'Add amazing feature'`)
|
||||
6. 📤 Push to the branch (`git push origin feature/amazing-feature`)
|
||||
7. 🔃 Open a Pull Request
|
||||
|
||||
---
|
||||
|
||||
## 🛠️ Dependencies
|
||||
|
||||
### Production Dependencies
|
||||
|
||||
| Package | Version | Purpose |
|
||||
|---------|---------|---------|
|
||||
| `axios` | ^1.6.8 | HTTP client for web requests |
|
||||
| `cheerio` | ^1.0.0-rc.12 | HTML parsing and DOM manipulation |
|
||||
| `@google/generative-ai` | ^0.8.0 | AI integration for enhanced descriptions |
|
||||
| `dotenv` | ^16.4.5 | Environment variable management |
|
||||
|
||||
### Development Dependencies
|
||||
|
||||
| Package | Version | Purpose |
|
||||
|---------|---------|---------|
|
||||
| `mocha` | ^11.0.1 | Test framework |
|
||||
| `chai` | ^5.1.2 | Assertion library |
|
||||
| `mocha-junit-reporter` | ^2.2.1 | JUnit XML test reporting |
|
||||
| `mocha-multi-reporters` | ^1.5.1 | Multiple test reporters support |
|
||||
|
||||
---
|
||||
|
||||
## ❓ FAQ
|
||||
|
||||
### Q: Do I need a Goodreads API key?
|
||||
**A:** No! This library works by analyzing Goodreads' public HTML structure, so no API key is required.
|
||||
|
||||
### Q: Is this library officially supported by Goodreads?
|
||||
**A:** No, this is an unofficial library. Use responsibly and in accordance with Goodreads' terms of service.
|
||||
|
||||
### Q: What happens if Goodreads changes their HTML structure?
|
||||
**A:** The library may need updates to work with new HTML structures. Report issues if you encounter problems.
|
||||
|
||||
### Q: Can I use this in a commercial application?
|
||||
**A:** Yes, under the MIT license. However, ensure compliance with Goodreads' terms of service.
|
||||
|
||||
### Q: How can I avoid rate limiting?
|
||||
**A:** The library includes a built-in 2-second delay between requests. You can modify this in the config file if needed.
|
||||
|
||||
---
|
||||
|
||||
## 🔒 Legal & Disclaimer
|
||||
|
||||
- This is an **unofficial** library and is not affiliated with Goodreads
|
||||
- Use responsibly and in accordance with Goodreads' terms of service
|
||||
- The library is provided "as-is" without warranties
|
||||
- Users are responsible for ensuring compliance with applicable laws and terms
|
||||
|
||||
---
|
||||
|
||||
## 📄 License
|
||||
|
||||
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
||||
|
||||
```
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2024 szbk
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🤝 Support & Community
|
||||
|
||||
- **GitHub Issues**: [Report bugs and request features](https://github.com/szbk/goodreads-book-search/issues)
|
||||
- **GitHub Discussions**: [Community discussions and questions](https://github.com/szbk/goodreads-book-search/discussions)
|
||||
- **NPM Page**: [Package information and version history](https://www.npmjs.com/package/szbk-goodreads-search-book)
|
||||
|
||||
---
|
||||
|
||||
## 📊 Version History
|
||||
|
||||
### v1.1.2 (Current)
|
||||
- ✨ Enhanced HTML parsing stability
|
||||
- 🛡️ Improved error handling
|
||||
- 📝 Better documentation
|
||||
|
||||
### v1.1.0
|
||||
- 🔧 Added configurable timeouts
|
||||
- 🧪 Enhanced test coverage
|
||||
- 🚀 Performance improvements
|
||||
|
||||
### v1.0.0
|
||||
- 🎉 Initial release
|
||||
- 📚 Core Goodreads search functionality
|
||||
- 🔍 ISBN-based book lookup
|
||||
|
||||
---
|
||||
|
||||
## 🙏 Acknowledgments
|
||||
|
||||
- **Goodreads** - For providing an amazing book database platform
|
||||
- **Cheerio** - Excellent HTML parsing library
|
||||
- **Axios** - Reliable HTTP client
|
||||
- **Mocha & Chai** - Great testing framework
|
||||
- The open-source community for inspiration and tools
|
||||
|
||||
---
|
||||
|
||||
<div align="center">
|
||||
|
||||
**⭐ If this project helped you, please give it a star on GitHub!**
|
||||
|
||||
Made with ❤️ by [szbk](https://github.com/szbk)
|
||||
|
||||
</div>
|
||||
Reference in New Issue
Block a user