Component
gelbeseiten-to-xlsx skill
Collect every company on a GelbeSeiten category page and write them to a styled Excel file.
gelbeseiten-to-xlsx skill
A Claude skill that scrapes a GelbeSeiten (German Yellow Pages) category page and turns every business listing on it into a formatted Excel contact list.
Given a URL like https://www.gelbeseiten.de/branchen/maler/oberursel-taunus
the skill collects every company — name, address, phone, email, website,
opening hours, rating, reviews, distance — and writes them to a styled
.xlsx file, optionally deduplicating rows that share the same address.
When to use
Trigger this skill when the user:
- pastes a
gelbeseiten.de/branchen/...URL and wants the companies in a spreadsheet, - asks to "collect all
<trade>in<town>" as an xlsx / contact list, - references a file like
Oberursel-maler.xlsxor asks for a Branchenbuch export.
Do not use it for single-company lookups or for non-GelbeSeiten sources.
Why the scripts exist
A naive scrape doesn't work, for three reasons the skill works around:
- Only the first 50 results are server-rendered. The rest live behind a
"Mehr Anzeigen" button that's unreliable under browser automation. The
skill instead POSTs to GelbeSeiten's own
/ajaxsuchepaging endpoint. - Emails and websites aren't on the listing page — they're on each
company's
/gsbiz/<realid>detail page, mostly inside a JSON-LDLocalBusinessblock. The skill fetches every detail page in parallel from the same origin. - Large result sets can't be returned through
javascript_toolwithout truncation, so the rows are passed out via the clipboard.
Files
| File | Role |
|---|---|
SKILL.md | The procedure Claude follows (inputs, steps, output template, gotchas). |
extract_listings.js | Runs inside the listing page via Claude-in-Chrome. Pages through /ajaxsuche, fetches every detail page, and stashes the rows on window.__rows. |
build_xlsx.py | Reads the extracted JSON and writes the styled workbook. Supports --dedupe to merge rows by address. |
Requirements
- Claude in Chrome MCP (
mcp__Claude_in_Chrome__*) — to drive a real browser session ongelbeseiten.deso same-originfetch()calls work. - Python 3 with
openpyxlforbuild_xlsx.py. - A writable output folder (the script saves wherever you point it).
Usage
The full procedure is in SKILL.md; the short version:
- Confirm inputs with the user: URL, output filename, whether to dedupe by address, and whether to match an existing template.
navigateto the listing URL in Chrome.- Paste
extract_listings.jsintojavascript_tooland runawait extractGelbeSeiten()— it auto-detectsWAS/WOfrom the page's hidden#mod-LoadMoreform, pages through all results, and fetches every detail page concurrently. - Copy the rows out via clipboard (focus the page first):
then read the clipboard and save it asawait navigator.clipboard.writeText(JSON.stringify(window.__rows))<trade>.json. - Build the workbook:
python3 build_xlsx.py <input.json> <output.xlsx> "<Title>" \ [--industry "Malerbetriebe"] [--province Hessen] [--dedupe]<Title>is the emoji + heading, e.g.🎨 Maler – Oberursel (Taunus). The script appends· N Companies · Source: GelbeSeitenautomatically. - Reload the xlsx, verify the row count and headers, spot-check a few rows,
then deliver it with
present_files.
Output format
The workbook has 22 columns and matches the existing Oberursel_taxi.xlsx
template:
#, Company Name, Industry, Business Description, Province, ZIP Code, City,
Street, Contact Person, Telephone 1, Telephone 2, Telephone 3, Email,
Email 2, Website, Social Media, Opening Hours, Rating, # Reviews, Distance,
Badge / Partner, GelbeSeiten URL
Styling:
- Row 1: merged title bar, Arial 11 bold white on navy
#0D2E4E, height 26. - Row 2: column headers, Arial 9 bold white on blue
#1F4E79, wrapped, height 30. - Data: Arial 9, wrapped, alternating band fill
#DEEAF1/ white. - Freeze panes at
C1so#andCompany Namestay visible while scrolling.
Facebook / Instagram links land in Social Media, not Website.
Industry defaults to the trade (e.g. "Malerbetriebe"); Business Description
comes from the JSON-LD keywords field; Province is the German state
(Hessen for the Frankfurt/Taunus area by default).
Dedupe behaviour
With --dedupe, rows are grouped by (ZIP code, normalized street). Within
each group:
- The most complete record wins (most filled fields, then longest name).
- Up to three distinct phone numbers are merged into Telephone 1/2/3.
- Empty fields (
email,web,hours,rating) on the canonical row are filled from siblings when available. - The longest
Business Descriptionis kept.
Street normalization treats Straße / Strasse / Str. / str as
equivalent and strips non-alphanumerics, so "Hauptstraße 12" and
"Hauptstr. 12" collapse correctly.
Reviews
Every review comes from someone who downloaded or purchased this component.
Sign in and download this component to leave a verified review.
- ZHU Julieverified★★★★★Jul 2, 2026
I used this component, this is perfect, works fine! 5 stars.
Comments
2 commentsOpen discussion — ask questions before you download. Anyone can comment.
Sign in to join the discussion.