SPB Git

spb/ultra-sharp-agent-skills Public

Ultra-Sharp Agent Skills — a research-first skill-authoring system + 72 production-ready skills for AI agents.

Python 100%
4.0 KB · 77 lines markdown
Rendered Raw Blame History
1---2name: processing-html3description: Creates, reads, and modifies local HTML files — extracting text, tables, and links, or editing markup with BeautifulSoup. Use when the user asks to parse, scrape data out of, edit, clean up, or generate an .html or .htm file, extract a table or links from saved HTML, or build a static HTML page. Do not use for fetching live web pages (that is web browsing/scraping) or for XML data files.4---56<!--7Author: Simon-Pierre Boucher8Contact: contact@spboucher.ai9-->1011# Processing HTML1213## When to use / when NOT to use14- **Use for:** local `.html`/`.htm` files — extracting text, tables, or links; targeted markup edits; generating static pages from scratch.15- **Do NOT use for:** fetching live web pages (that is web browsing/scraping — get the file first, then this skill applies) or XML data files (use the XML skill — XML parsers are strict, HTML parsers are tolerant).1617## Quick reference1819**Default:** BeautifulSoup4 with the built-in `html.parser` (`pip install beautifulsoup4`). **Escape hatch:** the `lxml` parser (`pip install lxml`) for large or badly malformed files — faster and more lenient.2021```python22from bs4 import BeautifulSoup2324soup = BeautifulSoup(open("page.html", encoding="utf-8"), "html.parser")2526# Read / extract27title = soup.title.get_text(strip=True) if soup.title else ""28links = [(a.get_text(strip=True), a["href"]) for a in soup.find_all("a", href=True)]29rows = [[c.get_text(strip=True) for c in tr.find_all(["td", "th"])]30        for tr in soup.select("table tr")]           # lists-of-lists3132# Modify — targeted, leave everything else untouched33for img in soup.find_all("img", src=True):34    if not img.get("alt"):35        img["alt"] = ""36open("page.html", "w", encoding="utf-8").write(str(soup))37```3839**Create** — write HTML5 directly, no library:4041```html42<!DOCTYPE html>43<html lang="en">44<head>45  <meta charset="utf-8">46  <meta name="viewport" content="width=device-width, initial-scale=1">47  <title>Page title</title>48</head>49<body>50  <main>…</main>51</body>52</html>53```5455## Rules56- **Never regex-parse HTML.** Use the soup — selectors and tree navigation, always.57- Edit surgically: modify the matched tags only; do not re-indent or `prettify()` an existing file (it rewrites every text node's whitespace).58- New pages are HTML5: doctype, `<meta charset="utf-8">`, semantic tags (`main`, `nav`, `article`), `lang` attribute.59- Extract tables as lists-of-lists; flag `rowspan`/`colspan` cells instead of silently mis-aligning columns.6061## Workflow621. Identify the operation: extract / modify / create.632. Parse with `html.parser`; if the file is huge (>5 MB) or the tree looks wrong (missing siblings, truncated body), reparse with `"lxml"`.643. Perform the operation with the narrowest selector that matches (recipes in references/recipes.md).654. Write back with the file's original encoding.665. **Validate:** re-parse the written file and confirm the edit landed (query the changed element) and the element count of untouched regions is unchanged. Fix and repeat until clean.6768## Edge cases & failure modes69- **bs4/lxml missing**`pip install beautifulsoup4` / `pip install lxml`.70- **Malformed HTML** → parsers auto-repair rather than error; if extraction returns nothing, the repaired tree may differ from the source — try the `"lxml"` parser and inspect `soup.prettify()[:2000]` to see the actual tree before concluding data is absent.71- **Encoding** → check `<meta charset>` before assuming UTF-8; on `UnicodeDecodeError`, reopen with that charset or pass raw bytes to BeautifulSoup and let it detect.72- **JavaScript-rendered content** → if the data isn't in the file, it never was: say so — no parser will find DOM built at runtime.73- **Fragments** (no `<html>`/`<body>`) → parse and write back as-is; do not let output gain wrapper tags the input lacked (html.parser doesn't add them; lxml does).7475## References76Deeper copy-paste recipes (selectors, table→CSV, rewriting links, sanitizing): see [references/recipes.md](references/recipes.md).77