Last active
June 21, 2026 06:06
-
-
Save mehori/7756e5e31bd82f9a7ef18bf3c493410e to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import sys | |
| import requests | |
| from bs4 import BeautifulSoup | |
| import json | |
| import os | |
| from datetime import datetime | |
| # Install this script in a directory like ~/hugo_root/tools/ | |
| # Configure your project paths | |
| # there are 2 more places hard-coded in the script. change it. | |
| DATA_FILE = "../data/blogcards.json" | |
| IMAGE_DIR = "../assets/images/blogcards" | |
| # Ensure directories exist | |
| os.makedirs(IMAGE_DIR, exist_ok=True) | |
| os.makedirs("data", exist_ok=True) | |
| def fetch_card_data(url): | |
| # Generate ID based on current time (added seconds to prevent collisions) | |
| card_id = datetime.now().strftime("%Y%m%d%H%M%S") | |
| print(f"Fetching data for: {url}") | |
| headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)'} | |
| try: | |
| response = requests.get(url, headers=headers, timeout=10) | |
| response.raise_for_status() | |
| soup = BeautifulSoup(response.content, 'html.parser') | |
| except Exception as e: | |
| print(f"Error fetching URL: {e}") | |
| sys.exit(1) | |
| # 1. Extract Title | |
| og_title = soup.find('meta', property='og:title') | |
| title = og_title['content'] if og_title and og_title.get('content') else "" | |
| if not title: | |
| title = soup.title.string if soup.title else url | |
| # 2. Extract Description | |
| og_desc = soup.find('meta', property='og:description') | |
| if not og_desc: | |
| og_desc = soup.find('meta', attrs={'name': 'description'}) | |
| desc = og_desc['content'] if og_desc and og_desc.get('content') else "" | |
| # 3. Extract and Download Image | |
| og_image = soup.find('meta', property='og:image') | |
| image_url = og_image['content'] if og_image and og_image.get('content') else None | |
| local_image_path = "" | |
| if image_url: | |
| # Handle relative image URLs | |
| if image_url.startswith('/'): | |
| from urllib.parse import urljoin | |
| image_url = urljoin(url, image_url) | |
| print(f"Downloading image: {image_url}") | |
| try: | |
| img_data = requests.get(image_url, headers=headers, timeout=10).content | |
| # Save as jpg in assets folder | |
| local_image_path = f"images/blogcards/{card_id}.jpg" | |
| with open(f"assets/{local_image_path}", 'wb') as handler: | |
| handler.write(img_data) | |
| except Exception as e: | |
| print(f"Failed to download image: {e}") | |
| # 4. Update the Hugo Data JSON | |
| if os.path.exists(DATA_FILE): | |
| with open(DATA_FILE, 'r', encoding='utf-8') as f: | |
| try: | |
| data = json.load(f) | |
| except json.JSONDecodeError: | |
| data = {} | |
| else: | |
| data = {} | |
| data[card_id] = { | |
| "url": url, | |
| "title": title.strip(), | |
| "description": desc.strip(), | |
| "image": local_image_path | |
| } | |
| with open(DATA_FILE, 'w', encoding='utf-8') as f: | |
| json.dump(data, f, indent=2, ensure_ascii=False) | |
| print(f"\nSuccess! Card ID: {card_id}") | |
| print(f"Markdown usage:") | |
| print(f"{{{{< blogcard id=\"{card_id}\" url=\"{url}\" >}}}}") | |
| if __name__ == "__main__": | |
| if len(sys.argv) < 2: | |
| print("Usage: python add_card.py <URL>") | |
| sys.exit(1) | |
| target_url = sys.argv[1] | |
| fetch_card_data(target_url) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment