跳转到主要内容

交互函数

本文列出了在 IDE 中使用交互代码编写抓取器时可用的命令,并对其进行了说明。
标有星号 的命令是 Bright Data 开发的专有功能。

bad_input

将抓取器输入标记为无效。将阻止任何抓取重试 error_code=bad_input
bad_input();
bad_input('缺少搜索词');

blocked

将页面标记为失败,因为网站拒绝访问 (error_code=blocked)
blocked();
blocked('显示了登录页面');

bounding_box

描述元素区域的坐标框(相对于页面,而非浏览器视口)。只会测量第一个匹配的元素。
  • selector:元素的有效 CSS 选择器
let box = bounding_box('.product-list');
// box == {
//   top: 10,
//   right: 800,
//   bottom: 210,
//   left: 200,
//   x: 200,
//   y: 10,
//   width: 600,
//   height: 200,
// }

browser_size

返回当前浏览器窗口大小
TBD

capture_graphql

捕获并重放 graphql 请求,同时更改变量
  • options:控制要捕获的 graphql 请求的参数
    • url
    • payload
let q = capture_graphql({
    payload: {id: 'ProfileQuery'},
    // 如果 graphql 端点不是默认值 "*/graphql",则可能需要使用正则表达式传递 url 选项
    // url: /\bgraphql\b/ // 默认值
});

navigate('https://example.com');

let [first_query, first_response] = q.wait_captured();

collect(first_response.data.profile);

let second = q.replay({
    variables: {other_id: 2},
});

collect(second.data.profile);

click

点击元素(会在元素出现后再点击)
  • selector:元素选择器
click('#show-more');
$('#show-more').click()
// 点击与传入坐标最接近的元素(相对于页面)。
// 例如,点击地图中心的标记
let box = bounding_box('#map')
let center = {x: (box.left+box.right)/2, y: (box.top+box.bottom)/2};
click('.map-pin', {coordinates: center});

close_popup

弹出窗口可能在抓取过程中随时出现,您不一定能确定何时等待或关闭它们。在代码顶部添加 close_popup() 可创建后台监视器,当弹出窗口出现时自动关闭。如果弹出窗口多次出现,它将始终被关闭
  • popup selector:有效 CSS 选择器
  • close selector:有效 CSS 选择器
  • options:click_inside:包含关闭按钮选择器的父 iframe 选择器
close_popup('.popup', '.popup_close');
close_popup('iframe.with-popup', '.popup_close', {click_inside: 'iframe.with-popup'});

collect

向爬虫创建的数据集中添加一行数据 语法collect(<data_line>[, <validate_fn>]);
  • data_line:包含要收集字段的对象
  • validate_fn:可选函数,用于检查数据行是否有效
collect({price: data.price});
collect(product, p=>{
    if (!p.title)
        throw new Error('产品缺少标题');
})

console

记录交互代码的消息
console.log(1, 'brightdata', [1, 2], {key: value});
console.error(1, 'brightdata', [1, 2], {key: value});

country

配置抓取器从指定国家运行 语法country(<code>);
  • code:2 位 ISO 国家代码
country('us');

dead_page

将页面标记为死链接,以便在未来收集中进行过滤 error_code=dead_page
dead_page();
dead_page('产品已移除');

detect_block

检测页面阻止
  • resource:指定检测所需资源的对象
    • selector
  • condition:指定资源如何处理以进行检测的对象
    • exists
    • has_text
detect_block({selector: '.foo'}, {exists: true});
detect_block({selector: '.bar'}, {has_text: 'text'});
detect_block({selector: '.baz'}, {has_text: /regex_pattern/});

disable_event_listeners

停止页面上所有事件监听器运行。必须先调用 track_event_listeners()
  • event_types:应禁用的特定事件类型
disable_event_listeners();
disable_event_listeners(['hover', 'click']);

el_exists

检查页面元素是否存在,并返回布尔值
  • selector:有效 CSS 选择器
  • timeout:等待元素出现的超时时间
el_exists('#example'); // => true
el_exists('.does_not_exist'); // => false
el_exists('.does_not_exist', 5e3); // => false(5 秒后)

el_is_visible

检查页面元素是否可见
  • selector:有效 CSS 选择器
  • timeout:等待元素可见的超时时间
el_is_visible('#example');
el_is_visible('.is_not_visible', 5e3); // false(5 秒后)

embed_html_comment

在页面 HTML 中添加注释。可用于在 HTML 快照中嵌入元数据。
  • comment:注释内容
embed_html_comment('trace-id: asdf123');

font_exists

断言浏览器在页面上渲染指定字体家族的能力 语法font_exists(<font-family>);
font_exists('Liberation Mono');

freeze_page

强制页面停止变化,可用于在抓取后保存页面特定状态,以便快照看到的页面状态与当前一致。此命令为实验性,如发现问题,请报告支持
freeze_page();

hover

悬停在元素上(会在元素出现后再悬停) 语法hover(<selector>);
  • selector:元素选择器
hover('#item');

html_capture_options

影响 HTML 捕获过程
  • options:对象,定义 HTML 捕获应如何处理
    • coordinate_attributes
html_capture_options({
    coordinate_attributes: true,
});

Image

收集图像数据
  • src:图像 URL 或 data:image URI 字符串
let i = new Image('https://example.com/image.png');
collect({image: i});

input

交互代码可用的全局对象,由触发输入或 next_stage() 提供
navigate(input.url);

job

交互代码可用的全局对象,由触发输入或 next_stage() 提供
let {created} = job;

load_html

加载 HTML 并返回 Cheerio 实例
  • html:任意 HTML 字符串
let $$ = load_html('<p id="p1">p1</p><p id="p2">p2</p>');
collect({data: $$('#p2').text()});

load_more

滚动列表到底部以触发加载更多内容,适用于懒加载无限滚动网站
  • selector:包含懒加载内容的元素选择器
load_more(<selector>);
load_more('.search-results');
load_more('.search-results', {children: '.result-item', trigger_selector: '.btn-load-more', timeout: 10000});

load_sitemap

从 sitemap xml 读取 URL 列表(支持 sitemap 索引和 .gz 压缩的 sitemap,见示例)
let {pages} = load_sitemap({url: 'https://example.com/sitemap.xml.gz'});
let {children} = load_sitemap({url: 'https://example.com/sitemap-index.xml'});

location

包含当前页面位置信息的对象。可用字段:href
navigate('https://example.com');
location.href; // "https://example.com/"

Money

收集价格/货币数据
  • value:金额
  • currency:货币代码
let p = new Money(10, 'USD');
collect({product_price: p});

mouse_to

将鼠标移动到指定的 (x, y) 位置 语法mouse_to(<x>, <y>);
  • x:目标 x 坐标
  • y:目标 y 坐标
mouse_to(0, 0);

导航浏览器到指定 URL 语法navigate(<url>);
  • 默认情况下,404 状态码会抛出 dead_page 错误,可使用 opt.allow_status 覆盖
  • url:要导航的 URL
  • opt:导航选项(见示例)
navigate(input.url);
navigate('https://example.com');

// 等待浏览器触发 DOM 内容加载事件
navigate(`url`, {wait_until: 'domcontentloaded'}); 

// 为导航添加 referer
navigate(`url`, {referer: `url`}); 

// 等待毫秒数,默认 30000 ms
navigate(`url`, {timeout: 45000}); 

// 如果 URL 返回 404 状态码,则不抛出错误
navigate(`url`, {allow_status: [404]});

// 指定浏览器宽高
navigate(`url`, {
    fingerprint: {screen: {width: 400, height: 400}},
});

next_stage

使用指定输入运行爬虫的下一阶段
  • input:传递给下一浏览器会话的输入对象
next_stage({url: 'http://example.com', page: 1});

parse

解析页面数据
let page_data = parse();
collect({
    title: page_data.title,
    price: page_data.price,
});

preserve_proxy_session

在该页面的子页面中保留代理会话
preserve_proxy_session();

press_key

在当前聚焦的输入框中输入特殊按键(如 Enter 或 Backspace,通常用于搜索框输入后)
press_key('Enter');
press_key('Backspace');

proxy_location

配置爬虫从指定位置运行。除非需要高精度控制,否则通常使用 country(code) 即可
  • configuration:指定代理位置的对象,详情见示例
proxy_location({country: 'us'});

// 纬度范围: [-85, 85], 经度范围: [-180, 180]
proxy_location({lat: 37.7749, long: 122.4194}); 

// 半径单位为 km
proxy_location({lat: 37.7749, long: 122.4194, country: 'US', radius: 100}); 

redirect_history

返回自上次导航以来的 URL 重定向历史
navigate('http://google.com');
let redirects = redirect_history();
// 返回:
// [
//   'http://google.com',
//   'http://www.google.com',
//   'https://www.google.com/',
// ]

rerun_stage

使用新输入重新运行当前阶段
rerun_stage({url: 'http://example.com/other-page'});

resolve_url

返回给定 URL 参数最终指向的 URL
  • url:URL 字符串或实例
let {href} = parse().anchor_elem_data;
collect({final_url: resolve_url(href)});

response_headers

返回最后一次页面加载的响应头
let headers = response_headers();
console.log('content-type', headers['content-type']);

request

发起直接 HTTP 请求
  • url | options:请求的 URL 或请求选项(见示例)
let res = request('http://www.example.com');
let res = request({url: 'http://www.example.com', method: 'POST', headers: {'Content-type': 'application/json'}, body: {hello: 'world'}})

right_click

与 click 相同,但使用鼠标右键点击(会在元素出现后再点击) 语法right_click(<selector>);
  • selector:元素选择器
right_click('#item');

run_stage

使用新浏览器会话运行特定阶段
  • stage:要运行的阶段(1 为第一阶段)
  • input:传递给下一浏览器会话的输入对象
run_stage(2, {url: 'http://example.com', page: 1});

scroll_to

滚动页面,使元素可见。如果用于触发懒加载列表加载更多元素,请使用 load_more()。默认滚动为自然滚动,可能需要几秒。如果想立即跳转,请使用 {immediate: true} 语法scroll_to(<selector>);
  • selector:要滚动到的元素选择器
scroll_to('.author-profile');
scroll_to('top'); // 滚动到页面顶部
scroll_to('bottom'); // 滚动到页面底部
scroll_to('top', {immediate: true}); // 立即跳转到顶部

scroll_to_all

滚动页面,使所有匹配选择器的元素都可见 语法scroll_to_all(<selector>);
  • selector:要滚动的元素选择器
scroll_to_all('.author-profiles');

select

从 select 元素中选择一个值 语法select(<select>, <value>);
  • selector:元素选择器
select('#country', 'Canada');

set_lines

在页面抓取结束时,将多行数据添加到数据集中。每次调用 set_lines() 会覆盖之前的设置,仅最后一组数据会被加入数据集(按页面抓取跟踪)。适用于抓取器在错误时收集部分数据的情况,可以多次调用 set_lines() 更新数据,最后一次调用会被使用 语法set_lines(<data_line>[, <validate_fn>]);
  • lines:要添加到最终数据集的数据行数组
  • validate_fn:可选函数,用于检查数据行是否有效(每行运行一次)
set_lines(products_so_far);
set_lines(products_so_far, i=>{
    if (!i.price)
        throw new Error('缺少价格');
});

设置指定的会话 cookie;如果存在相同 cookie,则可能覆盖
set_session_cookie(`domain`, `name`, `value`);

set_session_headers

为所有 HTTP 请求设置额外头信息
  • headers:键值对象形式的额外请求头
