123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620 |
- package common
- import (
- "errors"
- "git.listensoft.net/tool/jspkit/common/lxrod"
- "git.listensoft.net/tool/jspkit/common/models"
- "git.listensoft.net/tool/jspkit/common/watermark"
- "git.listensoft.net/tool/jspkit/logger"
- "git.listensoft.net/tool/jspkit/taxerr"
- "github.com/go-rod/rod"
- "github.com/go-rod/rod/lib/input"
- "github.com/go-rod/rod/lib/proto"
- "github.com/go-rod/rod/lib/utils"
- "go.uber.org/zap"
- "os"
- "strings"
- "time"
- )
- func MustHas(page *rod.Page, xpath string) bool {
- x, _, _ := HasX(page, xpath)
- return x
- }
- func MustHasX(page *rod.Page, xpath string) bool {
- x, _, _ := HasX(page, xpath)
- return x
- }
- func MustHasXV(page *rod.Page, xpath string) bool {
- for _, element := range MustElementsX(page, xpath) {
- visible, _ := element.Visible()
- if visible {
- return true
- }
- }
- return false
- }
- func MustElementX(page *rod.Page, xpath string) *rod.Element {
- for i := 0; i < 5; i++ {
- x, _ := ElementX(page, xpath)
- if x != nil {
- return x
- }
- utils.Sleep(1)
- }
- return nil
- }
- func MustHasXV1(page *rod.Page, xpath string) bool {
- for _, element := range MustElementsX1(page, xpath) {
- visible, _ := element.Visible()
- if visible {
- return true
- }
- }
- return false
- }
- func HasX(page *rod.Page, xpath string) (bool, *rod.Element, error) {
- var x *rod.Element
- var has bool
- var err error
- err = rod.Try(func() {
- has, x, err = page.HasX(xpath)
- if has {
- return
- }
- if err != nil {
- panic(err)
- }
- if has {
- return
- }
- iframe := GetAllIframe(page)
- for _, pg := range iframe {
- has, x, err = pg.HasX(xpath)
- if has {
- return
- }
- if err != nil {
- panic(err)
- }
- if has {
- return
- }
- }
- })
- if x != nil {
- x = x.Timeout(time.Second * 15)
- }
- return has, x, err
- }
- func ElementX(page *rod.Page, xpath string) (*rod.Element, error) {
- _, element, err := HasX(page, xpath)
- if err != nil {
- err = taxerr.NewWebStuckTitle(false)
- }
- return element, err
- }
- func GetAllIframe(page *rod.Page) []*rod.Page {
- fs := make([]*rod.Page, 0)
- if page.MustHasX(`//iframe`) {
- for _, element := range page.MustElementsX(`//iframe`) {
- fs = append(fs, element.MustFrame())
- fs = append(fs, GetAllIframe(element.MustFrame())...)
- }
- }
- return fs
- }
- func MustElementXV(page *rod.Page, xpath string) *rod.Element {
- for i := 0; i < 5; i++ {
- x, _ := ElementsX(page, xpath)
- for _, element := range x {
- visible, _ := element.Visible()
- if visible {
- return element
- }
- }
- utils.Sleep(1)
- }
- return nil
- }
- func MustElementsX(page *rod.Page, xpath string) (x []*rod.Element) {
- for i := 0; i < 5; i++ {
- x, _ = ElementsX(page, xpath)
- if len(x) != 0 {
- break
- }
- utils.Sleep(1)
- }
- return x
- }
- func MustElementsX1(page *rod.Page, xpath string) (x []*rod.Element) {
- x, _ = ElementsX(page, xpath)
- return x
- }
- func ElementsX(page *rod.Page, xpath string) ([]*rod.Element, error) {
- var arr []*rod.Element
- var err error
- err = rod.Try(func() {
- r, _ := page.Timeout(ClickTimeOut).ElementsX(xpath)
- if err != nil {
- panic(err)
- }
- arr = append(arr, r...)
- for _, pg := range GetAllIframe(page) {
- pg.MustWaitLoad()
- r, err = pg.Timeout(ClickTimeOut).ElementsX(xpath)
- if err != nil {
- panic(err)
- }
- arr = append(arr, r...)
- }
- })
- return arr, err
- }
- func WaitElementX(page *rod.Page, xpath string, interval float64) *rod.Element {
- for i := 0; i < 60; i++ {
- if has, el, _ := HasX(page, xpath); has {
- return el
- }
- time.Sleep(time.Duration(float64(time.Second) * interval))
- }
- return nil
- }
- func WaitNavigation(page *rod.Page, url string) {
- navigation := page.Timeout(time.Minute).MustWaitNavigation()
- page.Timeout(time.Minute).MustNavigate(url)
- logger.Info("调试埋点11-1")
- utils.Sleep(1)
- WaitTimeOut(navigation, time.Minute)
- logger.Info("埋点11-2")
- }
- func WaitTimeOut(f func(), timeout time.Duration) {
- resultChan := make(chan struct{}, 1)
- go func() {
- f()
- resultChan <- struct{}{}
- }()
- select {
- case <-resultChan:
- return
- case <-time.After(timeout):
- panic(taxerr.NewWebStuckTitle(ComInfo.Cscsts))
- }
- }
- func Link(p *rod.Page) {
- go func() {
- //for {
- //utils.Sleep(1)
- if p == nil {
- return
- }
- rod.Try(func() {
- lxrod.DialogWatch(nil, p)
- go p.Browser().EachEvent(func(e *proto.TargetTargetCreated) {
- defer func() {
- if r := recover(); r != nil {
- logger.Error("EachPageCreatedEvent recover:", zap.Any("r", r))
- }
- }()
- if e.TargetInfo.Type != proto.TargetTargetInfoTypePage {
- return
- }
- page := p.Browser().MustPageFromTargetID(e.TargetInfo.TargetID)
- lxrod.DialogWatch(nil, page)
- })()
- // has, _, _ := p.Has("dialog")
- // if has {
- // _, _ = p.Eval(`
- //window.alert = function() {};
- //window.confirm = function() { return true; };
- //window.prompt = function() {};`)
- // }
- })
- //}
- }()
- }
- // 有就点 没有就不点击
- func MustClick(page *rod.Page, xpath string) {
- x := MustElementsX(page, xpath)
- for _, element := range x {
- visible, _ := element.Visible()
- if visible {
- element.MustClick()
- break
- }
- }
- }
- func MustText(page *rod.Page, xpath string) string {
- //去掉左右空格
- return strings.TrimSpace(MustElementX(page, xpath).MustText())
- }
- // 输入文字
- func Input(p *rod.Page, selector, inputVal string) {
- err := rod.Try(func() {
- if inputVal == "" || inputVal == "*" {
- inputVal = "0"
- }
- e := rod.Try(func() {
- p.Timeout(time.Second).MustSearch(selector).MustSelectAllText().MustFrame().Keyboard.MustType(input.Backspace)
- })
- if e != nil {
- if w := errors.Unwrap(e); w != nil {
- logger.Info(w.Error() + "-" + selector + "-" + inputVal)
- } else {
- logger.Info(e.Error() + "-" + selector + "-" + inputVal)
- }
- }
- e = rod.Try(func() {
- p.Timeout(time.Second).MustSearch(selector).MustSelectAllText().MustInput(inputVal)
- })
- if e != nil {
- if w := errors.Unwrap(e); w != nil {
- logger.Info(strings.Split(w.Error(), "\t")[0] + "-" + selector + "-" + inputVal)
- } else {
- logger.Info(strings.Split(e.Error(), "\t")[0] + "-" + selector + "-" + inputVal)
- }
- }
- })
- if err != nil {
- logger.Info(err.Error() + "-" + selector + "-" + inputVal)
- }
- }
- // 输入文字
- func MustInputX(p *rod.Page, xPath, inputVal string) {
- e := MustElementX(p, xPath)
- _ = e.ScrollIntoView()
- e.MustClick().MustSelectAllText().MustInput(inputVal)
- }
- // 拦截请求
- func PageHijackReq(b *rod.Page, pattern string, ch chan []byte) *rod.HijackRouter {
- router := b.HijackRequests()
- router.MustAdd(pattern, func(ctx *rod.Hijack) {
- rod.Try(func() {
- ctx.MustLoadResponse()
- ch <- []byte(ctx.Response.Body())
- utils.Sleep(5)
- select {
- case <-ch:
- break
- }
- })
- })
- go router.Run()
- return router
- }
- // 获取拦截请求的值
- func GetHijackResp(ch chan []byte, t float64) ([]byte, error) {
- d := time.Duration(t * float64(time.Second))
- select {
- case val := <-ch:
- return val, nil
- case <-time.After(d):
- return nil, errors.New("请求网页超时,请稍后重试!")
- }
- }
- // WaitForPageLoad 等待页面完全加载,selector 为等待某个元素加载的选择器,可选
- func WaitForPageLoad(page *rod.Page, timeoutDuration time.Duration, selector ...string) {
- start := time.Now()
- // 1. 等待页面 readyState 为 "complete",加上超时控制
- for {
- readyState := page.MustEval(`() => document.readyState`).String()
- if readyState == "complete" {
- break // 页面加载完成,退出循环
- }
- // 检查是否超时
- if time.Since(start) > timeoutDuration {
- break
- }
- time.Sleep(500 * time.Millisecond) // 每次检查之间等待一段时间
- }
- // 2. 等待页面元素稳定
- page.MustWaitStable()
- // 3. 如果传入了 selector,等待特定元素加载完成
- if len(selector) > 0 {
- rod.Try(func() {
- page.Timeout(timeoutDuration).MustElement(selector[0]) // 使用传入的选择器等待元素
- })
- }
- // 4. 等待所有网络请求结束
- rod.Try(func() {
- page.Timeout(timeoutDuration).MustWaitIdle()
- })
- utils.Sleep(3)
- }
- func WaitHasX(page *rod.Page, xpath string) (x bool) {
- for i := 0; i < 5; i++ {
- x, _, _ = HasX(page, xpath)
- if !x {
- utils.Sleep(1)
- }
- }
- return x
- }
- func SaveErrImg(p *rod.Page, info models.CompanyInfo) string {
- var check_path string
- check_path = "./data/sbImg/" + info.TaxNo + "/"
- if !PathExists(check_path) {
- os.MkdirAll(check_path, os.ModePerm)
- }
- check_path = check_path + info.Period + "-" + time.Now().Format("2006-01-02-15-04-05") + ".png"
- check_path2 := ""
- _ = rod.Try(func() {
- p.Timeout(ClickTimeOut).MustScreenshot(check_path)
- watermark.Add(check_path)
- check_path2 = PostSbjt(info.TaxNo, info.Period, check_path)
- os.Remove(check_path)
- })
- return check_path2
- }
- // InputWithTimeout 规定时间内填入输入值,默认5s
- func InputWithTimeout(p *rod.Page, selector, inputVal string, timeout ...int64) {
- var t int64
- if len(timeout) == 0 {
- t = 5
- } else {
- t = timeout[0]
- }
- p.Timeout(time.Duration(t) * time.Second).MustSearch(selector).MustSelectAllText().MustInput(inputVal)
- }
- func SaveErrImgTask(p *rod.Page, info *models.TaxTask) string {
- var check_path string
- check_path = "./data/sbImg/" + info.TaxNo + "/"
- if !PathExists(check_path) {
- os.MkdirAll(check_path, os.ModePerm)
- }
- check_path = check_path + info.Period + "-" + time.Now().Format("2006-01-02-15-04-05") + ".png"
- var check_path2 string
- _ = rod.Try(func() {
- p.Timeout(ClickTimeOut).MustScreenshot(check_path)
- watermark.Add(check_path)
- check_path2 = PostSbjt(info.TaxNo, info.Period, check_path)
- os.Remove(check_path)
- })
- return check_path2
- }
- // 使用键盘模拟输入
- func InputStrNew(page *rod.Page, el *rod.Element, str string) {
- el.MustScrollIntoView()
- box := el.MustShape().Box()
- Click(page, box.X+(box.Width/2), box.Y+(box.Height/2))
- time.Sleep(time.Millisecond * 100)
- selectAll2(page)
- time.Sleep(time.Millisecond * 100)
- _ = page.Keyboard.Type(input.Delete)
- _ = page.Keyboard.Type(input.Backspace)
- time.Sleep(time.Millisecond * 100)
- _ = page.Keyboard.Type(input.Backspace)
- for _, v := range str {
- _ = page.Keyboard.Type(input.Key(v))
- time.Sleep(time.Millisecond * 100)
- }
- }
- func Click(page *rod.Page, x, y float64) {
- page.Mouse.MustMoveTo(x, y)
- time.Sleep(time.Millisecond * 100)
- page.Mouse.MustDown("left")
- page.Mouse.MustUp("left")
- }
- func selectAll2(page *rod.Page) {
- page.Keyboard.MustType(input.ControlLeft).MustType('a').MustType('a').MustType(input.ControlLeft)
- }
- // 输入文字Str
- func InputStr(p *rod.Page, selector, inputVal string) {
- err := rod.Try(func() {
- e := rod.Try(func() {
- p.Timeout(time.Duration(1 * float64(time.Second))).MustSearch(selector).MustSelectAllText().MustFrame().Keyboard.MustType(input.Backspace)
- })
- if e != nil {
- logger.Info(e.Error() + "-" + selector + "-" + inputVal)
- }
- e = rod.Try(func() {
- p.Timeout(time.Duration(1 * float64(time.Second))).MustSearch(selector).MustSelectAllText().MustInput(inputVal)
- })
- if e != nil {
- logger.Info(strings.Split(e.Error(), "\t")[0] + "-" + selector + "-" + inputVal)
- }
- })
- if err != nil {
- logger.Info(err.Error() + "-" + selector + "-" + inputVal)
- }
- }
- // 输入文字 string
- func InputElementXStr(p *rod.Page, xPath, inputVal string) {
- elementX := MustElementX(p, xPath)
- disabled := elementX.MustAttribute("disabled")
- if disabled != nil {
- return
- }
- readonly := elementX.MustAttribute("readonly")
- if readonly != nil {
- return
- }
- elementX.MustSelectAllText().MustInput(inputVal)
- }
- func WaitElementXFoTimesNil(page *rod.Page, xpath string, times int) *rod.Element {
- for i := 0; i < times; i++ {
- if has, el, _ := HasX(page, xpath); has && MustElementX(page, xpath).MustVisible() {
- return el
- }
- time.Sleep(time.Second)
- }
- return nil
- }
- func MustElementX10(page *rod.Page, xpath string) *rod.Element {
- for i := 0; i < 10; i++ {
- x, _ := ElementX(page, xpath)
- if x != nil {
- return x
- }
- utils.Sleep(1)
- }
- return nil
- }
- func MustElementX15(page *rod.Page, xpath string) *rod.Element {
- for i := 0; i < 15; i++ {
- x, _ := ElementX(page, xpath)
- if x != nil {
- return x
- }
- utils.Sleep(1)
- }
- return nil
- }
- func MustHasXV30(page *rod.Page, xpath string) bool {
- for _, element := range MustElementsX30(page, xpath) {
- visible, _ := element.Visible()
- if visible {
- return true
- }
- }
- return false
- }
- func MustElementsX30(page *rod.Page, xpath string) (x []*rod.Element) {
- for i := 0; i < 30; i++ {
- x, _ = ElementsX(page, xpath)
- if len(x) != 0 {
- break
- }
- utils.Sleep(1)
- }
- return x
- }
- func WaitElementXFoTimes(page *rod.Page, xpath string, times int) *rod.Element {
- for i := 0; i < times; i++ {
- if has, el, _ := HasX(page, xpath); has && MustElementX(page, xpath).MustVisible() {
- return el
- }
- time.Sleep(time.Second)
- }
- logger.Info("页面加载失败元素未找到,请稍后再试", xpath)
- panic(taxerr.NewWebStuckTitle(InfoCscsts))
- }
- func MustElementsX10(page *rod.Page, xpath string) (x []*rod.Element) {
- for i := 0; i < 10; i++ {
- x, _ = ElementsX(page, xpath)
- if len(x) != 0 {
- break
- }
- utils.Sleep(1)
- }
- return x
- }
- func WaitMustElementsX(page *rod.Page, xpath string) (elementsX []*rod.Element) {
- for i := 0; i < 5; i++ {
- elementsX = MustElementsX(page, xpath)
- if len(elementsX) != 0 {
- return
- }
- utils.Sleep(1)
- }
- return
- }
- func ClickB(page *rod.Page, el string) {
- box := MustElementX(page, el).MustShape().Box()
- Click(page, box.X+(box.Width/2), box.Y+(box.Height/2))
- }
- func WaitElementX10(page *rod.Page, xpath string) *rod.Element {
- return WaitElementXFoTimes(page, xpath, 10)
- }
- func MustElementX30(page *rod.Page, xpath string) *rod.Element {
- for i := 0; i < 30; i++ {
- x, _ := ElementX(page, xpath)
- if x != nil {
- return x
- }
- utils.Sleep(1)
- }
- return nil
- }
- func WaitHasX10(page *rod.Page, xpath string) (x bool) {
- for i := 0; i < 10; i++ {
- x, _, _ = HasX(page, xpath)
- if !x {
- utils.Sleep(1)
- }
- }
- return x
- }
- // 返回当前元素下一个元素的text 如果没有元素就直接返回空
- func MustNextText(page *rod.Page, xpath string) string {
- x := MustElementXV(page, xpath)
- if x == nil {
- return ""
- }
- return x.MustNext().MustText()
- }
- // 2033年12月31日 // 2033-12-31
- func DataFormat(data string) string {
- strings.ReplaceAll(data, "年", "-")
- strings.ReplaceAll(data, "月", "-")
- strings.ReplaceAll(data, "日", "")
- if len(data) > 10 {
- data = data[:10]
- }
- return data
- }
- // 返回当前元素下一个元素的text 如果没有元素就直接返回空
- func MustNext2Text(page *rod.Page, xpath string) string {
- x := MustElementXV(page, xpath)
- if x == nil {
- return ""
- }
- return x.MustNext().MustNext().MustText()
- }
- // 拦截
- func HijackReq(page *rod.Page, uri, xPath string) []byte {
- ch := make(chan []byte)
- r := PageHijackReq(page, uri, ch)
- MustElementX(page, xPath).MustClick()
- data, err := GetHijackResp(ch, 10)
- if err != nil {
- zaplog.LoggerS.Info(string(data))
- panic(taxerr.NewWebStuckTitle(false))
- }
- _ = r.Stop()
- return data
- }
|