Llama Web Scraping: Tại sao việc rendering quyết định dữ liệu
Senior Cybersecurity Analyst
Tóm tắt:
- Khoảng cách giữa "không thể trích xuất" và "trích xuất sạch sẽ" là một cuộc gọi render, và hướng dẫn này đo lường nó một cách chính xác. Một yêu cầu GET đơn giản trên một danh mục sản phẩm chỉ có JavaScript trả về một mẫu không được render; cùng một URL thông qua Scrapeless Universal Scraping API với
js_rendertrả về 13 span sản phẩm thực, và Llama đã trích xuất chính xác tất cả 12 sản phẩm thật từ chúng. - Llama 4 là cấp độ rẻ nhất hiện tại, không phải Llama 3.
meta-llama/llama-4-scoutlà Llama thế hệ hiện tại rẻ nhất trên danh mục OpenRouter trực tiếp — một gia đình khác, mới hơn so với tên Llama 3.1 mà hầu hết các hướng dẫn hiện có vẫn sử dụng. - Mô hình đã tự động lọc ra một hàng mẫu bị lỗi. Trang được render thực tế chứa 13 span
product-name; một trong số đó là một placeholder chưa được xử lý${product.name}, và việc trích xuất của Llama đã trả về chính xác 12 sản phẩm thật, bỏ qua sản phẩm giả mà không cần được yêu cầu. - Đây là con đường qua đám mây, không phải cục bộ. Một hướng dẫn riêng trên trang này, Web Scraping with LLaMA 3, đề cập đến việc chạy Llama cục bộ thông qua Ollama; trong khi đó hướng dẫn này chạy Llama 4 thông qua một API được lưu trữ thay thế.
- Chưa có khóa API Llama gốc? Yêu cầu giống hệt chạy qua OpenRouter. Hướng dẫn này đã thực hiện nó trực tiếp trên
meta-llama/llama-4-scoutvà hiển thị đầu ra đã bắt. - Miễn phí để bắt đầu ở phía fetch. Tạo khóa API Scrapeless của bạn tại app.scrapeless.com.
Llama có thể trích xuất các trang web không?
Một điểm cuối Llama được lưu trữ đọc văn bản và trả về các trường; nó không tải các trang, thực thi JavaScript của chúng, hoặc giữ một phiên. Điều đó đúng cho dù mô hình chạy cục bộ thông qua Ollama hay thông qua API đám mây — trọng số mô hình không thay đổi gì về cách HTTP hoạt động. Điều khác biệt giữa con đường cục bộ và đám mây chỉ là nơi diễn ra suy diễn.
Web Scraping with LLaMA 3, đã có trên trang này, đề cập đến lộ trình cục bộ: llama3.1:8b qua Ollama, kết hợp với Selenium chống lại các trang sản phẩm. Hướng dẫn này đề cập đến một nửa khác — một mô hình Llama 4 được lưu trữ được tiếp cận qua một API, không yêu cầu tải mô hình cục bộ và không yêu cầu GPU, trên một mục tiêu demo khác được chọn riêng để chứng minh tại sao lớp fetch quan trọng. Đối với câu hỏi về danh mục rộng hơn, LLM scraper explainer đề cập đến công cụ LLM-như-parser nói chung.
Cài đặt
openai bao gồm con đường OpenRouter (Llama được phục vụ phía sau một bề mặt tương thích OpenAI ở đó), và requests bao gồm lớp fetch:
bash
pip install "llama-api-client==0.6.0" "openai==2.48.0" requests
Cấu hình
bash
export LLAMA_API_KEY="your_llama_api_key"
export SCRAPELESS_API_KEY="sk_your_scrapeless_key"
Lấy một trang mà Llama thực sự có thể đọc
Mục tiêu demo là một trang thực hành render công cộng được xây dựng mục đích để chứng minh chính xác khoảng cách này: lưới sản phẩm của nó trống cho đến khi JavaScript phía client điền vào, và HTML thô thay vào đó chứa một chuỗi literal mẫu chưa được thực thi. Một đoạn mã cho thấy sự khác biệt và lưu phiên bản có giá trị trích xuất từ:
python
# fetch_rendered.py — GET thường so với render phía server, cùng một URL
import os
import requests
URL = "https://www.scrapingcourse.com/javascript-rendering"
MARKER = 'class="product-name"'
plain = requests.get(URL, timeout=60).text
print(f"plain GET: {len(plain):,} ký tự | spans tên sản phẩm: {plain.count(MARKER)}")
resp = requests.post(
"https://api.scrapeless.com/api/v2/unlocker/request",
headers={
"Content-Type": "application/json",
"x-api-token": os.environ["SCRAPELESS_API_KEY"],
},
json={
"actor": "unlocker.webunlocker",
"input": {"url": URL, "method": "GET", "js_render": True},
},
timeout=120,
)
resp.raise_for_status()
rendered = resp.json().get("data", "")
print(f"rendered: {len(rendered):,} ký tự | spans tên sản phẩm: {rendered.count(MARKER)}")
with open("page.html", "w", encoding="utf-8") as f:
f.write(rendered)
Chạy lệnh in ra product-name spans: 1 cho fetch đơn giản — một lần truy cập duy nhất là một mẫu <span class="product-name">${product.name}</span> chưa được thực thi, không phải dữ liệu thực — và product-name spans: 13 cho phiên bản đã được render. Khoảng cách giữa hai cái này chính xác là vòng đời tài liệu mà tiêu chuẩn lập trình HTML định nghĩa: nội dung chỉ tồn tại sau khi các script chạy trên DOM. Việc render và định tuyến proxy xảy ra ở phía máy chủ trong một POST đó — Universal Scraping API chính là lớp fetch, và page.html giờ đây là thứ mà một mô hình có thể trích xuất từ.
Triển khai cơ bản: Llama như một extractor
API Llama chính thức của Meta nhận đầu ra có cấu trúc thông qua response_format={"type": "json_schema", "json_schema": {...}}, theo SDK được phát hành tại repository khách hàng Python cho Llama API của Meta — không có chế độ json_object trống ở điểm cuối này, chỉ có đầu ra có hướng dẫn với schema. Danh mục OpenRouter hiện tại liệt kê meta-llama/llama-4-scout là mô hình Llama 4 thế hệ rẻ nhất; trên API gốc của Meta, ID mô hình tương đương mang định dạng đầy đủ là Llama-4-Scout-17B-16E-Instruct-FP8.
Lưu ý: Khối này cần một
LLAMA_API_KEYcó tín dụng — điều kiện tiên quyết mà hướng dẫn này không giả định. Phần tiếp theo chạy việc trích xuất giống hệt trực tiếp qua OpenRouter, với đầu ra đã được ghi lại.
python
# extract_llama.py — trích xuất API Llama gốc (cần LLAMA_API_KEY)
import json
import os
from llama_api_client import LlamaAPIClient
client = LlamaAPIClient(api_key=os.environ["LLAMA_API_KEY"])
page_html = open("page.html", encoding="utf-8").read()
response = client.chat.completions.create(
model="Llama-4-Scout-17B-16E-Instruct-FP8",
max_completion_tokens=2000,
response_format={
"type": "json_schema",
"json_schema": {
"name": "Products",
"schema": {
"type": "object",
"properties": {
"products": {
"type": "array",
"items": {
"type": "object",
"properties": {"name": {"type": "string"}, "price_usd": {"type": "number"}},
"required": ["name", "price_usd"],
},
}
},
"required": ["products"],
},
},
},
messages=[
{"role": "system", "content": "Trích xuất mọi sản phẩm thực từ trang này. Bỏ qua bất kỳ mẫu chỗ trống nào chưa được render."},
{"role": "user", "content": page_html},
],
)
data = json.loads(response.completion_message.content.text)
print(f"đã trích xuất {len(data['products'])} sản phẩm")
Lưu ý hình dạng phản hồi: Khách hàng gốc của Meta trả về tin nhắn dưới response.completion_message.content.text, không phải đường dẫn choices[0].message.content mà các khách hàng tương thích OpenAI sử dụng.
Không có khóa gốc? Thực hiện qua OpenRouter
OpenRouter cung cấp Llama qua bề mặt chat-completions tương thích với OpenAI giống như các mô hình khác trong chuỗi này. Đây là phiên bản mà hướng dẫn này thực hiện cho thực tế, fetch và trích xuất trong một tập lệnh tự chứa:
python
# extract_openrouter.py — trích xuất tương tự, thực hiện qua OpenRouter
import json
import os
import requests
from openai import OpenAI
URL = "https://www.scrapingcourse.com/javascript-rendering"
resp = requests.post(
"https://api.scrapeless.com/api/v2/unlocker/request",
headers={
"Content-Type": "application/json",
"x-api-token": os.environ["SCRAPELESS_API_KEY"],
},
json={"actor": "unlocker.webunlocker", "input": {"url": URL, "method": "GET", "js_render": True}},
timeout=120,
)
resp.raise_for_status()
page_html = resp.json().get("data", "")
client = OpenAI(base_url="https://openrouter.ai/api/v1", api_key=os.environ["OPENROUTER_API_KEY"])
completion = client.chat.completions.create(
model="meta-llama/llama-4-scout",
temperature=0,
max_tokens=2000,
response_format={"type": "json_object"},
messages=[
{
"role": "system",
"content": 'Trích xuất mọi sản phẩm. Phản hồi CHỈ với JSON: {"products":[{"name":str,"price_usd":number}]}.',
},
{"role": "user", "content": page_html},
],
)
data = json.loads(completion.choices[0].message.content)
print(f"đã trích xuất {len(data['products'])} sản phẩm từ trang đã được render")
for row in data["products"]:
print(json.dumps(row, ensure_ascii=False))
Chạy trực tiếp đã trích xuất chính xác 12 sản phẩm thực, không có mẫu chỗ trống nào:
text
đã trích xuất 12 sản phẩm từ trang đã được render
{"name": "Áo hoodie Chaz Kangeroo", "price_usd": 52}
{"name": "Áo hoodie Teton Pullover", "price_usd": 70}
Cả hai đều làm việc với kiến trúc fetch-then-extract giống nhau. Local, thông qua Ollama, tránh được chi phí mỗi token nhưng cần một máy chủ có GPU và tải mô hình; con đường đám mây trong hướng dẫn này không cần phần cứng cục bộ nhưng tính phí theo từng token. Bài viết kèm theo Web Scraping with LLaMA 3 sẽ đề cập chi tiết đến con đường cục bộ.
H: Tại sao mô hình lại bỏ qua một trong những sản phẩm trên trang đã được hiển thị?
Bởi vì nó không phải là một sản phẩm thực tế. HTML đã được hiển thị trong lần chạy trực tiếp của hướng dẫn này chứa 13 span product-name, nhưng một trong số đó là một dấu chỗ mẫu ${product.name} không được khởi tạo còn sót lại từ framework phía client của trang — mô hình đã đúng khi loại bỏ nó khỏi 12 sản phẩm được trích xuất.
H: Việc scraping với Llama có hợp pháp không?
Lớp trích xuất không thay đổi quy tắc thu thập trên cả con đường đám mây và cục bộ. Chỉ lấy các trang công khai, tôn trọng các điều khoản của trang web và các chỉ thị robots theo tiêu chuẩn được định nghĩa bởi Giao thức loại trừ Robots, giữ cho khối lượng trong giới hạn và xử lý bất kỳ dữ liệu cá nhân nào theo luật hiện hành.
Tại Scrapless, chúng tôi chỉ truy cập dữ liệu có sẵn công khai trong khi tuân thủ nghiêm ngặt các luật, quy định và chính sách bảo mật trang web hiện hành. Nội dung trong blog này chỉ nhằm mục đích trình diễn và không liên quan đến bất kỳ hoạt động bất hợp pháp hoặc vi phạm nào. Chúng tôi không đảm bảo và từ chối mọi trách nhiệm đối với việc sử dụng thông tin từ blog này hoặc các liên kết của bên thứ ba. Trước khi tham gia vào bất kỳ hoạt động cạo nào, hãy tham khảo ý kiến cố vấn pháp lý của bạn và xem xét các điều khoản dịch vụ của trang web mục tiêu hoặc có được các quyền cần thiết.



