ReadPageScrape-增强版

更新时间:
复制 MD 格式

本文介绍 ReadPageScrape 接口,主要通过无头浏览器动态渲染并触达目标页面,包含接口功能、参数、返回以及接口调用方法。

1. 接口说明

  1. 通过浏览器沙箱环境读取 HTML 并解析网页内容。

  2. 接口将在目标页面资源完全加载后开始解析(可通过 pageTimeout 参数调整最大等待时长),接口整体耗时将显著受目标站点资源加载情况的影响。

  3. 若目标地址的响应头中的内容类型(Content-Type)为 application/pdf,系统将自动触发 PDF 解析(pdf 处理大小不超过 30 MB),文件超过限制或解析结果为空时,会回退到当前页面 DOM,不能保证返回完整 PDF 正文。

2. 接口定义

2.1 请求参数

字段

参数值

说明

url

<string>

required

解析的目标地址,必须以 http:// 或 https:// 开头

pageTimeout

<int>

[0, 100000]

default:8000

页面导航阶段的超时时间,单位为毫秒。默认 8000,超过 100000 时按 100000 处理。

  • 该参数不是接口总耗时上限

  • 正文就绪检查、actions、截图、PDF 解析、正文处理及网络传输还会增加耗时

  • 大多数页面可在 5000ms 内加载完成

  • 对于资源较多的页面,可以设置为 10000ms

formats

<array>

rawHtml

html

markdown

text

screenshot

default: [
"html", "markdown", "text"
]

解析结果格式

  • rawHtml:目标站点的 html

  • html: 根据 readabilityMode 处理后的页面内容

  • markdown:根据 html 转换成的 markdown 内容

  • text:html 中的文本内容

  • screenshot: 页面截图,截图会增加额外耗时,实际时间取决于页面和服务处理情况

maxAge

<int>

[0, ∞]

default: 1296000

最大缓存时间,单位(秒)

  • 当请求参数actions中存在 type != "wait" 时,禁用缓存读取和写入

  • 当请求参数actions中所有元素都满足 type = "wait" 时,仍可命中缓存,命中时不会再次执行这些动作

  • 若缓存时间小于 maxAge,则返回缓存内容

  • 若 maxAge 等于 0,则不使用缓存

actions

<array>

actions.type: "wait"
等待指定时间或元素出现

  • actions.duration<int>:等待毫秒数

  • actions.selector<string>:CSS 选择器,等待元素出现

[]

在获取正文内容之前按顺序执行指定操作。

  • 最大不超过20步

  • 执行超时时间 60000ms

示例如下:

[
  {
    "type": "wait",
    "selector": "#list",
    "timeout": 10000
  },
  {
    "type": "wait",
    "duration": 800
  },
  {
    "type": "eval",
    "scripts": "document.querySelector('#cookie-accept')?.click()"
  }
]

actions.type: "eval"

  • actions.scripts<string>:要执行的 JS 代码,支持 return 返回值

readability

<map | null>

readabilityMode

<string>

none

normal

article

default: none

normal: 基于自研算法,剔除无关信息(页头/页脚,导航等),并返回重点正文内容。

article: 基于自研算法,获取站点主要正文内容(适用于博客、新闻站点,不适用于目录页、导航页)

excludeAllImages

<bool>

default: false

是否剔除所有图片

excludeAllLinks

<bool>

default: false

是否剔除所有链接

excludedTags

<array>

[]

指定排除的标签,如:

["form", "header", "footer", "nav"]

返回参数

字段

字段说明

样例

requestId

<string>

请求RequestId,排查问题时可以提供此信息

errorCode

<string | null>

错误码

错误码

errorMessage

<string | null>

错误信息

data

<map>

statusCode

<int>

目标站点请求返回的 HttpCode

errorMessage

<string | null>

若目标站点请求失败,返回目标站点失败的相应错误信息

rawHtml

<string | null>

目标站点原始 html

html

<string | null>

目标站点可读 html

text

<string | null>

文本格式内容

markdown

<string | null>

markdown 格式的内容

screenshot

<string | null>

目标站点截图

actions

<array | null>

与 actions 顺序对应的执行结果

  • wait 成功或 eval 未返回值时为 {}

  • eval 返回值放在 ret 中

  • 动作失败返回 error

  • 动作预算耗尽后记录超时或跳过结果,通常仍继续获取当前页面正文

  • 严重浏览器异常仍可能导致整个请求失败

