cleaned up readme

This commit is contained in:
cporter202
2025-12-09 11:23:13 -05:00
parent befe6fb055
commit 43403aa8b8
2 changed files with 20417 additions and 21098 deletions

41270
README.md

File diff suppressed because it is too large Load Diff

245
generate_readme_clean.js Normal file
View File

@@ -0,0 +1,245 @@
/**
* Script to generate a clean, organized README.md with all Apify Actors
*/
const fs = require('fs');
// Read the JSON file
const actors = JSON.parse(fs.readFileSync('apify_actors.json', 'utf-8'));
console.log(`Processing ${actors.length} actors...`);
// Function to convert category name to readable format and anchor
function formatCategoryName(category) {
const acronyms = {
'AI': 'AI',
'MCP': 'MCP',
'SEO': 'SEO',
'API': 'API'
};
let readable = category
.split('_')
.map(word => {
const upper = word.toUpperCase();
if (acronyms[upper]) {
return acronyms[upper];
}
return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();
})
.join(' ');
if (readable === 'Ai') readable = 'AI';
if (readable === 'Mcp Servers') readable = 'MCP Servers';
if (readable === 'Seo Tools') readable = 'SEO Tools';
const anchor = readable.toLowerCase().replace(/\s+/g, '-');
return { readable, anchor };
}
// Organize actors by category
const actorsByCategory = {};
const uncategorized = [];
for (const actor of actors) {
const categories = actor.categories || [];
if (categories.length > 0) {
for (const category of categories) {
if (!actorsByCategory[category]) {
actorsByCategory[category] = [];
}
const exists = actorsByCategory[category].some(a =>
a.name === actor.name && a.username === actor.username
);
if (!exists) {
actorsByCategory[category].push(actor);
}
}
} else {
uncategorized.push(actor);
}
}
const sortedCategories = Object.keys(actorsByCategory).sort();
// Generate README content
let content = `# 🚀 API Mega List\n\n`;
content += `> **The most comprehensive collection of APIs on GitHub** - ${actors.length.toLocaleString()} ready-to-use APIs for building everything from simple automations to full-scale applications.\n\n`;
content += `---\n\n`;
// Statistics section with badges
content += `## 📊 Collection Statistics\n\n`;
content += `| Metric | Count |\n`;
content += `|--------|-------|\n`;
content += `| **Total APIs** | **${actors.length.toLocaleString()}** |\n`;
content += `| **Categories** | **${sortedCategories.length}** |\n`;
content += `| **Last Updated** | ${new Date().toISOString().split('T')[0]} |\n\n`;
content += `### 📁 Available Formats\n\n`;
content += `- **[APIFY_ACTORS.md](APIFY_ACTORS.md)** - Complete markdown list (~8.3 MB)\n`;
content += `- **[apify_actors.json](apify_actors.json)** - Full JSON dataset (~11.6 MB)\n`;
content += `- **[apify_actors_simple.txt](apify_actors_simple.txt)** - Simple text format (~996 KB)\n\n`;
content += `---\n\n`;
// What are Apify Actors section
content += `## 🤔 What are Apify Actors?\n\n`;
content += `Apify Actors are pre-built web scraping and automation tools that can extract data from websites, automate workflows, and integrate with AI applications. Each actor is a ready-to-use API that you can run via the Apify platform.\n\n`;
content += `**All links in this collection include affiliate tracking** (\`?fpr=p2hrc6\`) - clicking any API link supports this project! 🎉\n\n`;
content += `---\n\n`;
// Table of Contents with better formatting
content += `## 📚 Table of Contents\n\n`;
content += `<details>\n`;
content += `<summary><b>Click to expand - ${sortedCategories.length} Categories</b></summary>\n\n`;
// Create a table for better organization
content += `| Category | APIs | Link |\n`;
content += `|----------|------|------|\n`;
for (const category of sortedCategories) {
const count = actorsByCategory[category].length;
const { anchor, readable } = formatCategoryName(category);
content += `| **${readable}** | ${count.toLocaleString()} | [View →](#${anchor}) |\n`;
}
if (uncategorized.length > 0) {
content += `| **Uncategorized** | ${uncategorized.length.toLocaleString()} | [View →](#uncategorized) |\n`;
}
content += `\n</details>\n\n`;
content += `---\n\n`;
// Write categorized actors with better formatting
for (const category of sortedCategories) {
const categoryActors = actorsByCategory[category];
const { readable, anchor } = formatCategoryName(category);
content += `## ${readable}\n\n`;
content += `<p align="right"><a href="#-table-of-contents">↑ Back to top</a></p>\n\n`;
content += `**${categoryActors.length.toLocaleString()} APIs in this category**\n\n`;
// Sort actors by title
const sortedActors = categoryActors.sort((a, b) =>
(a.title || a.name || '').localeCompare(b.title || b.name || '')
);
// Group into columns for better readability (every 3 items)
for (let i = 0; i < sortedActors.length; i += 3) {
const batch = sortedActors.slice(i, i + 3);
for (const actor of batch) {
const title = actor.title || actor.name || 'Unknown';
const affiliateUrl = actor.affiliate_url || actor.url || '';
const description = actor.description || '';
// Truncate descriptions at word boundaries
const maxDescLength = 150;
let shortDescription = description;
if (description.length > maxDescLength) {
let cutPoint = maxDescLength;
const lastSpace = description.lastIndexOf(' ', maxDescLength);
if (lastSpace > maxDescLength * 0.8) {
cutPoint = lastSpace;
}
shortDescription = description.substring(0, cutPoint).trim() + '...';
}
// Clean up title - remove extra brackets if present
let cleanTitle = title;
if (cleanTitle.startsWith('[') && cleanTitle.includes(']')) {
cleanTitle = cleanTitle.replace(/^\[([^\]]+)\]\s*/, '$1 ');
}
if (shortDescription) {
content += `- **[${cleanTitle}](${affiliateUrl})** - ${shortDescription}\n`;
} else {
content += `- **[${cleanTitle}](${affiliateUrl})**\n`;
}
}
}
content += `\n`;
}
// Write uncategorized actors
if (uncategorized.length > 0) {
content += `## Uncategorized\n\n`;
content += `<p align="right"><a href="#-table-of-contents">↑ Back to top</a></p>\n\n`;
content += `**${uncategorized.length.toLocaleString()} APIs in this category**\n\n`;
const sortedUncategorized = uncategorized.sort((a, b) =>
(a.title || a.name || '').localeCompare(b.title || b.name || '')
);
for (const actor of sortedUncategorized) {
const title = actor.title || actor.name || 'Unknown';
const affiliateUrl = actor.affiliate_url || actor.url || '';
const description = actor.description || '';
const maxDescLength = 150;
let shortDescription = description;
if (description.length > maxDescLength) {
let cutPoint = maxDescLength;
const lastSpace = description.lastIndexOf(' ', maxDescLength);
if (lastSpace > maxDescLength * 0.8) {
cutPoint = lastSpace;
}
shortDescription = description.substring(0, cutPoint).trim() + '...';
}
let cleanTitle = title;
if (cleanTitle.startsWith('[') && cleanTitle.includes(']')) {
cleanTitle = cleanTitle.replace(/^\[([^\]]+)\]\s*/, '$1 ');
}
if (shortDescription) {
content += `- **[${cleanTitle}](${affiliateUrl})** - ${shortDescription}\n`;
} else {
content += `- **[${cleanTitle}](${affiliateUrl})**\n`;
}
}
content += `\n`;
}
content += `---\n\n`;
// Usage section
content += `## 🚀 How to Use\n\n`;
content += `1. **Browse by Category** - Use the table of contents above to jump to any category\n`;
content += `2. **Click Any API** - All links include affiliate tracking and take you to the Apify platform\n`;
content += `3. **View Documentation** - Each API page has full documentation, examples, and pricing\n`;
content += `4. **Run via API** - All actors can be run programmatically via Apify's API\n`;
content += `5. **Schedule Runs** - Set up automated schedules for regular data collection\n\n`;
content += `---\n\n`;
// Notes section
content += `## 📝 Notes\n\n`;
content += `- ✅ All APIs are sorted alphabetically within their categories\n`;
content += `- ✅ Descriptions are optimized for readability (truncated to ~150 characters)\n`;
content += `- ✅ For full descriptions and details, visit the individual API pages\n`;
content += `- ✅ This list is automatically generated from the Apify Store API\n`;
content += `- ✅ All links include affiliate tracking (\`?fpr=p2hrc6\`)\n\n`;
content += `---\n\n`;
// Footer
content += `<div align="center">\n\n`;
content += `**Total APIs: ${actors.length.toLocaleString()}** | `;
content += `**Categories: ${sortedCategories.length}** | `;
content += `**Last Updated: ${new Date().toISOString().split('T')[0]}**\n\n`;
content += `*One of the most valuable API lists on GitHub—period.* 💪\n\n`;
content += `</div>\n`;
// Write to README.md
fs.writeFileSync('README.md', content, 'utf-8');
console.log(`✅ Clean README.md generated successfully!`);
console.log(` - ${sortedCategories.length} categories`);
console.log(` - ${actors.length.toLocaleString()} total APIs`);
console.log(` - ${uncategorized.length.toLocaleString()} uncategorized APIs`);