页面交互
Crawl4AI 提供强大的功能,可用于与动态网页交互、处理 JavaScript 执行、等待条件以及管理多步骤流程。通过组合 js_code、wait_for 和某些 CrawlerRunConfig 参数,您可以:
- 点击“加载更多”按钮
- 填写表格并提交
- 等待元素或数据出现
- 跨多个步骤重复使用会话
下面是关于如何操作的简要概述。
1. JavaScript执行
基本执行
在CrawlerRunConfig
接受单个 JS 字符串或 JS 代码片段列表。示例:我们将滚动到页面底部,然后选择点击“加载更多”按钮。
import asyncio
from crawl4ai import AsyncWebCrawler, CrawlerRunConfig
async def main():
# Single JS command
config = CrawlerRunConfig(
js_code="window.scrollTo(0, document.body.scrollHeight);"
)
async with AsyncWebCrawler() as crawler:
result = await crawler.arun(
url="https://news.ycombinator.com", # Example site
config=config
)
print("Crawled length:", len(result.cleaned_html))
# Multiple commands
js_commands = [
"window.scrollTo(0, document.body.scrollHeight);",
# 'More' link on Hacker News
"document.querySelector('a.morelink')?.click();",
]
config = CrawlerRunConfig(js_code=js_commands)
async with AsyncWebCrawler() as crawler:
result = await crawler.arun(
url="https://news.ycombinator.com", # Another pass
config=config
)
print("After scroll+click, length:", len(result.cleaned_html))
if __name__ == "__main__":
asyncio.run(main())
相关的CrawlerRunConfig
参数:-js_code
:页面加载后运行的 JavaScript 字符串或字符串列表。 -js_only
:如果设置为True
在后续调用中,表示我们将继续现有会话,而无需新的完整导航。-session_id
:如果您想在多次调用中保持相同的页面,请指定一个 ID。
2.等待条件
2.1 基于 CSS 的等待
有时,你只想等待特定元素出现。例如:
import asyncio
from crawl4ai import AsyncWebCrawler, CrawlerRunConfig
async def main():
config = CrawlerRunConfig(
# Wait for at least 30 items on Hacker News
wait_for="css:.athing:nth-child(30)"
)
async with AsyncWebCrawler() as crawler:
result = await crawler.arun(
url="https://news.ycombinator.com",
config=config
)
print("We have at least 30 items loaded!")
# Rough check
print("Total items in HTML:", result.cleaned_html.count("athing"))
if __name__ == "__main__":
asyncio.run(main())
关键参数:-wait_for="css:..."
:告诉爬虫等待 CSS 选择器出现。
2.2 基于 JavaScript 的等待
对于更复杂的条件(例如,等待内容长度超过阈值),前缀js:
:
wait_condition = """() => {
const items = document.querySelectorAll('.athing');
return items.length > 50; // Wait for at least 51 items
}"""
config = CrawlerRunConfig(wait_for=f"js:{wait_condition}")
幕后:Crawl4AI 持续轮询 JS 函数,直到返回true
或者发生超时。
3.处理动态内容
许多现代网站需要多个步骤:滚动、点击“加载更多”或通过 JavaScript 更新。以下是一些典型的模式。
3.1 加载更多示例(Hacker News“更多”链接)
import asyncio
from crawl4ai import AsyncWebCrawler, CrawlerRunConfig
async def main():
# Step 1: Load initial Hacker News page
config = CrawlerRunConfig(
wait_for="css:.athing:nth-child(30)" # Wait for 30 items
)
async with AsyncWebCrawler() as crawler:
result = await crawler.arun(
url="https://news.ycombinator.com",
config=config
)
print("Initial items loaded.")
# Step 2: Let's scroll and click the "More" link
load_more_js = [
"window.scrollTo(0, document.body.scrollHeight);",
# The "More" link at page bottom
"document.querySelector('a.morelink')?.click();"
]
next_page_conf = CrawlerRunConfig(
js_code=load_more_js,
wait_for="""js:() => {
return document.querySelectorAll('.athing').length > 30;
}""",
# Mark that we do not re-navigate, but run JS in the same session:
js_only=True,
session_id="hn_session"
)
# Re-use the same crawler session
result2 = await crawler.arun(
url="https://news.ycombinator.com", # same URL but continuing session
config=next_page_conf
)
total_items = result2.cleaned_html.count("athing")
print("Items after load-more:", total_items)
if __name__ == "__main__":
asyncio.run(main())
关键参数:-session_id="hn_session"
:在多次调用时保持同一页面arun()
.-js_only=True
:我们不执行完全重新加载,只是在现有页面中应用 JS。 -wait_for
和js:
:等待项目数量超过 30。
3.2 表单交互
如果网站有搜索或登录表单,您可以填写字段并提交js_code
。例如,如果 GitHub 有一个本地搜索表单:
js_form_interaction = """
document.querySelector('#your-search').value = 'TypeScript commits';
document.querySelector('form').submit();
"""
config = CrawlerRunConfig(
js_code=js_form_interaction,
wait_for="css:.commit"
)
result = await crawler.arun(url="https://github.com/search", config=config)
实际上:用真实站点的表单选择器替换 ID 或类。
4. 时序控制
1.page_timeout
(毫秒):整体页面加载或脚本执行的时间限制。2.delay_before_return_html
(秒):等待片刻再捕获最终的 HTML。3.mean_delay
&max_range
:如果你打电话arun_many()
对于多个 URL,这些会在每个请求之间添加一个随机暂停。
例子:
5. 多步骤交互示例
下面是一个简化的脚本,它在 GitHub 的 TypeScript 提交页面上执行多次“加载更多”操作。它每次都重复使用同一个会话来累积新的提交。代码包含相关的CrawlerRunConfig
您所依赖的参数。
import asyncio
from crawl4ai import AsyncWebCrawler, BrowserConfig, CrawlerRunConfig, CacheMode
async def multi_page_commits():
browser_cfg = BrowserConfig(
headless=False, # Visible for demonstration
verbose=True
)
session_id = "github_ts_commits"
base_wait = """js:() => {
const commits = document.querySelectorAll('li.Box-sc-g0xbh4-0 h4');
return commits.length > 0;
}"""
# Step 1: Load initial commits
config1 = CrawlerRunConfig(
wait_for=base_wait,
session_id=session_id,
cache_mode=CacheMode.BYPASS,
# Not using js_only yet since it's our first load
)
async with AsyncWebCrawler(config=browser_cfg) as crawler:
result = await crawler.arun(
url="https://github.com/microsoft/TypeScript/commits/main",
config=config1
)
print("Initial commits loaded. Count:", result.cleaned_html.count("commit"))
# Step 2: For subsequent pages, we run JS to click 'Next Page' if it exists
js_next_page = """
const selector = 'a[data-testid="pagination-next-button"]';
const button = document.querySelector(selector);
if (button) button.click();
"""
# Wait until new commits appear
wait_for_more = """js:() => {
const commits = document.querySelectorAll('li.Box-sc-g0xbh4-0 h4');
if (!window.firstCommit && commits.length>0) {
window.firstCommit = commits[0].textContent;
return false;
}
// If top commit changes, we have new commits
const topNow = commits[0]?.textContent.trim();
return topNow && topNow !== window.firstCommit;
}"""
for page in range(2): # let's do 2 more "Next" pages
config_next = CrawlerRunConfig(
session_id=session_id,
js_code=js_next_page,
wait_for=wait_for_more,
js_only=True, # We're continuing from the open tab
cache_mode=CacheMode.BYPASS
)
result2 = await crawler.arun(
url="https://github.com/microsoft/TypeScript/commits/main",
config=config_next
)
print(f"Page {page+2} commits count:", result2.cleaned_html.count("commit"))
# Optionally kill session
await crawler.crawler_strategy.kill_session(session_id)
async def main():
await multi_page_commits()
if __name__ == "__main__":
asyncio.run(main())
要点:
- :保持同一页面打开。
- +
wait_for
+js_only=True
:我们进行部分刷新,等待新的提交出现。 - 确保我们每一步都能看到最新的数据。
6. 结合互动与提取
一旦动态内容加载完毕,您可以附加extraction_strategy
(喜欢JsonCssExtractionStrategy
或者LLMExtractionStrategy
)。 例如:
from crawl4ai import JsonCssExtractionStrategy
schema = {
"name": "Commits",
"baseSelector": "li.Box-sc-g0xbh4-0",
"fields": [
{"name": "title", "selector": "h4.markdown-title", "type": "text"}
]
}
config = CrawlerRunConfig(
session_id="ts_commits_session",
js_code=js_next_page,
wait_for=wait_for_more,
extraction_strategy=JsonCssExtractionStrategy(schema)
)
完成后,检查result.extracted_content
用于 JSON。
7.相关CrawlerRunConfig
参数
以下是与交互相关的关键参数CrawlerRunConfig
。有关完整列表,请参阅配置参数。
- :初始加载后运行的 JavaScript。
- : 如果
True
,没有新的页面导航——只有现有会话中的 JS。 - :CSS(
"css:..."
) 或 JS ("js:..."
) 表达式来等待。 - :在各个呼叫之间重复使用同一页面。
- :是从缓存读取/写入还是绕过。
- :自动删除某些弹出窗口。
- ,
override_navigator
,magic
:反机器人或“类人”互动。
8. 结论
Crawl4AI 的页面交互功能可让您:
1. 执行 JavaScript 以执行滚动、点击或表单填写操作。2. 等待 CSS 或自定义 JS 条件满足后再捕获数据。3. 使用部分重新加载或持久会话处理多步骤流程(例如“加载更多”)。4. 结合结构化提取功能,实现动态网站。
使用这些工具,您可以自信地抓取现代化的交互式网页。如需高级挂钩、用户模拟或深入配置,请参阅API 参考或相关的高级文档。祝您脚本编写愉快!
9.虚拟滚动
对于使用虚拟滚动的网站(滚动时内容会被替换而不是追加,例如 Twitter 或 Instagram),Crawl4AI 提供了专用VirtualScrollConfig
:
from crawl4ai import AsyncWebCrawler, CrawlerRunConfig, VirtualScrollConfig
async def crawl_twitter_timeline():
# Configure virtual scroll for Twitter-like feeds
virtual_config = VirtualScrollConfig(
container_selector="[data-testid='primaryColumn']", # Twitter's main column
scroll_count=30, # Scroll 30 times
scroll_by="container_height", # Scroll by container height each time
wait_after_scroll=1.0 # Wait 1 second after each scroll
)
config = CrawlerRunConfig(
virtual_scroll_config=virtual_config
)
async with AsyncWebCrawler() as crawler:
result = await crawler.arun(
url="https://twitter.com/search?q=AI",
config=config
)
# result.html now contains ALL tweets from the virtual scroll
虚拟滚动 vs JavaScript 滚动
特征 | 虚拟卷轴 | JS代码滚动 |
---|---|---|
用例 | 滚动期间替换的内容 | 附加内容或简单滚动 |
配置 | 目的 | 使用滚动命令 |
自动合并 | 是 - 合并所有独特内容 | 否 - 仅捕获最终状态 |
最适合 | Twitter、Instagram、虚拟桌子 | 传统页面,加载更多按钮 |
有关详细示例和配置选项,请参阅虚拟滚动文档。