Skip to main content
Test generic extractors (newspaper, trafilatura) first. Only use custom selectors if they fail.

Discovery Workflow

1

Inspect article page

2

Analyze HTML structure

3

Test selectors

4

Search for specific fields

Extractor Order Options

Generic Extractors

Best for: Clean news articles and blog posts
What it extracts:
  • Title
  • Author
  • Published date
  • Main content
  • Top image
  • Keywords
  • Summary
Generic extractors work for ~80% of news/blog sites. Try them first before creating custom selectors.

Custom Selectors

Standard fields (title, author, content, date) → main DB columns. Any other field → stored in metadata JSON column.

News Article

spider.json

E-commerce Product

spider.json

Forum Thread

spider.json

Playwright Extractor

Basic Configuration

spider.json
Settings:
  • PLAYWRIGHT_WAIT_SELECTOR: CSS selector to wait for (max 30s)
  • PLAYWRIGHT_DELAY: Extra seconds after page load

Infinite Scroll

spider.json
Settings:
  • INFINITE_SCROLL: Enable scroll behavior (default: false)
  • MAX_SCROLLS: Max scrolls to perform (default: 5)
  • SCROLL_DELAY: Seconds between scrolls (default: 1.0)

Complete Playwright Example

spa_spider.json

Selector Discovery Principles

  • Target main content element (not navigation, sidebar, footer)
  • Selector should match ONE unique element
  • Prefer specific classes (.article-title over .title)
  • Test on multiple pages
  • Prefer semantic tags (<article>, <time>, <h1>)
  • Validate content length (>500 chars for content, >10 for title)
  • Avoid dynamic/generated class names
Common mistakes:
  • Selector matches multiple elements
  • Targets sidebar/footer instead of main content
  • Overly generic selectors like div.text

Identifying JS-Rendered Sites

Playwright Wait: Common Selectors

Article sites:
  • .article-content
  • #main-content
  • article.post
  • [data-loaded="true"]
Product pages:
  • .product-details
  • .price-container
  • #product-info
Social/Forums:
  • .post-list
  • #posts
  • .loaded
Generic:
  • .content-loaded
  • [data-ready]
  • .main-container

Implementation Details

Extractor classes (from source: core/extractors.py):

NewspaperExtractor

extractors.py:36-78Uses newspaper4k library

TrafilaturaExtractor

extractors.py:80-128Uses trafilatura library

CustomExtractor

extractors.py:131-257Uses BeautifulSoup + CSS selectors

SmartExtractor

extractors.py:259-464Tries multiple strategies in order

PlaywrightExtractor

extractors.py:398-464Async browser rendering

Troubleshooting

Generic Extractors Return Empty Content

  1. Check if JS-rendered (empty <div id="app"></div>)
  2. Try Playwright: {"EXTRACTOR_ORDER": ["playwright", "trafilatura"]}
  3. Use custom selectors: {"EXTRACTOR_ORDER": ["custom", "trafilatura"]}

Custom Selector Returns None

  1. Test selector: ./scrapai analyze page.html --test "your-selector"
  2. Check selector specificity and uniqueness
  3. Verify element exists in HTML structure

Playwright Timeout

  1. Increase delay: {"PLAYWRIGHT_DELAY": 10}
  2. Use different wait selector that appears earlier
  3. Verify selector exists in rendered page

Content Extracted But Wrong

  1. Verify selector uniqueness (may match sidebar/footer)
  2. Make selector more specific: {"content": "main article.post div.body"}
  3. Test on multiple pages

Best Practices

  1. Start with generic extractors: ["newspaper", "trafilatura"] (80% success rate)
  2. Add custom selectors if needed: ["custom", "trafilatura"]
  3. Use Playwright for JS-rendered sites: ["playwright", "trafilatura"]
  4. Test on multiple pages
  5. Monitor quality: ./scrapai show 1 --project proj

Custom Callbacks

Extract structured data with callbacks

Data Processors

Transform extracted data