set_session_headers({'HEADER_NAME': 'HEADER_VALUE'});

solve_captcha

解决页面上显示的任何验证码
solve_captcha();
solve_captcha({type: 'simple', selector: '#image', input: '#input'});

status_code

返回最后一次页面加载的状态码
collect({status_code: status_code()});

tag_all_responses

保存匹配的所有浏览器请求响应
  • field:标记字段名称
  • pattern:匹配的 URL 模式
  • options:设置 options.jsonp=true 可解析 jsonp 格式响应,系统会自动检测
tag_all_responses(<field>, <pattern>, <options>);
tag_all_responses('resp', /url/, {jsonp: true});
tag_all_responses('resp', /url/, {allow_error: true});
tag_all_responses('profiles', /\/api\/profile/);
navigate('https://example.com/sports');
let profiles = parse().profiles;
for (let profile of profiles)
    collect(profile);

tag_download

获取浏览器下载的文件
  • url:匹配请求的模式或字符串
let SEC = 1000;
let download = tag_download(/example.com\/foo\/bar/);
click('button#download');
let file1 = download.next_file({timeout: 10*SEC});
let file2 = download.next_file({timeout: 20*SEC});
collect({file1, file2});

tag_image

保存元素的图片 URL
  • field:标记字段名称
  • selector:有效 CSS 选择器
tag_image(field, selector);
tag_image('image', '#product-image');

tag_response

保存浏览器请求响应数据 语法tag_response(<field>, <pattern>, <options>);
  • name:标记字段名称
  • pattern:匹配的 URL 模式
  • options:设置 options.jsonp=true 可解析 jsonp 格式响应,系统会自动检测
tag_response('resp', /url/, {jsonp: true});
tag_response('resp', /url/, {allow_error: true});
tag_response('resp', (req, res)=>{
            if (req.url.includes('/api/'))
            {
                let request_body = req.body;
                let request_headers = req.headers;
                let response_body = res.body;
                let response_headers = res.headers;
            }
        });

tag_response('teams', /\/api\/teams/);
navigate('https://example.com/sports');
let teams = parse().teams;
for (let team of teams)
    collect(team);

tag_screenshot

保存页面 HTML 的截图
语法tag_screenshot(<field>, <options>);
  • field:标记字段名称
  • options:下载选项(见示例)
tag_screenshot('html_screenshot', {filename: 'screen'});
tag_screenshot('view', {full_page: false}); // full_page 默认为 true

tag_script

提取页面 script 中的 JSON 数据 语法tag_script(<field>, <selector>);
  • field:标记脚本名称
  • selector:要标记的 script 元素选择器
tag_script('teams', '#preload-data');
tag_script('ssr_state', '#__SSR_DATA__');
navigate('https://example.com/');
collect(parse().ssr_state);

tag_serp

将当前页面解析为搜索引擎结果页
  • field:标记字段名称
  • type:解析器类型(如 bing, google)
tag_serp('serp_bing_results', 'bing');
tag_serp('serp_google_results', 'google');

tag_video

保存元素的视频 URL
  • field:标记字段名称
  • selector:有效 CSS 选择器
  • opt:下载选项(见示例)
tag_video(field, selector);
tag_video('video', '#product-video', {download: true});

tag_window_field

标记浏览器页面中的 JS 值
  • field:数据路径
tag_window_field(field, key);
tag_window_field('initData', '__INIT_DATA__');

track_event_listeners

开始追踪浏览器创建的事件监听器,之后可用 disable_event_listeners() 停用
track_event_listeners();

type

在输入框中输入文本(会等待元素出现后再输入)
  • selector:元素选择器
  • text:输入文本
type(<selector>, <text>);
type('#location', 'New York');

// 如果输入框非空,则替换文本
type(<selector>, <text>, {replace: true}); 

// 输入到 id 以 "input-box" 结尾的元素
type('[id$=input-box]', <text>); 