{
  "actions": [
    {},
    {},
    {
      "ret": ""
    }
  ]
}

links

<map | null>

internal

<array|null>

目标 url 中的链接信息(站内链接)

  • href:链接地址

  • text:链接展示文本

  • title:补充提示

[
  {
   "href": "https://www.alibabagroup.com/cn/global/home",
   "text": "阿里巴巴集团",
   "title": ""
  }
]

external

<array|null>

目标 url 中的链接信息(站外链接)

media

<map | null>

images

<array|null>

目标 url 中的图片信息

  • src: 图片地址

  • data: 内嵌数据或附加数据

  • alt:替代文本

  • desc: 补充说明

  • format: 图片格式

[
  {
   "src": "https://img.alicdn.com/tfs/TB1AOdINW6qK1RjSZFmXXX0PFXa-258-258.jpg",
   "data": "",
   "alt": "阿里云微信",
   "desc": null,
   "format": "jpg"
  }
]

audios

<array|null>

目标 url 中的音频信息

  • src: audio 地址

  • data: 内嵌数据或附加数据

  • alt:替代文本

  • desc: 补充说明

  • format: 格式

videos

<array|null>

目标 url 中的视频信息

  • src: video 地址

  • data: 内嵌数据或附加数据

  • alt:替代文本

  • desc: 补充说明

  • format: 格式

[
 {
 "src": "blob:https://xxxxx.com/xxx",
 "data": "",
 "alt": null,
 "desc": "",
 "format": null
 }
]

metadata

<map>

url

<string>

目标地址

{
  "metadata": {
    "url": "https://example.com/article/123",
    "title": "Example Article Title",
    "hostLogo": "https://example.com/favicon.ico",
    "lastModified": "2026-06-20T10:00:00Z",
    "redirectedUrl": null,
    "contentType": "text/html; charset=utf-8",
    "pdfParse": false,
    "description": "A brief description of the article.",
    "author": "John Doe",
    "publishedDate": "2026-06-15T08:30:00Z",
    "siteName": "Example Site",
    "imageUrl": "https://example.com/images/og-image.jpg",
    "canonicalUrl": "https://example.com/article/123",
    "language": "en",
    "schemaType": "Article",
    "pageType": "article"
  }
}

redirectedUrl

实际重定向后的 URL

title

<string|null>

站点标题

hostLogo

<string|null>

站点 favicon / logo URL

lastModified

<string|null>

最后修改时间

publishedDate

<string|null>

发布日期(article:published_time / JSON-LD datePublished)

contentType

<string|null>

HTTP 响应的 Content-Type 头

description

<string|null>

页面描述(og:description → <meta name="description">)

author

<string|null>

作者信息(article:author / JSON-LD author)

siteName

<string|null>

站点名称(og:site_name)

imageUrl

<string|null>

主图 URL(og:image)

canonicalUrl

<string|null>

规范 URL(<link rel="canonical">)

language

<string|null>

页面语言(<html lang="...">)

schemaType

<string|null>

JSON-LD @type(如 Article, Product)

pageType

<string|null>

基于自研算法的页面分类

  • article:单篇文章/新闻/博客/长文

  • forum:论坛/问答/讨论帖

  • product:电商商品详情页

  • listing:搜索结果/列表/分类索引页

  • collection:首页/落地页/导航页

  • documentation:技术文档(API Reference、教程、FAQ)

  • service: 营销/定价/联系/关于/隐私条款页

  • empty:空白页(404、无内容)

  • login: 登录/认证页

  • video:视频为主的页面

  • paid: 付费墙

  • other:其它

pdfParse

<bool>

是否触发 pdf 解析

错误码

HttpCode

错误码

错误信息

处理方案

400

InvalidParameter

The specified parameter 'request' is not valid

确认请求参数是否符合协议规范

404

InvalidAccessKeyId.NotFound

Specified access key is not found.

检查并确保AccessKey/Secret正确。

403

Retrieval.NotActivate

Please activate AI search service

请跳转控制台开通

403

Retrieval.NotAuthorised

Please authorize the AliyunIQSFullAccess privilege to the sub-account.

子账号没有进行授权,参考创建RAM用户并授权

