mirror of
https://github.com/fish2018/pansou.git
synced 2025-11-25 03:14:59 +08:00
新增插件jutoushe
This commit is contained in:
1
main.go
1
main.go
@@ -63,6 +63,7 @@ import (
|
||||
_ "pansou/plugin/yuhuage"
|
||||
_ "pansou/plugin/u3c3"
|
||||
_ "pansou/plugin/clxiong"
|
||||
_ "pansou/plugin/jutoushe"
|
||||
)
|
||||
|
||||
// 全局缓存写入管理器
|
||||
|
||||
199
plugin/jutoushe/html结构分析.md
Normal file
199
plugin/jutoushe/html结构分析.md
Normal file
@@ -0,0 +1,199 @@
|
||||
# JUTOUSHE(剧透社)HTML结构分析
|
||||
|
||||
## 网站信息
|
||||
- **网站名称**: 剧透社
|
||||
- **域名**: https://1.star2.cn/
|
||||
- **类型**: 网盘资源分享站,主要提供电视剧、电影、短剧、综艺等影视资源
|
||||
- **特点**: 提供多种网盘下载链接(夸克、百度、阿里等)
|
||||
|
||||
## 搜索页面结构
|
||||
|
||||
### 1. 搜索URL模式
|
||||
```
|
||||
https://1.star2.cn/search/?keyword={关键词}
|
||||
|
||||
示例:
|
||||
https://1.star2.cn/search/?keyword=%E7%91%9E%E5%85%8B%E5%92%8C%E8%8E%AB%E8%92%82
|
||||
https://1.star2.cn/search/?keyword=%E4%B8%8E%E6%99%8B%E9%95%BF%E5%AE%89
|
||||
|
||||
参数说明:
|
||||
- keyword: URL编码的搜索关键词
|
||||
```
|
||||
|
||||
### 2. 搜索结果容器
|
||||
- **父容器**: `<ul class="erx-list">`
|
||||
- **结果项**: `<li class="item">` (每个搜索结果)
|
||||
|
||||
### 3. 单个搜索结果结构
|
||||
|
||||
#### 标题和链接区域 (.a)
|
||||
```html
|
||||
<div class="a">
|
||||
<a href="/dm/8100.html" class="main">【动漫】瑞克和莫蒂8.全集</a>
|
||||
<span class="tags"></span>
|
||||
</div>
|
||||
|
||||
提取要素:
|
||||
- 详情页链接: a.main 的 href 属性 (需要拼接完整域名)
|
||||
- 标题: a.main 的文本内容 (包含分类标签)
|
||||
```
|
||||
|
||||
#### 时间信息区域 (.i)
|
||||
```html
|
||||
<div class="i">
|
||||
<span class="erx-num-font time">2025-05-26</span>
|
||||
</div>
|
||||
|
||||
提取要素:
|
||||
- 发布时间: span.time 的文本内容 (格式: YYYY-MM-DD)
|
||||
```
|
||||
|
||||
## 详情页面结构
|
||||
|
||||
### 1. 详情页URL模式
|
||||
```
|
||||
https://1.star2.cn/{分类}/{ID}.html
|
||||
|
||||
示例:
|
||||
https://1.star2.cn/dm/8100.html (动漫类别)
|
||||
https://1.star2.cn/ju/8737.html (国剧类别)
|
||||
|
||||
分类说明:
|
||||
- /dm/ : 动漫
|
||||
- /ju/ : 国剧
|
||||
- /dj/ : 短剧
|
||||
- /zy/ : 综艺
|
||||
- /mv/ : 电影
|
||||
- /rh/ : 韩日剧
|
||||
- /ym/ : 英美剧
|
||||
- /wj/ : 外剧
|
||||
- /qt/ : 其他
|
||||
```
|
||||
|
||||
### 2. 详情页面关键区域
|
||||
|
||||
#### 标题区域
|
||||
```html
|
||||
<h1>【动漫】瑞克和莫蒂8.全集</h1>
|
||||
|
||||
提取要素:
|
||||
- 标题: h1 的文本内容
|
||||
```
|
||||
|
||||
#### 元信息区域
|
||||
```html
|
||||
<section class="erx-tct i">
|
||||
<span class="time">2025-05-26</span>
|
||||
<span class="view">823次浏览</span>
|
||||
</section>
|
||||
|
||||
提取要素:
|
||||
- 发布时间: span.time 的文本内容
|
||||
- 浏览次数: span.view 的文本内容 (可选)
|
||||
```
|
||||
|
||||
#### 下载链接区域
|
||||
```html
|
||||
<div class="dlipp-cont-wp">
|
||||
<div class="dlipp-cont-inner">
|
||||
<div class="dlipp-cont-hd">
|
||||
<img src="/skin/images/tv.png" alt="影片地址">
|
||||
<span>影片地址</span>
|
||||
</div>
|
||||
<div class="dlipp-cont-bd">
|
||||
<a class="dlipp-dl-btn j-wbdlbtn-dlipp" href="https://pan.quark.cn/s/2b941bc45d86" target="_blank">
|
||||
<img src="/skin/images/kk.png" alt="夸克网盘">
|
||||
<span>夸克网盘</span>
|
||||
</a>
|
||||
<a class="dlipp-dl-btn j-wbdlbtn-dlipp" href="https://pan.baidu.com/s/1E92Hy50UxJnTTrU3qD9jqQ?pwd=8888" target="_blank">
|
||||
<img src="/skin/images/bd.png" alt="百度网盘">
|
||||
<span>百度网盘</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
提取要素:
|
||||
- 网盘链接: .dlipp-cont-bd a.dlipp-dl-btn 的 href 属性
|
||||
- 网盘类型: 从链接URL自动识别 (quark.cn, baidu.com 等)
|
||||
- 提取码: 从URL参数中提取 (如 ?pwd=8888)
|
||||
```
|
||||
|
||||
## CSS选择器总结
|
||||
|
||||
| 数据项 | 页面类型 | CSS选择器 | 提取方式 |
|
||||
|--------|----------|-----------|----------|
|
||||
| 搜索结果列表 | 搜索页 | `ul.erx-list li.item` | 遍历所有结果项 |
|
||||
| 标题 | 搜索页 | `.a a.main` | 文本内容 |
|
||||
| 详情页链接 | 搜索页 | `.a a.main` | href 属性 |
|
||||
| 发布时间 | 搜索页 | `.i span.time` | 文本内容 |
|
||||
| 详情页标题 | 详情页 | `h1` | 文本内容 |
|
||||
| 详情页时间 | 详情页 | `section.i span.time` | 文本内容 |
|
||||
| 浏览次数 | 详情页 | `section.i span.view` | 文本内容 |
|
||||
| 下载链接 | 详情页 | `.dlipp-cont-bd a.dlipp-dl-btn` | href 属性 |
|
||||
|
||||
## 实现要点
|
||||
|
||||
### 1. 网盘类型自动识别
|
||||
根据链接URL自动识别网盘类型:
|
||||
```
|
||||
pan.quark.cn → quark (夸克网盘)
|
||||
pan.baidu.com → baidu (百度网盘)
|
||||
aliyundrive.com → aliyun (阿里云盘)
|
||||
alipan.com → aliyun (阿里云盘新域名)
|
||||
cloud.189.cn → tianyi (天翼云盘)
|
||||
pan.xunlei.com → xunlei (迅雷网盘)
|
||||
115.com → 115 (115网盘)
|
||||
123pan.com → 123 (123网盘)
|
||||
caiyun.139.com → mobile (移动云盘)
|
||||
```
|
||||
|
||||
### 2. 提取码处理
|
||||
- 百度网盘: `?pwd=1234` 格式
|
||||
- 其他网盘: 一般无需提取码或在URL中已包含
|
||||
|
||||
### 3. 标题清理
|
||||
- 保留分类标签如 `【动漫】`、`【国剧】` 等
|
||||
- 去除多余空格和特殊字符
|
||||
|
||||
### 4. 时间格式处理
|
||||
- 原格式: `2025-05-26`
|
||||
- 需转换为标准时间对象
|
||||
|
||||
### 5. 内容描述
|
||||
- 可以从标题中提取分类信息作为描述
|
||||
- 或使用固定描述如 "剧透社影视资源"
|
||||
|
||||
## 支持的分类
|
||||
|
||||
| 分类代码 | 中文名称 | 路径 | 说明 |
|
||||
|----------|----------|------|------|
|
||||
| dm | 动漫 | /dm/ | 动画、动漫作品 |
|
||||
| ju | 国剧 | /ju/ | 国产电视剧 |
|
||||
| dj | 短剧 | /dj/ | 短视频剧集 |
|
||||
| zy | 综艺 | /zy/ | 综艺节目 |
|
||||
| mv | 电影 | /mv/ | 电影作品 |
|
||||
| rh | 韩日 | /rh/ | 韩国、日本影视剧 |
|
||||
| ym | 英美 | /ym/ | 英美影视剧 |
|
||||
| wj | 外剧 | /wj/ | 其他外国影视剧 |
|
||||
| qt | 其他 | /qt/ | 其他类型内容 |
|
||||
|
||||
## 错误处理
|
||||
|
||||
1. **网络超时**: 设置合理的超时时间,实现重试机制
|
||||
2. **解析失败**: 对于解析失败的页面,记录日志但不中断流程
|
||||
3. **空结果**: 搜索无结果时返回空数组
|
||||
4. **链接失效**: 验证链接格式,过滤掉明显无效的链接
|
||||
|
||||
## 反爬虫处理
|
||||
|
||||
1. **请求头设置**: 使用标准浏览器User-Agent
|
||||
2. **请求频率**: 控制请求间隔,避免被封IP
|
||||
3. **错误重试**: 遇到403/429等状态码时适当延迟重试
|
||||
|
||||
## 特殊说明
|
||||
|
||||
1. **域名**: 网站可能使用多个域名或动态域名,需要灵活处理
|
||||
2. **编码**: 确保中文关键词正确URL编码
|
||||
3. **链接拼接**: 详情页链接为相对路径,需要拼接完整URL
|
||||
4. **缓存**: 建议缓存搜索结果,避免重复请求
|
||||
348
plugin/jutoushe/jutoushe.go
Normal file
348
plugin/jutoushe/jutoushe.go
Normal file
@@ -0,0 +1,348 @@
|
||||
package jutoushe
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/PuerkitoBio/goquery"
|
||||
|
||||
"pansou/model"
|
||||
"pansou/plugin"
|
||||
)
|
||||
|
||||
type JutoushePlugin struct {
|
||||
*plugin.BaseAsyncPlugin
|
||||
}
|
||||
|
||||
func init() {
|
||||
p := &JutoushePlugin{
|
||||
BaseAsyncPlugin: plugin.NewBaseAsyncPlugin("jutoushe", 1),
|
||||
}
|
||||
plugin.RegisterGlobalPlugin(p)
|
||||
}
|
||||
|
||||
// Search 执行搜索并返回结果(兼容性方法)
|
||||
func (p *JutoushePlugin) Search(keyword string, ext map[string]interface{}) ([]model.SearchResult, error) {
|
||||
result, err := p.SearchWithResult(keyword, ext)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result.Results, nil
|
||||
}
|
||||
|
||||
// SearchWithResult 执行搜索并返回包含IsFinal标记的结果(推荐方法)
|
||||
func (p *JutoushePlugin) SearchWithResult(keyword string, ext map[string]interface{}) (model.PluginSearchResult, error) {
|
||||
return p.AsyncSearchWithResult(keyword, p.searchImpl, p.MainCacheKey, ext)
|
||||
}
|
||||
|
||||
// searchImpl 实现搜索逻辑
|
||||
func (p *JutoushePlugin) searchImpl(client *http.Client, keyword string, ext map[string]interface{}) ([]model.SearchResult, error) {
|
||||
// 1. 构建搜索URL
|
||||
baseURL := "https://1.star2.cn"
|
||||
searchURL := fmt.Sprintf("%s/search/?keyword=%s", baseURL, url.QueryEscape(keyword))
|
||||
|
||||
// 2. 创建带超时的上下文
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
||||
defer cancel()
|
||||
|
||||
// 3. 创建请求对象
|
||||
req, err := http.NewRequestWithContext(ctx, "GET", searchURL, nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("[%s] 创建请求失败: %w", p.Name(), err)
|
||||
}
|
||||
|
||||
// 4. 设置请求头,避免反爬虫检测
|
||||
req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36")
|
||||
req.Header.Set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8")
|
||||
req.Header.Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8")
|
||||
req.Header.Set("Connection", "keep-alive")
|
||||
req.Header.Set("Referer", baseURL+"/")
|
||||
|
||||
// 5. 发送HTTP请求(带重试机制)
|
||||
resp, err := p.doRequestWithRetry(req, client)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("[%s] 搜索请求失败: %w", p.Name(), err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
// 6. 检查状态码
|
||||
if resp.StatusCode != 200 {
|
||||
return nil, fmt.Errorf("[%s] 请求返回状态码: %d", p.Name(), resp.StatusCode)
|
||||
}
|
||||
|
||||
// 7. 解析搜索结果页面
|
||||
doc, err := goquery.NewDocumentFromReader(resp.Body)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("[%s] HTML解析失败: %w", p.Name(), err)
|
||||
}
|
||||
|
||||
// 8. 提取搜索结果
|
||||
var results []model.SearchResult
|
||||
doc.Find("ul.erx-list li.item").Each(func(i int, s *goquery.Selection) {
|
||||
// 提取标题和链接
|
||||
linkElem := s.Find(".a a.main")
|
||||
title := strings.TrimSpace(linkElem.Text())
|
||||
detailPath, exists := linkElem.Attr("href")
|
||||
|
||||
if !exists || title == "" {
|
||||
return // 跳过无效项
|
||||
}
|
||||
|
||||
// 构建完整的详情页URL
|
||||
detailURL := baseURL + detailPath
|
||||
|
||||
// 提取发布时间
|
||||
timeStr := strings.TrimSpace(s.Find(".i span.time").Text())
|
||||
publishTime := p.parseDate(timeStr)
|
||||
|
||||
// 构建唯一ID
|
||||
uniqueID := fmt.Sprintf("%s-%s", p.Name(), p.extractIDFromURL(detailPath))
|
||||
|
||||
// 创建搜索结果(先不获取下载链接)
|
||||
result := model.SearchResult{
|
||||
UniqueID: uniqueID,
|
||||
Title: title,
|
||||
Content: fmt.Sprintf("剧透社影视资源:%s", title),
|
||||
Datetime: publishTime,
|
||||
Tags: p.extractTags(title),
|
||||
Links: []model.Link{}, // 稍后从详情页获取
|
||||
Channel: "", // 插件搜索结果必须为空字符串
|
||||
}
|
||||
|
||||
// 异步获取详情页的下载链接
|
||||
if links := p.getDetailLinks(client, detailURL); len(links) > 0 {
|
||||
result.Links = links
|
||||
results = append(results, result)
|
||||
}
|
||||
})
|
||||
|
||||
// 9. 关键词过滤
|
||||
filteredResults := plugin.FilterResultsByKeyword(results, keyword)
|
||||
|
||||
return filteredResults, nil
|
||||
}
|
||||
|
||||
// doRequestWithRetry 带重试机制的HTTP请求
|
||||
func (p *JutoushePlugin) doRequestWithRetry(req *http.Request, client *http.Client) (*http.Response, error) {
|
||||
maxRetries := 3
|
||||
var lastErr error
|
||||
|
||||
for i := 0; i < maxRetries; i++ {
|
||||
if i > 0 {
|
||||
// 指数退避重试
|
||||
backoff := time.Duration(1<<uint(i-1)) * 200 * time.Millisecond
|
||||
time.Sleep(backoff)
|
||||
}
|
||||
|
||||
// 克隆请求避免并发问题
|
||||
reqClone := req.Clone(req.Context())
|
||||
|
||||
resp, err := client.Do(reqClone)
|
||||
if err == nil && resp.StatusCode == 200 {
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
if resp != nil {
|
||||
resp.Body.Close()
|
||||
}
|
||||
lastErr = err
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("重试 %d 次后仍然失败: %w", maxRetries, lastErr)
|
||||
}
|
||||
|
||||
// getDetailLinks 获取详情页的下载链接
|
||||
func (p *JutoushePlugin) getDetailLinks(client *http.Client, detailURL string) []model.Link {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
|
||||
defer cancel()
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, "GET", detailURL, nil)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// 设置请求头
|
||||
req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36")
|
||||
req.Header.Set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8")
|
||||
req.Header.Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8")
|
||||
req.Header.Set("Referer", "https://1.star2.cn/")
|
||||
|
||||
resp, err := client.Do(req)
|
||||
if err != nil || resp.StatusCode != 200 {
|
||||
if resp != nil {
|
||||
resp.Body.Close()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
doc, err := goquery.NewDocumentFromReader(resp.Body)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
var links []model.Link
|
||||
|
||||
// 提取下载链接
|
||||
doc.Find(".dlipp-cont-bd a.dlipp-dl-btn").Each(func(i int, s *goquery.Selection) {
|
||||
href, exists := s.Attr("href")
|
||||
if !exists || href == "" {
|
||||
return
|
||||
}
|
||||
|
||||
// 过滤掉无效链接
|
||||
if !p.isValidNetworkDriveURL(href) {
|
||||
return
|
||||
}
|
||||
|
||||
// 确定网盘类型和提取提取码
|
||||
cloudType := p.determineCloudType(href)
|
||||
password := p.extractPassword(href)
|
||||
|
||||
link := model.Link{
|
||||
Type: cloudType,
|
||||
URL: href,
|
||||
Password: password,
|
||||
}
|
||||
|
||||
links = append(links, link)
|
||||
})
|
||||
|
||||
return links
|
||||
}
|
||||
|
||||
// determineCloudType 根据URL确定网盘类型
|
||||
func (p *JutoushePlugin) determineCloudType(url string) string {
|
||||
switch {
|
||||
case strings.Contains(url, "pan.quark.cn"):
|
||||
return "quark"
|
||||
case strings.Contains(url, "drive.uc.cn"):
|
||||
return "uc"
|
||||
case strings.Contains(url, "pan.baidu.com"):
|
||||
return "baidu"
|
||||
case strings.Contains(url, "aliyundrive.com") || strings.Contains(url, "alipan.com"):
|
||||
return "aliyun"
|
||||
case strings.Contains(url, "pan.xunlei.com"):
|
||||
return "xunlei"
|
||||
case strings.Contains(url, "cloud.189.cn"):
|
||||
return "tianyi"
|
||||
case strings.Contains(url, "115.com"):
|
||||
return "115"
|
||||
case strings.Contains(url, "123pan.com"):
|
||||
return "123"
|
||||
case strings.Contains(url, "caiyun.139.com"):
|
||||
return "mobile"
|
||||
case strings.Contains(url, "mypikpak.com"):
|
||||
return "pikpak"
|
||||
default:
|
||||
return "others"
|
||||
}
|
||||
}
|
||||
|
||||
// extractPassword 从URL中提取提取码
|
||||
func (p *JutoushePlugin) extractPassword(url string) string {
|
||||
// 处理百度网盘的pwd参数
|
||||
if strings.Contains(url, "pan.baidu.com") && strings.Contains(url, "pwd=") {
|
||||
re := regexp.MustCompile(`pwd=([^&]+)`)
|
||||
matches := re.FindStringSubmatch(url)
|
||||
if len(matches) > 1 {
|
||||
return matches[1]
|
||||
}
|
||||
}
|
||||
|
||||
// 其他网盘暂不处理提取码
|
||||
return ""
|
||||
}
|
||||
|
||||
// isValidNetworkDriveURL 验证是否为有效的网盘链接
|
||||
func (p *JutoushePlugin) isValidNetworkDriveURL(url string) bool {
|
||||
if url == "" {
|
||||
return false
|
||||
}
|
||||
|
||||
// 检查是否为HTTP/HTTPS链接
|
||||
if !strings.HasPrefix(url, "http://") && !strings.HasPrefix(url, "https://") {
|
||||
return false
|
||||
}
|
||||
|
||||
// 检查是否包含已知网盘域名
|
||||
knownDomains := []string{
|
||||
"pan.quark.cn", "drive.uc.cn", "pan.baidu.com",
|
||||
"aliyundrive.com", "alipan.com", "pan.xunlei.com",
|
||||
"cloud.189.cn", "115.com", "123pan.com",
|
||||
"caiyun.139.com", "mypikpak.com",
|
||||
}
|
||||
|
||||
for _, domain := range knownDomains {
|
||||
if strings.Contains(url, domain) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// extractIDFromURL 从URL路径中提取ID
|
||||
func (p *JutoushePlugin) extractIDFromURL(urlPath string) string {
|
||||
// 从 /dm/8100.html 提取 8100
|
||||
re := regexp.MustCompile(`/([^/]+)/(\d+)\.html`)
|
||||
matches := re.FindStringSubmatch(urlPath)
|
||||
if len(matches) > 2 {
|
||||
return matches[2]
|
||||
}
|
||||
|
||||
// 如果无法提取,使用完整路径作为ID
|
||||
return strings.ReplaceAll(urlPath, "/", "_")
|
||||
}
|
||||
|
||||
// extractTags 从标题中提取标签
|
||||
func (p *JutoushePlugin) extractTags(title string) []string {
|
||||
var tags []string
|
||||
|
||||
// 提取分类标签
|
||||
categoryPattern := regexp.MustCompile(`【([^】]+)】`)
|
||||
matches := categoryPattern.FindAllStringSubmatch(title, -1)
|
||||
for _, match := range matches {
|
||||
if len(match) > 1 {
|
||||
tags = append(tags, match[1])
|
||||
}
|
||||
}
|
||||
|
||||
// 如果没有提取到分类,添加默认标签
|
||||
if len(tags) == 0 {
|
||||
tags = append(tags, "影视资源")
|
||||
}
|
||||
|
||||
return tags
|
||||
}
|
||||
|
||||
// parseDate 解析日期字符串
|
||||
func (p *JutoushePlugin) parseDate(dateStr string) time.Time {
|
||||
if dateStr == "" {
|
||||
return time.Now()
|
||||
}
|
||||
|
||||
// 尝试解析 YYYY-MM-DD 格式
|
||||
if t, err := time.Parse("2006-01-02", dateStr); err == nil {
|
||||
return t
|
||||
}
|
||||
|
||||
// 尝试解析 YYYY年MM月DD日 格式
|
||||
re := regexp.MustCompile(`(\d{4})年(\d{1,2})月(\d{1,2})日`)
|
||||
matches := re.FindStringSubmatch(dateStr)
|
||||
if len(matches) == 4 {
|
||||
year, _ := strconv.Atoi(matches[1])
|
||||
month, _ := strconv.Atoi(matches[2])
|
||||
day, _ := strconv.Atoi(matches[3])
|
||||
return time.Date(year, time.Month(month), day, 0, 0, 0, 0, time.Local)
|
||||
}
|
||||
|
||||
// 解析失败,返回当前时间
|
||||
return time.Now()
|
||||
}
|
||||
Reference in New Issue
Block a user