// 发送 'Enter' 键
type(<selector>, ['Enter']); 

// 输入文本后发送 'Enter'
type(<selector>, ['Some text', 'Enter']); 

// 删除 1 个字符
type(<selector>, ['Backspace']); 

URL

NodeJS 标准 url 模块的 URL 类
let u = new URL('https://example.com');

verify_requests

监控失败请求,并使用回调函数处理
  • callback:在每个失败请求时调用,参数格式为 {url, error, type, response}
verify_requests(({url, error, type, response})=>{
    if (response.status != 404 && type == 'Font')
        throw new Error('字体加载失败');
});

Video

收集视频数据
  • src:视频 URL
let v = new Video('https://example.com/video.mp4');
collect({video: v});

wait

等待页面元素出现
  • selector:元素选择器
  • opt:等待选项(见示例)
wait(<selector>);
wait('#welcome-splash');
wait('.search-results .product');
wait('[href^="/product"]');

// 等待毫秒数,默认 30000 ms
wait(<selector>, {timeout: 5000}); 

// 等待元素隐藏
wait(<selector>, {hidden: true}); 

// 等待 iframe 内的元素
wait(<selector>, {inside: '#iframe_id'}); 

wait_any

等待任意匹配条件成功
wait_any(['#title', '#notfound']);

wait_for_parser_value

等待解析器字段包含值(点击操作后等待数据出现时有用)
  • field:解析器值路径
  • validate_fn:可选回调函数,验证值是否正确
  • opt:额外选项(如 timeout)
wait_for_parser_value(<field>[, <validate_fn>][, opt]);
wait_for_parser_value('profile');
wait_for_parser_value('listings.0.price', v=>{
    return parseInt(v) > 0;
}, {timeout: 5000});

wait_for_text

等待页面元素包含指定文本
  • selector:元素选择器
  • text:要等待的文本
wait_for_text(<selector>, <text>);
wait_for_text('.location', 'New York');

wait_hidden

等待元素不可见(被移除或隐藏)
  • selector:元素选择器
wait_hidden(<selector>);
wait_hidden('#welcome-splash');
wait_hidden(<selector>, {timeout: 5000});

wait_network_idle

等待浏览器网络空闲指定时间
  • timeout:网络空闲毫秒数
  • options.ignore:排除部分请求模式
wait_network_idle();
wait_network_idle({
    timeout: 1000,
    ignore: [/long_request/, 'https://example.com'],
});

wait_page_idle

等待 DOM 树在指定时间内没有变化
  • timeout:等待毫秒数
  • options.ignore:排除部分元素监控
wait_page_idle();
wait_page_idle({
    ignore: [<selector1>, <selector2>],
    idle_timeout: 1000,
});

wait_visible

等待元素在页面上可见
  • selector:元素选择器
wait_visible(<selector>);
wait_visible('#welcome-splash');
wait_visible(<selector>, {timeout: 5000});

$

jQuery 风格的辅助函数
  • selector:元素选择器
$(<selector>);
wait($('.store-card'));

Clicking on selector based on text

jQuery 风格辅助函数
$('.selector').filter_includes('text').click();

emulate_device

以移动设备查看页面,会修改 UA、分辨率和设备像素比
  • device:设备名称字符串