429

Retrieval.Throttling.User

Request was denied due to user flow control.

超出限流规格,请稍后重试

503

Retrieval.ServiceBusy

Service is temporarily unavailable. Please try again later.

服务端繁忙,可稍后重试。若持续出现,请联系客户支持。

403

ReadPage.SecurityRestrict

The ReadPage request was denied by a security or resource policy.

由于安全或资源限制拒绝。如:SSRF、robots协议、PDF大小超出限制等

400

ReadPage.RequestTimeout

The ReadPage request exceeded its execution time limit.

目标网页导航超时时,可适当增大 pageTimeout(增强版上限 100000ms)。该参数不是接口总耗时上限。

429

ReadPage.RateLimitByDomain

The domain has reached the rate limit.

请合理控制对目标网站的请求频率和并发量,不得干扰其正常运行

500

ReadPage.CommonError

Failed to process the ReadPage request.

3. 补充说明

1. 隐身模式(stealth mode)

本接口默认启用隐身模式。该模式会对浏览器环境进行指纹优化,使其更接近真实用户浏览器,从而提升自动化访问的兼容性与稳定性。

image

2. 限制

  1. 本接口遵守目标网站robots协议、用户协议及相关法律法规;

  2. 本接口仅提供技术支持与页面解析能力,不对第三方网站内容的生成、发布、展示或使用承担任何责任。对于通过本服务抓取、访问或以其他方式获取的第三方内容,我们不作任何形式的承诺或保证。

4. 接口调用

SDK 示例

Python SDK

前提条件

您需要确保已安装 Python 3.8 或以上版本。下例使用 Python SDK 1.6.0,仅展示基础调用。

安装SDK
pip install alibabacloud_iqs20241111==1.6.0
调用代码
import json

from Tea.exceptions import TeaException
from alibabacloud_iqs20241111 import models
from alibabacloud_iqs20241111.client import Client
from alibabacloud_tea_openapi import models as open_api_models


class Sample:
    def __init__(self):
        pass

    @staticmethod
    def create_client() -> Client:
        config = open_api_models.Config(
            # TODO: 使用您的AK/SK进行替换(建议通过环境变量加载)
            access_key_id="$YOUR_ACCESS_KEY",
            access_key_secret="$YOUR_ACCESS_SECRET"
        )
        config.endpoint = f"iqs.cn-zhangjiakou.aliyuncs.com"
        return Client(config)

    @staticmethod
    def main() -> None:
        client = Sample.create_client()
        run_instances_request = models.ReadPageScrapeRequest(
            body=models.ReadPageScrapeBody(
                url="http://www.example.com",
                max_age=0,
            )
        )
        try:
            response = client.read_page_scrape(run_instances_request)
            print(f"api success, request_id:{response.body.request_id}, result: ")
            print(f"{json.dumps(response.body.data.to_map(), indent=2)}")

        except TeaException as e:
            request_id = e.data.get("requestId")
            code = e.data.get("errorCode")
            message = e.data.get("errorMessage")
            print(f"api exception, requestId:{request_id}, code:{code}, message:{message}")


if __name__ == "__main__":
    Sample.main()
    

Java SDK

前提条件

已安装Java8或以上版本。

Maven依赖
<dependency>
    <groupId>com.aliyun</groupId>
    <artifactId>iqs20241111</artifactId>
    <version>1.6.0</version>
</dependency>
调用代码
package com.aliyun.iqs.readpage.example;

import com.aliyun.iqs20241111.Client;
import com.aliyun.iqs20241111.models.*;
import com.aliyun.teaopenapi.models.Config;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

public class Example {
    public static void main(String[] args) throws Exception {
        Client client = initClient();
        invoke(client, "http://www.example.com");
    }

    private static Client initClient() throws Exception {
        // TODO: 使用您的AK/SK进行替换(建议通过环境变量加载)
        String accessKeyId = "$YOUR_ACCESS_KEY";
        String accessKeySecret = "$YOUR_ACCESS_SECRET";

        Config config = new Config()
                .setAccessKeyId(accessKeyId)
                .setAccessKeySecret(accessKeySecret);

        config.setEndpoint("iqs.cn-zhangjiakou.aliyuncs.com");
        return new Client(config);
    }

