# type: ignore import json from pathlib import Path import requests from bs4 import BeautifulSoup from sentence_transformers import SentenceTransformer KNOWLEDGE_BASE_URL = "https://help.suno.com/en" KNOWLEDGE_BASE_URL_BASE = "https://help.suno.com" def scrape_category_cards_for_urls(url, a_tag_class="kb-category-card"): try: response = requests.get(url) soup = BeautifulSoup(response.content, "html.parser") links = soup.find_all("a", class_=a_tag_class) urls = [ None if link.get("href")[:8] == "https://" else f"{KNOWLEDGE_BASE_URL_BASE}{link.get('href')}" for link in links if link.get("href") ] return urls except Exception as e: print(f"Error scraping URL: {e}") return [] def scrape_knowledge_base(): try: articles = [] article_index = 0 category_urls = scrape_category_cards_for_urls(KNOWLEDGE_BASE_URL) print(category_urls) if len(category_urls): for url in category_urls: if url is None: continue print(f"Scraping {url} for categories...") subcategory_urls = scrape_category_cards_for_urls(url) for subcategory_url in subcategory_urls: if subcategory_url is None: continue article_urls = scrape_category_cards_for_urls( subcategory_url, a_tag_class="article-card" ) for article_url in article_urls: if article_url is None: continue article_title, article_text_chunks = scrape_webpage(article_url) for chunk in article_text_chunks: chunk_data = { "text": chunk, "url": article_url, "title": article_title or f"article-{article_index}", } articles.append(chunk_data) article_index += 1 else: print(f"No articles found for {KNOWLEDGE_BASE_URL}") return [] return articles except Exception as e: print(f"Error scraping {url}: {e}") return [] def scrape_webpage(url): """Scrape text content from a webpage""" print(f"Scraping {url}...") try: response = requests.get(url, timeout=10) soup = BeautifulSoup(response.content, "html.parser") # Remove script and style elements for script in soup(["script", "style"]): script.decompose() # Get text and title title = None title_el = soup.find("h1", class_="article-title") if title_el: title = title_el.get_text() content_el = soup.find("div", class_="article-content") text = None if content_el: text = content_el.get_text() # Clean up whitespace if text: chunks = (line.strip().replace("\n", " ") for line in text.splitlines()) # chunks = (phrase.strip() for line in lines for phrase in line.split(" ")) else: chunks = [] return (title, [chunk for chunk in chunks if chunk]) except Exception as e: print(f"Error scraping {url}: {e}") return "" if __name__ == "__main__": articles = scrape_knowledge_base() # returns { title -> text_chunks } dict model = SentenceTransformer("all-MiniLM-L6-v2") if articles: embeddings = model.encode([article["text"] for article in articles], show_progress_bar=True) for i, embedding in enumerate(embeddings): articles[i]["embedding"] = embedding.tolist() script_dir = Path(__file__).parent output_file = script_dir / ".." / "suno_orpheus" / "services" / "assets" / "knowledge_base.json" with open(output_file, "w", encoding="utf-8") as f: json.dump({"knowledge_chunks": articles}, f, ensure_ascii=False, indent=2)