链接提取
独立的链接提取 API,可从 HTML 中提取所有链接资源并按类型分组。
与 Extract 的关键区别
ExtractAllLinks 不会应用 HTML 清洗(EnableSanitization 在此无效),因此位于 <script src>、<iframe>、<link>、<embed> 等标签中的资源链接也会被完整提取。这是为了让这些资源链接能够被枚举出来——它们在 Extract 路径中通常会被清洗过程移除。
结果排序与去重
ExtractAllLinks 返回的结果按 URL 升序排列,并按 URL 去重。因此对相同输入多次调用会得到完全一致的输出(自 v1.4.2 起),便于结果比较、缓存复用与可重现的下游处理。同一 URL 出现在多个标签中时仅保留一条记录。
包函数
func ExtractAllLinks(htmlBytes []byte, cfg ...Config) ([]LinkResource, error)
func ExtractAllLinksFromFile(filePath string, cfg ...Config) ([]LinkResource, error)
func ExtractAllLinksWithContext(ctx context.Context, htmlBytes []byte, cfg ...Config) ([]LinkResource, error)
func ExtractAllLinksFromFileWithContext(ctx context.Context, filePath string, cfg ...Config) ([]LinkResource, error)Processor 方法
func (p *Processor) ExtractAllLinks(htmlBytes []byte) ([]LinkResource, error)
func (p *Processor) ExtractAllLinksFromFile(filePath string) ([]LinkResource, error)
func (p *Processor) ExtractAllLinksWithContext(ctx context.Context, htmlBytes []byte) ([]LinkResource, error)
func (p *Processor) ExtractAllLinksFromFileWithContext(ctx context.Context, filePath string) ([]LinkResource, error)分组工具
GroupLinksByType
按链接类型分组。
func GroupLinksByType(links []LinkResource) map[string][]LinkResourcelinks, _ := html.ExtractAllLinks(data)
groups := html.GroupLinksByType(links)
for typ, items := range groups {
fmt.Printf("类型 %s: %d 个\n", typ, len(items))
}LinkResource
type LinkResource struct {
URL string // 链接地址
Title string // 链接标题
Type string // 链接类型(link, image, video, audio, media, css, js, icon)
}链接类型详解
每种 Type 对应特定的 HTML 标签来源:
| Type 值 | 来源 HTML 标签 | 控制开关 |
|---|---|---|
link | <a href> | IncludeContentLinks / IncludeExternalLinks |
image | <img src> | IncludeImages |
video | <video src>、<source type="video/*">、<iframe>/<embed>/<object>(视频 URL) | IncludeVideos |
audio | <audio src>、<source type="audio/*"> | IncludeAudios |
media | <source> 无法判定 video/audio 时 | IncludeVideos / IncludeAudios |
css | <link rel="stylesheet"> | IncludeCSS |
js | <script src> | IncludeJS |
icon | <link rel="icon">、<link rel="apple-touch-icon"> 等 | IncludeIcons |
embed 链接的特殊处理
<iframe>、<embed>、<object> 的 src/data 只有在判定为视频 URL(含 YouTube、Vimeo、Dailymotion 等嵌入模式)时才会被提取,类型记为 video。非视频 URL 不会被收录。
配置
链接提取行为可通过 Config 的链接过滤字段控制:
cfg := html.DefaultConfig()
cfg.IncludeImages = true
cfg.IncludeCSS = true
cfg.IncludeJS = true
cfg.IncludeExternalLinks = true
cfg.ResolveRelativeURLs = true
cfg.BaseURL = "https://example.com"相对 URL 解析
当 ResolveRelativeURLs=true(默认)时,所有类型的相对 URL 会基于 BaseURL 统一解析为绝对 URL:
- 解析逻辑由
resolveURLIfEnabled集中处理,对内容链接、图片、媒体、source、script、embed、link 标签一视同仁 - 显式设置
BaseURL会跳过自动检测,直接使用调用方提供的值 BaseURL为空且ResolveRelativeURLs=true时,从文档自动推导 BaseURL(见下方提示)
内部与外部链接
内容链接(<a href>)通过两组开关分别控制内部与外部链接:
| 开关 | 控制范围 | 判定方式 |
|---|---|---|
IncludeContentLinks | 内部链接 | URL 本身为相对路径,或与 BaseURL 同域 |
IncludeExternalLinks | 外部链接 | URL 为绝对路径且与 BaseURL 不同域(IsDifferentDomain) |
默认两者均为 true(提取全部内容链接)。其余资源类型(图片、CSS、JS 等)不受内/外区分,仅由各自的 Include* 开关控制。
preload / prefetch 处理
<link rel="preload" as="..."> 与 rel="prefetch" 会根据 as 属性路由到不同类型:
as 属性值 | 归入类型 | 控制开关 |
|---|---|---|
style | css | IncludeCSS |
script | js | IncludeJS |
image | image | IncludeImages |
video | video | IncludeVideos |
audio | audio | IncludeAudios |
dns-prefetch、preconnect 同样走此路由,但通常不带 as 属性,故不会被收录。
BaseURL 自动检测
当 ResolveRelativeURLs=true 且 BaseURL 为空时,库会从 HTML 文档本身自动推导 BaseURL,按以下优先级逐项尝试,命中即返回:
<base href>标签;<meta property="og:url">或<meta property="canonical">的content;<link rel="canonical" href>;- 文档中出现的首个绝对 URL(从其
href/src提取 base)。
显式设置 BaseURL 会跳过自动检测,优先使用调用方提供的值。
示例
package main
import (
"fmt"
"log"
"github.com/cybergodev/html"
)
func main() {
data := []byte(`<html><head>
<link rel="stylesheet" href="/css/main.css">
<link rel="icon" href="/favicon.ico">
<script src="/js/app.js"></script>
</head><body>
<a href="/about">关于我们</a>
<img src="/img/logo.png" alt="Logo">
<video src="/media/intro.mp4"></video>
</body></html>`)
cfg := html.DefaultConfig()
cfg.BaseURL = "https://example.com"
links, err := html.ExtractAllLinks(data, cfg)
if err != nil {
log.Fatal(err)
}
// 按类型分组后遍历输出
groups := html.GroupLinksByType(links)
for typ, items := range groups {
fmt.Printf("%s(%d 个):\n", typ, len(items))
for _, l := range items {
fmt.Printf(" - %s [%s]\n", l.URL, l.Title)
}
}
}