Skip to content

Commit

Permalink
新增代理访问、浏览器数量限制、缓存开关,修复程序关闭浏览器不自动关闭的情况等
Browse files Browse the repository at this point in the history
  • Loading branch information
1944876825 committed Mar 22, 2024
1 parent 68b0dee commit e677f5f
Show file tree
Hide file tree
Showing 6 changed files with 136 additions and 70 deletions.
37 changes: 24 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,24 +1,35 @@
# sniffing.tools
嗅探网页媒体资源
嗅探网站网络资源工具

## 主要功能
* 嗅探网页中的媒体资源

## config.yaml 配置(不是很详细,请参考实例文件)
## windows使用方法
- 直接双击启动
- 自制.bat脚本,文件名:start.bat,代码如下:
```
start cmd /K "脚本名称.exe"
```

* port 项目运行端口
* headless 是否显示浏览器(false 当解析时,会显示浏览器加载网页的过程)
* hc_time 资源缓存时效(单位:秒,在此范围内,相同链接会走缓存的解析数据)
* parse
* name 资源名称
* match 资源特征匹配(可填多个)
* wait 等待资源加载成功(可填多个,需要填写css选择器,如 .play #play,程序会等待这个元素加载完毕再开始嗅探)
* click 如果有需要点击播放按钮才加载媒体的网页,可以填这个,不过需要手动使用css选择器找到对应按钮的(可填多个,当wait执行完才会执行这个)
* white 资源特征白名单(可填多个,包含此特征的资源会被选择)
* black 资源特征白名单(可填多个,包含此特征的资源不会被选择)
## linux使用方法
首先保证你的系统安装了谷歌浏览器,如果没有安装,请自行安装
- 运行方式1(缺点,命令行关闭就没了,可用于测试)
```
./脚本名称
```
- 运行方式2
```
nohup ./脚本名称
```
- 运行方式3
使用你习惯用的项目管理器,比如宝塔自带的Go项目管理器

## 使用方式
你的网址:端口/xt?url=
- 你的网址:端口/xt?url=
- 你的位置:端口/xt?proxy=你的代理&url=

## config.yaml 配置文件(不是很详细,请参考实例文件)
如果需要自定义配置,请将代码中的文件拷贝在程序同级目录,请参考config.yaml内注释

## LICENSE

Expand Down
9 changes: 6 additions & 3 deletions config.yaml
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
port: 8081
headless: false # true 不弹出浏览器 false 弹窗浏览器
port: 8081 # 项目运行端口
headless: true # true 不弹出浏览器 false 弹窗浏览器
hc: true # true 开启缓存 false 关闭缓存
hc_time: 300 # 缓存保存时间 单位:秒
xt_time: 300 # 嗅探超时时间 单位:秒
parse:
xc_max: 3 # 最多打开几个浏览器
proxy: # 默认代理,不填就不同代理,填了就是默认代理,如果需要动态代理,请在访问接口时添加参数 proxy 如:http://127.0.0.1:8081/xt?proxy=112.30.155.83:12792&url=
parse: # 嗅探规则,特殊资源特殊对待
- name: "西瓜视频" # 名称
match: # 资源特征
- "ixigua.com"
Expand Down
11 changes: 7 additions & 4 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,13 @@ import (
var Config = configModel{}

type configModel struct {
Port int `yaml:"port"`
HcTime int64 `yaml:"hc_time"`
XtTime int `yaml:"xt_time"`
Headless bool `yaml:"headless"`
Port int `yaml:"port"`
Hc bool `yaml:"hc"`
HcTime int64 `yaml:"hc_time"`
XtTime int `yaml:"xt_time"`
Headless bool `yaml:"headless"`
Proxy string `yaml:"proxy"`
XcMax int `yaml:"xc_max"`
Parse []ParseItemModel
}
type ParseItemModel struct {
Expand Down
12 changes: 6 additions & 6 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ require (
github.com/chromedp/cdproto v0.0.0-20231011050154-1d073bb38998
github.com/chromedp/chromedp v0.9.3
github.com/gin-gonic/gin v1.9.1
gopkg.in/yaml.v3 v3.0.1
)

require (
Expand Down Expand Up @@ -33,10 +34,9 @@ require (
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.11 // indirect
golang.org/x/arch v0.3.0 // indirect
golang.org/x/crypto v0.9.0 // indirect
golang.org/x/net v0.10.0 // indirect
golang.org/x/sys v0.8.0 // indirect
golang.org/x/text v0.9.0 // indirect
google.golang.org/protobuf v1.30.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
golang.org/x/crypto v0.21.0 // indirect
golang.org/x/net v0.21.0 // indirect
golang.org/x/sys v0.18.0 // indirect
golang.org/x/text v0.14.0 // indirect
google.golang.org/protobuf v1.33.0 // indirect
)
60 changes: 32 additions & 28 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,13 @@ import (
"fmt"
"github.com/gin-gonic/gin"
"log"
"os"
"os/signal"
"sniffing.tools/config"
"sniffing.tools/server"
"strconv"
"strings"
"syscall"
"time"
)

Expand All @@ -22,6 +25,15 @@ type UrlItemModel struct {
var Urls = make(map[string]UrlItemModel)

func main() {
signalChan := make(chan os.Signal, 1)
signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM)

// 主函数
go func() {
<-signalChan
server.CloseServers() // 确保关闭浏览器
os.Exit(0) // 退出程序
}()
fmt.Println("作者:By易仝 QQ:1944876825")
fmt.Println("开源地址:https://github.com/1944876825/sniffing.tools")

Expand All @@ -46,44 +58,46 @@ func main() {
// router 路由
func router(c *gin.Context) {
url := c.Query("url")
proxy := c.Query("proxy")
url = strings.TrimSpace(url)
log.Println("url:", url)
md5Url := getMD5(url)
log.Println("url: ", url)
if len(url) < 1 {
c.JSON(200, gin.H{"code": 404, "msg": "缺少URL"})
return
}
if Urls[getMD5(url)].Status == 1 {
if config.Config.Hc && Urls[md5Url].Status == 1 {
timestamp := time.Now().Unix()
timeExp, _ := strconv.ParseInt(Urls[getMD5(url)].TimeExp, 10, 64)
timeExp, _ := strconv.ParseInt(Urls[md5Url].TimeExp, 10, 64)
if timestamp < timeExp {
c.JSON(200, gin.H{
"code": 200,
"msg": "解析成功",
"url": Urls[getMD5(url)].PlayUrl,
"url": Urls[md5Url].PlayUrl,
})
return
}
}
if Urls[getMD5(url)].Status == 2 {
for Urls[getMD5(url)].Status == 2 {
if Urls[md5Url].Status == 2 {
for Urls[md5Url].Status == 2 {
time.Sleep(time.Millisecond * 200)
}
} else {
Urls[getMD5(url)] = UrlItemModel{
Urls[md5Url] = UrlItemModel{
Status: 2,
PlayUrl: "",
TimeExp: "",
}
go toParse(url)
for Urls[getMD5(url)].Status == 2 {
go toParse(url, proxy)
for Urls[md5Url].Status == 2 {
time.Sleep(time.Millisecond * 200)
}
}
if Urls[getMD5(url)].PlayUrl != "" {
if Urls[md5Url].PlayUrl != "" {
c.JSON(200, gin.H{
"code": 200,
"msg": "解析成功",
"url": Urls[getMD5(url)].PlayUrl,
"url": Urls[md5Url].PlayUrl,
})
} else {
c.JSON(200, gin.H{
Expand All @@ -92,7 +106,7 @@ func router(c *gin.Context) {
})
}
}
func toParse(url string) {
func toParse(url, proxy string) {
var mat = false
var cuParse = config.ParseItemModel{}

Expand All @@ -109,34 +123,24 @@ func toParse(url string) {
}
}

var ser = server.Model{}
ser.Url = url
ser := server.GetServer()
ser.Init(proxy)
ser.Data = cuParse

//if mat {
// if len(cuParse.Start) > 0 {
// ser.Url = cuParse.Start + ser.Url
// }
// if len(cuParse.End) > 0 {
// ser.Url = ser.Url + cuParse.End
// }
//}
ser.Init()
playUrl, err := ser.StartFindResource()
playUrl, err := ser.StartFindResource(url)

timestamp := time.Now().Unix()
futureTimestamp := timestamp + config.Config.HcTime

md5Url := getMD5(url)
if err == nil {
Urls[getMD5(url)] = UrlItemModel{
Urls[md5Url] = UrlItemModel{
Status: 1,
PlayUrl: playUrl,
TimeExp: strconv.FormatInt(futureTimestamp, 10),
}
return
}
log.Println("解析失败", err.Error())
Urls[getMD5(url)] = UrlItemModel{
Urls[md5Url] = UrlItemModel{
Status: 3,
PlayUrl: playUrl,
TimeExp: strconv.FormatInt(futureTimestamp, 10),
Expand Down
77 changes: 61 additions & 16 deletions server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,53 +5,81 @@ import (
"fmt"
"github.com/chromedp/cdproto/network"
"github.com/chromedp/chromedp"
"log"
"sniffing.tools/config"
"strings"
"sync"
"time"
)

var mutex sync.Mutex

func GetServer() *Model {
if len(Servers) >= config.Config.XcMax {
for len(Servers) >= config.Config.XcMax {
time.Sleep(time.Millisecond * 200)
}
}
xc := &Model{}
mutex.Lock()
Servers = append(Servers, xc)
mutex.Unlock()
return xc
}

var Servers []*Model

type Model struct {
Data config.ParseItemModel
Url string
ctx context.Context
playUrl string
needListen bool
cancel []context.CancelFunc
}

func (s *Model) Init() {
func (s *Model) Init(proxy string) {
// 创建Chrome浏览器上下文
var cancel context.CancelFunc
s.ctx, cancel = chromedp.NewContext(context.Background())
s.cancel = append(s.cancel, cancel)
// 截图选项
//var cancel context.CancelFunc
//s.ctx, cancel = chromedp.NewContext(context.Background())
//s.cancel = append(s.cancel, cancel)
opts := append(chromedp.DefaultExecAllocatorOptions[:],
chromedp.Flag("headless", config.Config.Headless), // 设置为true将在后台运行Chrome
chromedp.Flag("disable-gpu", true),
chromedp.Flag("no-sandbox", true),
chromedp.Flag("disable-dev-shm-usage", true),
)
if proxy == "" && config.Config.Proxy != "" {
proxy = config.Config.Proxy
}
if proxy != "" {
log.Println("使用代理:", proxy, "访问")
opts = append(opts, chromedp.ProxyServer(proxy))
}
// 创建Chrome浏览器实例
var allocCtx context.Context
allocCtx, cancel = chromedp.NewExecAllocator(s.ctx, opts...)
//var allocCtx context.Context
allocCtx, cancel := chromedp.NewExecAllocator(context.Background(), opts...)
s.cancel = append(s.cancel, cancel)
// 创建新的Chrome浏览器上下文
s.ctx, cancel = chromedp.NewContext(allocCtx)
s.cancel = append(s.cancel, cancel)
// 监听请求日志
s.listenForNetworkEvent()

// 设置窗口大小
_ = chromedp.Run(s.ctx, chromedp.EmulateViewport(1920, 1080))
//_ = chromedp.Run(s.ctx, chromedp.EmulateViewport(1920, 1080))
// 打开网页
//_ = chromedp.Run(s.ctx, chromedp.Navigate("about:blank"))
}
func (s *Model) StartFindResource() (string, error) {
func (s *Model) StartFindResource(url string) (string, error) {
defer s.Cancel()
s.needListen = true

if len(s.Data.White) < 1 {
s.Data.White = []string{".mp4", ".m3u8", ".flv"}
}
// 监听请求日志
s.needListen = true
s.listenForNetworkEvent()

// 打开网页
err := chromedp.Run(s.ctx, chromedp.Navigate(s.Url))
err := chromedp.Run(s.ctx, chromedp.Navigate(url))
if err != nil {
return "", err
}
Expand All @@ -70,12 +98,12 @@ func (s *Model) StartFindResource() (string, error) {
var i = 0
for s.playUrl == "" {
i++
if i > config.Config.XtTime*5 {
if i > config.Config.XtTime*20 {
s.needListen = false
fmt.Println("监听超时")
break
}
time.Sleep(time.Millisecond * 200)
time.Sleep(time.Millisecond * 50)
}
if len(s.playUrl) != 0 {
return s.playUrl, nil
Expand Down Expand Up @@ -127,7 +155,24 @@ func (s *Model) listenForNetworkEvent() {
})
}
func (s *Model) Cancel() {
log.Println("len1", len(Servers))
removeServer(s)
log.Println("len2", len(Servers))
for _, cancelFunc := range s.cancel {
cancelFunc()
}
}
func removeServer(serverToRemove *Model) {
for i, server := range Servers {
if server == serverToRemove {
Servers = append(Servers[:i], Servers[i+1:]...)
break
}
}
}
func CloseServers() {
for _, xc := range Servers {
xc.Cancel()
}
Servers = nil
}

0 comments on commit e677f5f

Please sign in to comment.