    private static void invoke(Client client, String url) {
        ReadPageScrapeBody input = new ReadPageScrapeBody();
        input.setUrl(url);

        ReadPageScrapeRequest request = new ReadPageScrapeRequest().setBody(input);

        try {
            ReadPageScrapeResponse response = client.readPageScrape(request);

            printOutput(response.getBody());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void printOutput(ReadPageScrapeResponseBody output) {
        // 使用 GsonBuilder 创建带格式化的 Gson 实例
        Gson gson = new GsonBuilder()
                .setPrettyPrinting()
                .disableHtmlEscaping()
                .create();

        // 输出格式化的 JSON
        String prettyJson = gson.toJson(output);
        System.out.println(prettyJson);
    }
}

Go SDK

前提条件

Go 环境版本必须不低于 1.10.x

安装SDK
require (
  github.com/alibabacloud-go/iqs-20241111 v1.6.0
)
调用代码
package main

import (
	"fmt"
	"log"

	openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client"
	iqs20241111 "github.com/alibabacloud-go/iqs-20241111/client"
	util "github.com/alibabacloud-go/tea-utils/v2/service"
	"github.com/alibabacloud-go/tea/tea"
)

const endpointURL = "iqs.cn-zhangjiakou.aliyuncs.com"

func createClient() (*iqs20241111.Client, error) {
	// TODO: 使用您的AK/SK进行替换
	accessKeyID := "YOUR_ACCESS_KEY"
	accessKeySecret := "YOUR_ACCESS_SECRET"

	if accessKeyID == "" || accessKeySecret == "" {
		return nil, fmt.Errorf("ACCESS_KEY or ACCESS_SECRET environment variable is not set")
	}

	config := &openapi.Config{
		AccessKeyId:     tea.String(accessKeyID),
		AccessKeySecret: tea.String(accessKeySecret),
		Endpoint:        tea.String(endpointURL),
	}

	return iqs20241111.NewClient(config)
}

func runReadPage(client *iqs20241111.Client) error {
	body := &iqs20241111.ReadPageScrapeBody{
		Url: tea.String("http://www.example.com"),
	}
	request := &iqs20241111.ReadPageScrapeRequest{
		body,
	}
	runtime := &util.RuntimeOptions{}

	resp, err := client.ReadPageScrapeWithOptions(request, nil, runtime)
	if err != nil {
		return fmt.Errorf("readpage failed: %w", err)
	}

	fmt.Printf("[%s] response: %s\n", *resp.Body.RequestId, resp.Body)
	return nil
}

func main() {
	client, err := createClient()
	if err != nil {
		log.Fatalf("Failed to create client: %v", err)
	}

	if err := runReadPage(client); err != nil {
		log.Fatalf("Error running readpage: %v", err)
	}
}

HTTP 调用示例

  • 请求参数(RequestBody)

curl --location "https://cloud-iqs.aliyuncs.com/readpage/scrape" \
--header "Content-Type: application/json" \
--header "X-API-Key: <YOUR-IQS-API-KEY>" \
--data '{
    "url": "https://www.example.com",
    "maxAge": 0
}'

  • 返回

{
  "data": {
    "html": "<html>\n<head><title>Example Domain</title></head>\n<body>\n<div>\n<h1>Example Domain</h1>\n<p>This domain is for use in documentation examples without needing permission. Avoid use in operations.</p>\n<p><a href=\"https://iana.org/domains/example\">Learn more</a></p>\n</div>\n</body>\n</html>",
    "links": {
      "internal": "[]",
      "external": "[{\"href\":\"https://iana.org/domains/example\",\"text\":\"Learn more\",\"title\":\"\"}]"
    },
    "markdown": "# Example Domain\nThis domain is for use in documentation examples without needing permission. Avoid use in operations.\n[Learn more](https://iana.org/domains/example)\n",
    "media": {
      "images": "[]",
      "audios": "[]",
      "videos": "[]"
    },
    "metadata": {
      "hostname": "www.example.com",
      "pdfParse": false,
      "title": "Example Domain",
      "url": "https://www.example.com"
    },
    "statusCode": 200,
    "text": "# Example Domain\nThis domain is for use in documentation examples without needing permission. Avoid use in operations.\nLearn more\n"
  },
  "requestId": "1d0ac13a-8c73-4134-a835-35d0126f733c"
}