[Bug]: Text after an inline <link>, <meta>, <style> or <noscript> is dropped from cleaned_html and markdown
I maintainer di solito rispondono entro 3 giorni
Valutazione
- Difficoltà
- 2/5
- Tempo stimato
- 1-3 ore
- Idoneità per principianti
- 85/100
Direzione di ricerca
Leggi il ciclo di rimozione dei tag in crawl4ai/content_scraping_strategy.py intorno alle righe 827–830 e confronta il comportamento di remove() con l’approccio drop_tree() descritto nell’issue e nell’issue correlata #2377. Riproduci il problema con lo snippet HTML fornito e conferma che il testo successivo a ciascun elemento rimosso rimane in cleaned_html e nel Markdown.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
crawl4ai version
0.9.4 (reproduced). The same code is in v0.9.5 and on main and develop (checked 2026-10-19).
Expected Behavior
When the scraper strips <style>, <link>, <meta> and <noscript> from the body, the text that follows each of them stays in cleaned_html and in the markdown.
Current Behavior
The text that follows each removed element is lost. LXMLWebScrapingStrategy._scrap removes these tags with lxml's remove() (crawl4ai/content_scraping_strategy.py, lines 827-830 in v0.9.5):
for tag in ["style", "link", "meta", "noscript"]:
for element in body.xpath(f".//{tag}"):
if element.getparent() is not None:
element.getparent().remove(element)
lxml stores the text after an element as that element's .tail, and remove() discards it together with the element.
Wikipedia articles are hit in particular, because MediaWiki puts <link rel="mw:PageProp/Category"> inside paragraphs. https://en.wikipedia.org/wiki/Tokyo has 18 such <link> elements followed by text inside a <p>; one of them is followed by ", Tokyo is home to 26 of the world's 500 largest companies, ...", which never reaches the output. The crawl still reports success, so nothing signals the loss.
Is this reproducible?
Yes
Inputs Causing the Bug
Any HTML where <link>, <meta>, <style> or <noscript> is followed by text in the same parent, for example https://en.wikipedia.org/wiki/Tokyo.
Steps to Reproduce
- Run the snippet below.
- Compare the printed markdown with the paragraphs in
HTML.
Code snippets
import asyncio
from crawl4ai import AsyncWebCrawler, CrawlerRunConfig, CacheMode
HTML = """<html><body><article>
<p>The port grew quickly, and as of 2020<link rel="mw:PageProp/Category" href="/x">, it handles more cargo than any other port.</p>
<p>The old warehouses stood on the quay<meta property="mw:PageProp/toc"> until the great fire destroyed them.</p>
<p>Styled text<style>.a{color:red}</style> continues after a style element.</p>
<p>Plain text<noscript>Enable JavaScript</noscript> continues after a noscript element.</p>
</article></body></html>"""
async def main():
async with AsyncWebCrawler() as crawler:
result = await crawler.arun("raw:" + HTML, config=CrawlerRunConfig(cache_mode=CacheMode.BYPASS))
print(result.markdown.raw_markdown)
asyncio.run(main())
Output on 0.9.4:
The port grew quickly, and as of 2020
The old warehouses stood on the quay
Styled text
Plain text
Expected:
The port grew quickly, and as of 2020, it handles more cargo than any other port.
The old warehouses stood on the quay until the great fire destroyed them.
Styled text continues after a style element.
Plain text continues after a noscript element.
Suggested fix
Replace element.getparent().remove(element) with element.drop_tree(). drop_tree() comes with lxml.html and moves the element's tail text onto the previous sibling or the parent. With this one-line change the snippet prints the expected output above.
Related:
- #1938 / #1939 fixed the same loss in
remove_empty_elements_fast()by moving.tailby hand. - #2377 (open) fixes it for links removed by
exclude_external_linksand similar options, usingdrop_tree().
This loop is a third place with the same pattern.
OS
Debian GNU/Linux 12 (bookworm), in the official unclecode/crawl4ai:0.9.4 Docker image (lxml 6.1.3)
Python version
3.12.14
Error logs & Screenshots (if applicable)
None. The crawl succeeds and the text is silently missing.
- Lingua principale
- Python
- Stelle
- 85.9k
- Fork
- 8.9k
- Merge medio
- 5g 6h
- PR unite (30g)
- 24
Preparare l'ambiente
- Include un Dockerfile o un file Docker Compose
- Ha un modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di unclecode/crawl4ai
-
[Bug]: Since 0.9.1, Linux launches chrome-headless-shell instead of ChromiumForse già presa Una pull request collegata a questa issue è aperta o già unita. Aperta🐞 Bug 🩺 Needs Triage
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
unclecode/crawl4ai#2382 · 1 commento ·
I maintainer di solito rispondono entro 3 giorni
-
[Bug]: BestFirstCrawlingStrategy fetches a full batch past max_pagesForse già presa Una pull request collegata a questa issue è aperta o già unita. Aperta🐞 Bug 🩺 Needs Triage
Difficoltà 2/5 1-3 ore Idoneità per principianti 74/100
unclecode/crawl4ai#2381 · 1 commento ·
I maintainer di solito rispondono entro 3 giorni
-
[Bug]: CrawlerRunConfig.clone() drops fallback_fetch_function, so deep crawls never use itForse già presa @siva23367 l’ha presa 2 giorni fa. Aperta🐞 Bug 🩺 Needs Triage
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
unclecode/crawl4ai#2379 · 1 commento ·
I maintainer di solito rispondono entro 3 giorni
-
[Bug]: Docker memory guard reads host RAM when no container limit is set — cgroup v2 "max" defeats get_container_memory_percentForse già presa @Battleplus l’ha presa 58 giorni fa. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
unclecode/crawl4ai#2123 · 1 commento ·
I maintainer di solito rispondono entro 3 giorni
-
[Bug]: Docker server egress proxy resolves DNS synchronously on the event loop, stalling the whole server under loadForse già presa Una pull request collegata a questa issue è aperta o già unita. Aperta
Difficoltà 3/5 1-2 giorni Idoneità per principianti 72/100
I maintainer di solito rispondono entro 3 giorni
Tutte le issue di unclecode/crawl4ai
Issue simili
-
bug good first issue
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
yunaremaia/proto-drift#22 ·
-
bug good first issue
Difficoltà 2/5 1-3 ore Idoneità per principianti 82/100
yunaremaia/memwatch#96 ·
-
bug good first issue
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 91/100
yunaremaia/ci-gate-watch#34 ·
-
bug good first issue
Difficoltà 2/5 1-3 ore Idoneità per principianti 85/100
yunaremaia/agent-capability-attestation#64 ·
I maintainer di solito rispondono entro 1 giorno
-
bug good first issue
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 86/100
yunaremaia/agent-call-graph#43 ·
I maintainer di solito rispondono entro 1 giorno