惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Martin Fowler
Martin Fowler
有赞技术团队
有赞技术团队
博客园_首页
H
Help Net Security
GbyAI
GbyAI
aimingoo的专栏
aimingoo的专栏
V
Visual Studio Blog
The Cloudflare Blog
腾讯CDC
Jina AI
Jina AI
Last Week in AI
Last Week in AI
月光博客
月光博客
博客园 - 叶小钗
Google DeepMind News
Google DeepMind News
B
Blog RSS Feed
Blog — PlanetScale
Blog — PlanetScale
人人都是产品经理
人人都是产品经理
Engineering at Meta
Engineering at Meta
Y
Y Combinator Blog
Hugging Face - Blog
Hugging Face - Blog
博客园 - 聂微东
爱范儿
爱范儿
N
Netflix TechBlog - Medium
F
Fortinet All Blogs

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant
Scraping Dynamic Web Pages Without Selectors Using AI Vis...
Paras Tejpal · 2026-06-19 · via DEV Community

Paras Tejpal

****# Scraping Dynamic Web Pages Without Selectors Using AI Vision (TypeScript/JavaScript Tutorial)

Web scraping has traditionally been a game of cat-and-mouse. You spend hours writing fine-tuned CSS selectors or XPath paths, only for the website to change its layout or class names (especially on modern frameworks with generated CSS class names like css-1ux802d), breaking your entire data pipeline overnight.

In this tutorial, we will learn how to build a selector-free scraper using Opticparse, an AI-powered scraping tool that captures webpage screenshots and uses Gemini's multimodal vision intelligence to extract structured JSON data.

We will use the official Opticparse JavaScript/TypeScript SDK to extract data in less than 10 lines of code.


The Concept: AI Vision Scraping

Instead of parsing HTML source code directly, Opticparse:

  1. Launches a headless Chromium instance using Playwright.
  2. Navigates to the target page and takes a full-page snapshot.
  3. Passes the screenshot to an AI Vision Agent (Gemini) along with a text prompt.
  4. Returns clean, parsed JSON matching your description.

Because it mimics how a real human looks at the page, it does not care about dynamic CSS class name changes, shadow DOMs, or obfuscated HTML.


Setup & Installation

Install the official client library:

npm install opticparse-js

Get Your API Key

You can get an API key in two ways:

  1. RapidAPI Hub: Access the API globally on the RapidAPI Opticparse Listing. Subscribe to the Free basic tier to get a RapidAPI Key.
  2. Private Host: If you hosted the Docker microservice container yourself (e.g. on Render), use your private OPTICPARSE_API_KEY.

Code Example: Scraping Hacker News

Let's say we want to scrape the top 5 articles, their link URLs, and score points from the homepage of Hacker News.

Here is how you do it:

import { OpticparseClient } from 'opticparse-js';

// Initialize the client. 
// If using the RapidAPI marketplace, set useRapidApi: true
const client = new OpticparseClient({
  apiKey: 'YOUR_RAPIDAPI_KEY_HERE',
  useRapidApi: true
});

async function runScrape() {
  console.log('Scraping Hacker News articles...');

  try {
    const data = await client.scrape({
      targetUrl: 'https://news.ycombinator.com',
      extractionQuery: 'Extract the top 5 article titles, their link URLs, and score points as a JSON list of objects.',
      viewportWidth: 1280,
      viewportHeight: 1000
    });

    console.log('Scraped Data Output:');
    console.log(JSON.stringify(data, null, 2));

  } catch (error) {
    console.error('Scraping failed:', error);
  }
}

runScrape();

Sample Output

The client will automatically handle the asynchronous execution, image loading, and return a clean, fully-typed JSON structure:

[
  {
    "title": "Why I still use Vim",
    "url": "https://example.com/vim",
    "points": 142
  },
  {
    "title": "Show HN: Opticparse - AI Visual Scraper",
    "url": "https://github.com/parastejpal987-cmyk/opticparse",
    "points": 98
  }
]


Advanced Options

The SDK client supports configuring the browser environment to handle dynamic loading states:


typescript
const result = await client.scrape({
  targetUrl: 'https://example.com',
  extractionQuery: 'Extract details...',

  // Custom screen sizes for responsive layouts
  viewportWidth: 1920,
  viewportHeight: 1080,

  // Wait until page is completely loaded ('networkidle' | 'load' | 'domcontentloaded')
  waitUntil: 'networkidle',

  // Adjust timeout threshold (in milliseconds) for slower connec