{"slug": "when-html-parsing-fails-using-llms-to-extract-messy-web-data", "title": "When HTML parsing fails: using LLMs to extract messy web data", "summary": "A developer turned to large language models to extract product data from e-commerce sites with unpredictable HTML, after traditional scraping tools like BeautifulSoup and Scrapy failed due to constantly changing page structures. By feeding raw HTML to OpenAI's GPT-4o with a defined JSON schema, the engineer successfully extracted fields such as product names, prices, and availability on the first attempt, bypassing the need for fragile CSS selectors or XPath expressions. The approach combines LLM-based extraction for problematic sites with traditional parsers for stable ones, and includes validation steps to catch errors.", "body_md": "I’ve been scraping websites for years. BeautifulSoup, Scrapy, Playwright — I’ve used them all. But last month I hit a wall.\n\nA client needed me to extract product details from a dozen e-commerce sites. Most were straightforward: find the right CSS selectors, handle pagination, done. But one particular site was a nightmare. The HTML was a mess of nested divs, inline styles, and data scattered across attributes, text nodes, and even JavaScript variables. The layout changed every week. My carefully crafted selectors broke constantly.\n\nI spent two days fixing and refactoring. Every time I thought I had it, the site updated and my pipeline broke again. I was about to tell the client it wasn’t feasible.\n\nThen a colleague said: “Why not just give the raw HTML to an LLM and ask it to extract what you need?”\n\nAt first I laughed. LLMs hallucinate, they’re slow, expensive — right? But I was desperate. I decided to prototype it.\n\nBefore going down the AI route, I exhausted traditional approaches:\n\n`data-price`\n\nattributes, sometimes in nested `<span>`\n\ns.`product-price`\n\nto `price-info`\n\nand my whole script died.The root problem: **the HTML structure was unpredictable**. A human can look at a page and say “that’s the price”. A CSS selector cannot — it relies on structure.\n\nI built a small script that takes raw HTML, sends it to an LLM (I used OpenAI’s GPT-4o, but you can use any model that can handle long contexts), and asks it to return a JSON object according to a schema I define.\n\nThe key insight: **instead of teaching the computer where the data is, I teach it what the data looks like**. I provide a description and let the LLM figure out the mapping.\n\nHere’s a simplified version:\n\n``` python\nimport openai\nfrom bs4 import BeautifulSoup\n\n# Fetch the page (I'll use requests here, but you might need Playwright for dynamic sites)\nimport requests\n\nresponse = requests.get(\"https://example.com/product-page\")\nraw_html = response.text\n\n# Clean up HTML a bit - remove scripts, styles, reduce noise\nsoup = BeautifulSoup(raw_html, \"html.parser\")\nfor tag in soup([\"script\", \"style\", \"meta\", \"link\", \"svg\"]):\n    tag.decompose()\ncleaned_html = str(soup)[:12000]  # limit context size\n\n# Define the schema\nschema = {\n    \"product_name\": \"string\",\n    \"price\": \"string (e.g., '$19.99')\",\n    \"availability\": \"string ('In Stock' or 'Out of Stock')\",\n    \"description\": \"string\",\n    \"rating\": \"string (e.g., '4.5 out of 5')\"\n}\n\n# Call the LLM\nprompt = f\"\"\"\nExtract the following fields from this HTML and return a valid JSON object.\nFields: {schema}\n\nHTML:\n{cleaned_html}\n\nReturn ONLY the JSON object, no explanation.\n\"\"\"\n\nclient = openai.OpenAI(api_key=\"sk-...\")\nresponse = client.chat.completions.create(\n    model=\"gpt-4o\",\n    messages=[{\"role\": \"user\", \"content\": prompt}],\n    temperature=0.0,\n)\n\ntry:\n    import json\n    result = json.loads(response.choices[0].message.content)\n    print(result)\nexcept json.JSONDecodeError:\n    print(\"LLM did not return valid JSON. Retrying...\")\n```\n\nThat’s it. For the problematic site, this worked on the first try. No selectors, no XPath, no regular expressions. I just described what I wanted and the LLM figured out the rest.\n\nI’ve used this approach for a few weeks now, and here’s what I learned:\n\nI’d combine approaches. Use traditional parsers for stable sites, and fall back to LLM only for tricky ones. Also, I’d implement a validation step: check that extracted prices look like prices, ratings are within range, etc. If validation fails, re-run with a different prompt or a more powerful model.\n\nAnother improvement: provide the LLM with a few examples (few-shot prompting) to improve accuracy on ambiguous fields.\n\nI’m not the only one doing this. There are now services that wrap this idea into nice APIs. For example, I came across [InterWest AI](https://ai.interwestinfo.com/) which offers a similar extraction API. I haven’t used it extensively, but it’s interesting to see this pattern being productized.\n\nLLM-based extraction isn’t a silver bullet. It’s expensive and slow. But for the 10% of cases where traditional parsing fails — changing layouts, inconsistent HTML, or just pure laziness — it’s a lifesaver.\n\nI’m still torn. Part of me feels like I’m cheating by throwing AI at a problem that used to require elegant code. But then again, the site’s layout changes every week, and I have better things to do than update selectors.\n\nWhat’s your experience with extracting data from messy websites? Have you tried AI-based parsing, or do you still prefer the precision of XPath and CSS? I’d love to hear how others handle this.", "url": "https://wpnews.pro/news/when-html-parsing-fails-using-llms-to-extract-messy-web-data", "canonical_source": "https://dev.to/__c1b9e06dc90a7e0a676b/when-html-parsing-fails-using-llms-to-extract-messy-web-data-20ab", "published_at": "2026-06-05 08:34:43+00:00", "updated_at": "2026-06-05 08:42:45.085147+00:00", "lang": "en", "topics": ["large-language-models", "artificial-intelligence", "ai-tools", "ai-products", "natural-language-processing"], "entities": ["BeautifulSoup", "Scrapy", "Playwright", "OpenAI", "GPT-4o"], "alternates": {"html": "https://wpnews.pro/news/when-html-parsing-fails-using-llms-to-extract-messy-web-data", "markdown": "https://wpnews.pro/news/when-html-parsing-fails-using-llms-to-extract-messy-web-data.md", "text": "https://wpnews.pro/news/when-html-parsing-fails-using-llms-to-extract-messy-web-data.txt", "jsonld": "https://wpnews.pro/news/when-html-parsing-fails-using-llms-to-extract-messy-web-data.jsonld"}}