diff --git a/chrome.go b/chrome.go index c08de7f..481db6a 100644 --- a/chrome.go +++ b/chrome.go @@ -8,7 +8,6 @@ import ( "apigo.cc/gojs/goja" "github.com/go-rod/rod" "github.com/go-rod/rod/lib/launcher" - "github.com/ssgo/log" "github.com/ssgo/u" ) @@ -21,8 +20,10 @@ type Chrome struct { var chromes = map[string]*Chrome{} var chromesLock sync.Mutex -func (ch *Chrome) Close() { +func (ch *Chrome) Close(vm *goja.Runtime) { + logger := gojs.GetLogger(vm) if ch.browser != nil { + logger.Info("关闭本地 Chrome 浏览器", "id", ch.id) ch.browser.Close() ch.browser = nil } @@ -36,19 +37,21 @@ func (ch *Chrome) Close() { chromesLock.Unlock() } -func CloseAllChrome() { +func CloseAllChrome(vm *goja.Runtime) { n := len(chromes) if n > 0 { for _, ch := range chromes { - ch.Close() + ch.Close(vm) } - log.DefaultLogger.Info("关闭所有 Chrome 浏览器", "count", n) + logger := gojs.GetLogger(vm) + logger.Info("关闭所有 Chrome 浏览器", "count", n) } } func StartChrome(showWindow *bool, vm *goja.Runtime) (*Chrome, error) { logger := gojs.GetLogger(vm) ch := &Chrome{} + ch.id = u.UniqueId() ch.browser = rod.New() if localBrowserPath, hasLocalBrowser := launcher.LookPath(); hasLocalBrowser { ch.launcher = launcher.New().Bin(localBrowserPath).Headless(!u.Bool(showWindow)).Set("no-sandbox").Set("disable-gpu").Set("disable-dev-shm-usage").Set("single-process") @@ -60,18 +63,17 @@ func StartChrome(showWindow *bool, vm *goja.Runtime) (*Chrome, error) { } localChromeURL, err := ch.launcher.Launch() if err != nil { - ch.Close() + ch.Close(vm) return nil, gojs.Err(err) } - logger.Info("启动本地 Chrome 浏览器", "url", localChromeURL, "path", localBrowserPath) + logger.Info("启动本地 Chrome 浏览器", "id", ch.id, "url", localChromeURL, "path", localBrowserPath) ch.browser.ControlURL(localChromeURL) } if err := ch.browser.Connect(); err != nil { - ch.Close() + ch.Close(vm) return nil, gojs.Err(err) } - ch.id = u.UniqueId() chromesLock.Lock() chromes[ch.id] = ch chromesLock.Unlock() diff --git a/go.mod b/go.mod index 8823333..c41e063 100644 --- a/go.mod +++ b/go.mod @@ -3,11 +3,11 @@ module apigo.cc/gojs/http go 1.23.0 require ( - apigo.cc/gojs v0.0.21 + apigo.cc/gojs v0.0.22 apigo.cc/gojs/console v0.0.2 apigo.cc/gojs/file v0.0.4 apigo.cc/gojs/util v0.0.12 - github.com/go-rod/rod v0.112.8 + github.com/go-rod/rod v0.116.2 github.com/gorilla/websocket v1.5.3 github.com/ssgo/config v1.7.9 github.com/ssgo/httpclient v1.7.8 @@ -36,7 +36,9 @@ require ( github.com/ssgo/tool v0.4.29 // indirect github.com/tklauser/go-sysconf v0.3.15 // indirect github.com/tklauser/numcpus v0.10.0 // indirect + github.com/ysmood/fetchup v0.2.3 // indirect github.com/ysmood/goob v0.4.0 // indirect + github.com/ysmood/got v0.40.0 // indirect github.com/ysmood/gson v0.7.3 // indirect github.com/ysmood/leakless v0.9.0 // indirect github.com/yusufpapurcu/wmi v1.2.4 // indirect diff --git a/http.go b/http.go index ba2f05e..ba0bc0b 100644 --- a/http.go +++ b/http.go @@ -76,9 +76,11 @@ func init() { exportPart1 := "export default {\n" + strings.TrimRight(a[1], "}") return strings.Replace(httpTS, "export default {", exportPart1, 1) + "\n" + a[0] }, - Desc: "", - Example: "", - WaitForStop: CloseAllChrome, + Desc: "", + Example: "", + WaitForStop: func() { + CloseAllChrome(nil) + }, }) } diff --git a/http.ts b/http.ts index 4885f59..67f9828 100644 --- a/http.ts +++ b/http.ts @@ -26,9 +26,6 @@ function upload(url: string, form: Object, files: Object, headers?: Object): Res function download(filename: string, url: string, callback?: (finished: number, total: number) => void, headers?: Object): Result { return null as any } function connect(url: string, config?: WSConfig): WS { return null as any } -interface Chrome { -} - interface Client { get(url: string, headers?: Object): Result head(url: string, headers?: Object): Result diff --git a/page.go b/page.go index fbc584e..3d201f3 100644 --- a/page.go +++ b/page.go @@ -17,6 +17,7 @@ import ( type Page struct { page *rod.Page longTimeoutPage *rod.Page + originPage *rod.Page // Res []Resource } @@ -47,24 +48,9 @@ func (ch *Chrome) Open(url string) (*Page, error) { return nil, gojs.Err(err) } - longTimeoutPage := page.Timeout(time.Second * 15) - page = page.Timeout(time.Second * 5) - - pg := &Page{page: page, longTimeoutPage: longTimeoutPage} - // pg := &Page{page: page, longTimeoutPage: longTimeoutPage, Res: []Resource{}} - // proto.NetworkEnable{}.Call(page) - // longTimeoutPage.EachEvent(func(e *proto.NetworkResponseReceived) { - // fmt.Println(u.BMagenta(e.Response.URL), e.Type, e.Response.Status, e.Response.Headers["Content-Type"].Str(), e.Response.Headers["Content-Length"].Int()) - // pg.Res = append(pg.Res, Resource{ - // URL: e.Response.URL, - // Type: string(e.Type), - // Status: e.Response.Status, - // Size: e.Response.Headers["Content-Length"].Int(), - // MimeType: e.Response.Headers["Content-Type"].Str(), - // }) - // }) - - pg.longTimeoutPage.WaitLoad() + pg := &Page{originPage: page} + pg.ResetTimeout() + pg.WaitPageLoad() return pg, nil } @@ -198,13 +184,19 @@ func (pg *Page) Navigate(url string) error { if err != nil { return gojs.Err(err) } - pg.longTimeoutPage.WaitLoad() + pg.WaitPageLoad() return nil } // WaitLoad 等待页面加载完成 func (pg *Page) WaitPageLoad() error { - return gojs.Err(pg.longTimeoutPage.WaitLoad()) + time.Sleep(100 * time.Millisecond) + err := pg.page.WaitLoad() + if err != nil { + return gojs.Err(err) + } + pg.ResetTimeout() + return nil } // WaitIdle 等待页面空闲(无网络请求和JS执行) @@ -215,6 +207,28 @@ func (pg *Page) WaitIdle(ms *int) error { return gojs.Err(pg.page.WaitIdle(time.Millisecond * time.Duration(*ms))) } +// Wait 等待回调函数函数返回true +func (pg *Page) Wait(ms int, fn *func() bool) { + for i := 0; i < ms; i += 100 { + if fn != nil && (*fn)() { + break + } + time.Sleep(100 * time.Millisecond) + } + pg.ResetTimeout() +} + +// RandWait 随机等待 +func (pg *Page) RandWait(msMin int, msMax int) { + ms := u.GlobalRand1.Intn(msMax-msMin) + msMin + pg.Wait(ms, nil) +} + +func (pg *Page) ResetTimeout() { + pg.page = pg.originPage.Timeout(time.Second * 5) + pg.longTimeoutPage = pg.originPage.Timeout(time.Second * 15) +} + // WaitStable 等待页面DOM稳定 // func (pg *Page) WaitStable(ms *int) error { // if ms == nil { @@ -391,7 +405,7 @@ func (pg *Page) Back() error { if err != nil { return gojs.Err(err) } - pg.longTimeoutPage.WaitIdle(time.Second) + pg.WaitPageLoad() return nil } @@ -400,7 +414,7 @@ func (pg *Page) Forward() error { if err != nil { return gojs.Err(err) } - pg.longTimeoutPage.WaitIdle(time.Second) + pg.WaitPageLoad() return nil } @@ -447,7 +461,7 @@ func (el *Element) Text() (string, error) { } func (el *Element) InnerHTML() (string, error) { - r, err := el.element.Eval(`el => el.innerHTML`) + r, err := el.element.Eval(`el => {return el.innerHTML}`) if err != nil { return "", gojs.Err(err) } @@ -1061,7 +1075,7 @@ func (el *Element) RemoveProperty(name string) error { // IsInteractable 元素是否可交互 func (el *Element) IsInteractable() (bool, error) { _, err := el.element.Interactable() - if errors.Is(err, &rod.ErrNotInteractable{}) { + if errors.Is(err, &rod.NotInteractableError{}) { return false, nil } if err != nil {