Web 化进搜索
简介
本 codelabs 会聚焦在小程序如何通过适配 Web 化方案,推送数据进入抖音搜索,支持被用户搜索到更多小程序内容。
视频教程
前提条件
- •已经入驻抖音开放平台,并且小程序已经上线。
- •下载最新版本抖音小程序开发者工具。
- •抖音小程序控制台开启 Web 化功能,小程序控制台 > 运营 > 流量配置 > 小程序 Web 化接入。
目标
学习内容
- •如何完成小程序 Web 化的页面适配,包括开发、调试、上线。
- •如何推送 Web 化适配后的页面 sitemap 到平台。
- •如何在小程序控制台进行 Web 化数据运营。
概念和原理
小程序 Web 化进搜索的链路如下:
- 1.开发者完成页面选取和适配,将需要收录页面通过平台或者接口的形式推送给小程序平台。
- 2.小程序平台将开发者提交的指定小程序页面(sitemap 格式)转化成具体的 H5 页面(该 H5 不会被用户访问到,仅给抖音爬虫访问),并对 H5 页面进行审核。审核通过后将 H5 页面提交给抖音搜索爬虫。
- 3.抖音搜索爬虫会按照开发者设置的抓取频次抓取对应转化后的 H5 页面,将页面关键信息抽取出来存储到搜索索引库中。
- 4.在用户访问抖音 App 进行搜索时,抖音搜索会匹配到相关的索引库中的内容并展示出小程序卡片。用户点击卡片后会跳转到开发者提交的小程序页面。
页面选取
推荐选取偏图文类的内容页面。具体来说通常是小程序内具体某业务场景下的内容详情页,例如新闻详情页面、汽车详情页面、小说简介页、漫画简介页等。
不推荐提交偏时效性或与用户信息相关的页面,例如首页、推荐列表页、个人信息页等。
页面适配
页面信息设置
页面信息包括
title
、keywords
、description
等内容,未设置会影响爬虫抓取和算法理解效果。属性名 | 类型 | 默认值 | 必填 | 说明 | 最低支持版本 |
title | string | | 是 | 页面文章标题,根据页面的主要内容设置,且需要每个页面尽量唯一。需要根据页面接口返回值进行设置。 长度限制 70 字符。 | 3.22.0 |
keywords | string | | 是 | 页面文章关键词,多个关键词之间使用英文逗号 “,” 隔开。 | 3.22.0 |
description | string | | 是 | 页面文章摘要、描述信息。 长度限制 70 字符。 | 3.22.0 |
success | function | | 否 | 接口调用成功的回调函数 | 3.22.0 |
fail | function | | 否 | 接口调用失败的回调函数 | 3.22.0 |
complete | function | | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) | 3.22.0 |
代码示例
Page({ onLoad() { const data = fetchData(); tt.setPageInfo && tt.setPageInfo({ title: data.title, keywords: data.keywords, description: data.description, }); }, fetchData() { // 具体的页面信息请求接口 tt.request(); return { title: "小程序web化接入", description: "Web化是平台通过技术手段帮助抖音小程序自动转化得到的一个 H5 版本的小程序,其功能与展示形式与小程序一致。在对小程序进行Web化后,小程序的页面就可以被搜索爬虫抓取,从而可以以自然结果的样式在搜索结果中展现。这个H5版本的小程序不会被普通用户直接访问到,仅用于被搜索的爬虫抓取内容。用户在C端访问时,点击搜索卡片后打开的仍然是小程序。", keywords: "web化,搜索,小程序", }; }, });
页面调试
IDE 调试,保证页面在 Web 化后渲染正常。
完成页面适配后,可以在 IDE 进行预览调试,本地验收效果。
使用示例
页面渲染正常且正确设置页面信息,Web 化检测全部通过。
页面渲染异常,Web 化检测未通过,提示白屏。
未正确设置页面信息,Web 化检测未通过。
使用不支持能力,但不阻塞页面渲染,Web 化检测通过并打印不支持能力调用次数。
页面发布
在 IDE 完成 Web 化页面适配后,需要把适配后的代码更新到线上,进行小程序正式版发布。
下一章节将介绍页面适配完成后,如何提交页面收录。
页面收录
抓取频次 Quota 设置
重点说明:抓取频次与提交的页面量关系,包括 QPS 的计算。
页面提交数量
单日提交的路径上限在 1000 以内。假如有存量大量优质的内容想要快速收录,可以与对接运营或研发单独沟通诉求。
爬虫抓取频次
爬虫的抓取频次,可以在后台进行设置,建议抓取频次设置的数量为每日提交页面数量的两倍。 这是由于入搜索之前会由治理完成审核,因此同样的页面会被请求两次。
QPS 计算
计算公式:
- •页面访问 QPS = Math.min (抓取上限,单日提交页面数量 * 2) / (24 * 60 * 60)。
- •开发者服务器的 QPS = 页面访问 QPS * 页面内的接口请求 。
举例说明:
- •假如设置抓取频次上限为 80 万次/天,单日提交页面数量为 100 万,那么实际入库数量每日为 40 万,页面访问的 QPS 为 800000/(24*60*60) 约等于 9.25,开发者服务器的 QPS 等于页面访问 QPS 9.25 * 页面内的接口请求数。
- •假如设置抓取频次上限为 200 万次/天,单日提交页面数量为 100 万,那么实际入库数量每日为 100 万,页面访问 QPS 为 2000000/(24*60*60) 约等于 23。
页面提交
开发者可以向平台提交小程序 sitemap 文件,即由小程序页面地址所组成的文件,可通过在开发者平台上上传文件或通过服务端 OpenAPI 来提交页面。文件用于标记哪些页面内容支持被抖音索引和搜索展示,有如下格式和限制:
- •纯文本格式,每行填入一个路径,行与行之间分隔符为 '\n'
- •文件整体大小小于10M,路径数需要小于10w,单个路径大小需要小于200字节
- •路径需要符合小程序页面链接的path+query要求
样例:
pages/index/1?t=1 pages/index/2?t=2 pages/index/3?t=3 ....
在开发者平台提交页面
通过 OpenAPI 提交页面
示例代码
- •Go 版本:
package main import ( "fmt" "io/ioutil" "net/http" "strings" ) func main() { url := "https://open.douyin.com/api/apps/v1/search/upload_sitemap/" method := "POST" payload := strings.NewReader(`{ "app_id": "tt5daf2b12c285xxxx", "page_paths": [ "pages/index/1?t=1", "pages/index/2?t=2", "pages/index/3?t=3" ] }`) client := &http.Client{} req, err := http.NewRequest(method, url, payload) if err != nil { fmt.Println(err) return } req.Header.Add("access-token", "clt.78743ab256619da1fde8efabfb7c50da1jJz6mjqx0xwukNHcIdhIKWaAbOU_lq") req.Header.Add("Content-Type", "application/json") res, err := client.Do(req) if err != nil { fmt.Println(err) return } defer res.Body.Close() body, err := ioutil.ReadAll(res.Body) if err != nil { fmt.Println(err) return } fmt.Println(string(body)) }
- •Java 版本:
OkHttpClient client = new OkHttpClient().newBuilder() .build(); MediaType mediaType = MediaType.parse("application/json"); RequestBody body = RequestBody.create(mediaType, "{\"app_id\":\"tt5daf2b12c285xxxx\",\"page_paths\":[\"pages/index/1?t=1\",\"pages/index/2?t=2\",\"pages/index/3?t=3\"]}"); Request request = new Request.Builder() .url("https://open.douyin.com/api/apps/v1/search/upload_sitemap/") .method("POST", body) .addHeader("access-token", "clt.78743ab256619da1fde8efabfb7c50da1jJz6mjqx0xwukNHcIdhIKWaAbOU_lq") .addHeader("Content-Type", "application/json") .build(); Response response = client.newCall(request).execute();
- •Python 版本:
import http.client import json conn = http.client.HTTPSConnection("open.douyin.com") payload = json.dumps({ "app_id": "tt5daf2b12c285xxxx", "page_paths": [ "pages/index/1?t=1", "pages/index/2?t=2", "pages/index/3?t=3" ] }) headers = { 'access-token': 'clt.78743ab256619da1fde8efabfb7c50da1jJz6mjqx0xwukNHcIdhIKWaAbOU_lq', 'Content-Type': 'application/json' } conn.request("POST", "/api/apps/v1/search/upload_sitemap/", payload, headers) res = conn.getresponse() data = res.read() print(data.decode("utf-8"))
索引删除
开发者可向平台提交需要删除的已索引资源,包括死链、低质及不希望在抖音搜索中展现的内容,提交内容将在抖音搜索结果中屏蔽,将在 30 分钟后生效。。可通过开发者平台或服务端 OpenAPI 来删除索引。注意以下两点:
- •删除的索引无法再恢复。
- •提交的文件格式类似 sitemap 文件格式。
在开发者平台删除索引
通过 OpenAPI 删除索引
示例代码
- •Go 版本:
package main import ( "fmt" "io/ioutil" "net/http" "strings" ) func main() { url := "https://open.douyin.com/api/apps/v1/search/delete_index/" method := "POST" payload := strings.NewReader(`{ "app_id": "tt5daf2b12c285xxxx", "name":"index", "path_list": [ "pages/index/1?t=1", "pages/index/2?t=2", "pages/index/3?t=3" ] }`) client := &http.Client{} req, err := http.NewRequest(method, url, payload) if err != nil { fmt.Println(err) return } req.Header.Add("access-token", "clt.78743ab256619da1fde8efabfb7c50da1jJz6mjqx0xwukNHcIdhIKWaAbOU_lq") req.Header.Add("Content-Type", "application/json") res, err := client.Do(req) if err != nil { fmt.Println(err) return } defer res.Body.Close() body, err := ioutil.ReadAll(res.Body) if err != nil { fmt.Println(err) return } fmt.Println(string(body)) }
- •Java 版本:
OkHttpClient client = new OkHttpClient().newBuilder() .build(); MediaType mediaType = MediaType.parse("application/json"); RequestBody body = RequestBody.create(mediaType, "{\"app_id\":\"tt5daf2b12c285xxxx\",\"name\":\"index\",\"path_list\":[\"pages/index/1?t=1\",\"pages/index/2?t=2\",\"pages/index/3?t=3\"]}"); Request request = new Request.Builder() .url("https://open.douyin.com/api/apps/v1/search/delete_index/") .method("POST", body) .addHeader("access-token", "clt.78743ab256619da1fde8efabfb7c50da1jJz6mjqx0xwukNHcIdhIKWaAbOU_lq") .addHeader("Content-Type", "application/json") .build(); Response response = client.newCall(request).execute();
- •Python 版本:
import http.client import json conn = http.client.HTTPSConnection("open.douyin.com") payload = json.dumps({ "app_id": "tt5daf2b12c285xxxx", "name": "index", "path_list": [ "pages/index/1?t=1", "pages/index/2?t=2", "pages/index/3?t=3" ] }) headers = { 'access-token': 'clt.78743ab256619da1fde8efabfb7c50da1jJz6mjqx0xwukNHcIdhIKWaAbOU_lq', 'Content-Type': 'application/json' } conn.request("POST", "/api/apps/v1/search/delete_index/", payload, headers) res = conn.getresponse() data = res.read() print(data.decode("utf-8"))
数据运营
在完成页面收录后,开发者可以在小程序控制台观测具体的数据指标,其中包括页面爬取、页面收录数据、小程序搜索卡片的曝光和点击数据。
模块 | 数据口径 | 统计口径 |
流量概况 | 搜索曝光量 | 在时间筛选范围内的用户浏览小程序搜索卡片的曝光数据 |
搜索点击量 | 在时间筛选范围内的用户点击小程序搜索卡片的数据 | |
索引概况 | 总收录页面数 | 累计到更新时间的收录成功页面数据总数(页面重复提交只计入最新一次提交结果) |
总错误页面数 | 累计到更新时间的收录失败数据总数(页面重复提交只计入最新一次提交结果) | |
日折线图—收录页面数 | 总收录页面数每日变化趋势 | |
日折线图—错误页面数 | 总错误页面数每日变化趋势 | |
索引页面错误详情 | 页面收录失败明细 | 累计到更新时间的收录失败原因聚合统计 |
总结
恭喜,你已经完成了小程序 Web 化进搜索 Codelab。
你在该 Codelab 中了解了:
- •如何完成页面适配
- •如何完成页面收录
- •如果查看收录及搜索数据