emulate_device('iPhone X');
emulate_device('Pixel 2');
  • Blackberry PlayBook
  • Blackberry PlayBook landscape
  • BlackBerry Z30
  • BlackBerry Z30 landscape
  • Galaxy Note 3
  • Galaxy Note 3 landscape
  • Galaxy Note II
  • Galaxy Note II landscape
  • Galaxy S III
  • Galaxy S III landscape
  • Galaxy S5
  • Galaxy S5 landscape
  • Galaxy S8
  • Galaxy S8 landscape
  • Galaxy S9+
  • Galaxy S9+ landscape
  • Galaxy Tab S4
  • Galaxy Tab S4 landscape
  • iPad
  • iPad landscape
  • iPad (gen 6)
  • iPad (gen 6) landscape
  • iPad (gen 7)
  • iPad (gen 7) landscape
  • iPad Mini
  • iPad Mini landscape
  • iPad Pro
  • iPad Pro landscape
  • iPad Pro 11
  • iPad Pro 11 landscape
  • iPhone 4
  • iPhone 4 landscape
  • iPhone 5
  • iPhone 5 landscape
  • iPhone 6
  • iPhone 6 landscape
  • iPhone 6 Plus
  • iPhone 6 Plus landscape
  • iPhone 7
  • iPhone 7 landscape
  • iPhone 7 Plus
  • iPhone 7 Plus landscape
  • iPhone 8
  • iPhone 8 landscape
  • iPhone 8 Plus
  • iPhone 8 Plus landscape
  • iPhone SE
  • iPhone SE landscape
  • iPhone X
  • iPhone X landscape
  • iPhone XR
  • iPhone XR landscape
  • iPhone 11
  • iPhone 11 landscape
  • iPhone 11 Pro
  • iPhone 11 Pro landscape
  • iPhone 11 Pro Max
  • iPhone 11 Pro Max landscape
  • iPhone 12
  • iPhone 12 landscape
  • iPhone 12 Pro
  • iPhone 12 Pro landscape
  • iPhone 12 Pro Max
  • iPhone 12 Pro Max landscape
  • iPhone 12 Mini
  • iPhone 12 Mini landscape
  • iPhone 13
  • iPhone 13 landscape
  • iPhone 13 Pro
  • iPhone 13 Pro landscape
  • iPhone 13 Pro Max
  • iPhone 13 Pro Max landscape
  • iPhone 13 Mini
  • iPhone 13 Mini landscape
  • JioPhone 2
  • JioPhone 2 landscape
  • Kindle Fire HDX
  • Kindle Fire HDX landscape
  • LG Optimus L70
  • LG Optimus L70 landscape
  • Microsoft Lumia 550
  • Microsoft Lumia 950
  • Microsoft Lumia 950 landscape
  • Nexus 10
  • Nexus 10 landscape
  • Nexus 4
  • Nexus 4 landscape
  • Nexus 5
  • Nexus 5 landscape
  • Nexus 5X
  • Nexus 5X landscape
  • Nexus 6
  • Nexus 6 landscape
  • Nexus 6P
  • Nexus 6P landscape
  • Nexus 7
  • Nexus 7 landscape
  • Nokia Lumia 520
  • Nokia Lumia 520 landscape
  • Nokia N9
  • Nokia N9 landscape
  • Pixel 2
  • Pixel 2 landscape
  • Pixel 2 XL
  • Pixel 2 XL landscape
  • Pixel 3
  • Pixel 3 landscape
  • Pixel 4
  • Pixel 4 landscape
  • Pixel 4a (5G)
  • Pixel 4a (5G) landscape
  • Pixel 5
  • Pixel 5 landscape
  • Moto G4
  • Moto G4 landscape

解析器函数

本文列出了在 IDE 中编写爬虫时可在解析器代码中使用的命令,并对其进行了说明。

input

解析器代码中可用的全局变量
let url = input.url;

$

cheerio 的实例
$('#example').text();
$('$example').attr('href');
$('#example').text_sane(); /* 类似 $().text(),但会修剪文本并将所有空白字符替换为单个空格 "a b \t\n\n c" -> "a b c" */
更多信息请访问 cheerio 官网

location

解析器代码中可用的全局变量。对象包含当前页面的位置信息
let current_url = location.href; 

Image

收集图片数据
let i = new Image('https://example.com/image.png');
collect({image: i});

Video

收集视频数据
let v = new Video('https://example.com/video.mp4');
collect({video: v});

Money

收集价格/货币数据
let p = new Money(10, 'USD');
collect({product_price: p});