refactor: simplify OCR APIs

This commit is contained in:
lilong.129
2023-04-25 22:27:31 +08:00
parent f9bebf7202
commit 3ec27b9afc
13 changed files with 231 additions and 247 deletions
+5 -3
View File
@@ -150,7 +150,7 @@ func NewWorldCupLive(device uixt.Device, matchName, bundleID string, duration, i
func (wc *WorldCupLive) getCurrentLiveTime(utcTime time.Time) error { func (wc *WorldCupLive) getCurrentLiveTime(utcTime time.Time) error {
utcTimeStr := utcTime.Format("15:04:05") utcTimeStr := utcTime.Format("15:04:05")
ocrTexts, err := wc.driver.GetTextsByOCR() ocrTexts, err := wc.driver.GetScreenTextsByOCR()
if err != nil { if err != nil {
log.Error().Err(err).Msg("get ocr texts failed") log.Error().Err(err).Msg("get ocr texts failed")
return err return err
@@ -212,8 +212,10 @@ func (wc *WorldCupLive) EnterLive(bundleID string) error {
time.Sleep(5 * time.Second) time.Sleep(5 * time.Second)
// 青少年弹窗处理 // 青少年弹窗处理
if points, err := wc.driver.GetTextXYs([]string{"青少年模式", "我知道了"}); err == nil { if ocrTexts, err := wc.driver.GetScreenTextsByOCR(); err == nil {
_ = wc.driver.TapAbsXY(points[1].X, points[1].Y) if points, err := ocrTexts.FindTexts([]string{"青少年模式", "我知道了"}); err == nil {
_ = wc.driver.TapAbsXY(points[1].X, points[1].Y)
}
} }
// 进入世界杯 tab // 进入世界杯 tab
+12 -3
View File
@@ -222,7 +222,7 @@ func (dExt *DriverExt) DoAction(action MobileAction) error {
// } // }
findTextCondition := func(d *DriverExt) error { findTextCondition := func(d *DriverExt) error {
var err error var err error
point, err = d.GetTextXY(text, indexOption, scopeOption) point, err = d.FindScreenTextByOCR(text, indexOption, scopeOption)
return err return err
} }
foundTextAction := func(d *DriverExt) error { foundTextAction := func(d *DriverExt) error {
@@ -268,7 +268,11 @@ func (dExt *DriverExt) DoAction(action MobileAction) error {
var point PointF var point PointF
findTexts := func(d *DriverExt) error { findTexts := func(d *DriverExt) error {
var err error var err error
points, err := d.GetTextXYs(texts, scopeOption) ocrTexts, err := d.GetScreenTextsByOCR(scopeOption)
if err != nil {
return err
}
points, err := ocrTexts.FindTexts(texts, scopeOption)
if err != nil { if err != nil {
return err return err
} }
@@ -455,7 +459,12 @@ func (dExt *DriverExt) DoAction(action MobileAction) error {
if !ok { if !ok {
return fmt.Errorf("invalid video crawler params: %v(%T)", action.Params, action.Params) return fmt.Errorf("invalid video crawler params: %v(%T)", action.Params, action.Params)
} }
return dExt.VideoCrawler(params) data, _ := json.Marshal(params)
configs := &VideoCrawlerConfigs{}
if err := json.Unmarshal(data, configs); err != nil {
return errors.Wrapf(err, "invalid video crawler params: %v(%T)", action.Params, action.Params)
}
return dExt.VideoCrawler(configs)
} }
return nil return nil
} }
+4 -6
View File
@@ -17,14 +17,12 @@ func (dExt *DriverExt) DragOffsetFloat(pathname string, toX, toY, xOffset, yOffs
pressForDuration = []float64{1.0} pressForDuration = []float64{1.0}
} }
var x, y, width, height float64 point, err := dExt.FindUIRectInUIKit(pathname)
if x, y, width, height, err = dExt.FindUIRectInUIKit(pathname); err != nil { if err != nil {
return err return err
} }
fromX := x + width*xOffset // FIXME: handle offset
fromY := y + height*yOffset return dExt.Driver.DragFloat(point.X+xOffset, point.Y+yOffset, toX, toY,
return dExt.Driver.DragFloat(fromX, fromY, toX, toY,
WithDataPressDuration(pressForDuration[0])) WithDataPressDuration(pressForDuration[0]))
} }
+7 -7
View File
@@ -52,8 +52,8 @@ type DriverExt struct {
frame *bytes.Buffer frame *bytes.Buffer
doneMjpegStream chan bool doneMjpegStream chan bool
scale float64 scale float64
ocrService OCRService // used to get text from image OCRService IOCRService // used to get text from image
screenShots []string // cache screenshot paths screenShots []string // cache screenshot paths
CVArgs CVArgs
} }
@@ -75,7 +75,7 @@ func NewDriverExt(device Device, driver WebDriver) (dExt *DriverExt, err error)
return nil, err return nil, err
} }
if dExt.ocrService, err = newVEDEMOCRService(); err != nil { if dExt.OCRService, err = newVEDEMOCRService(); err != nil {
return nil, err return nil, err
} }
@@ -178,10 +178,10 @@ func init() {
rand.Seed(time.Now().UnixNano()) rand.Seed(time.Now().UnixNano())
} }
func (dExt *DriverExt) FindUIRectInUIKit(search string, options ...DataOption) (x, y, width, height float64, err error) { func (dExt *DriverExt) FindUIRectInUIKit(search string, options ...DataOption) (point PointF, err error) {
// click on text, using OCR // click on text, using OCR
if !isPathExists(search) { if !isPathExists(search) {
return dExt.FindTextByOCR(search, options...) return dExt.FindScreenTextByOCR(search, options...)
} }
// click on image, using opencv // click on image, using opencv
return dExt.FindImageRectInUIKit(search, options...) return dExt.FindImageRectInUIKit(search, options...)
@@ -194,12 +194,12 @@ func (dExt *DriverExt) MappingToRectInUIKit(rect image.Rectangle) (x, y, width,
} }
func (dExt *DriverExt) IsOCRExist(text string) bool { func (dExt *DriverExt) IsOCRExist(text string) bool {
_, _, _, _, err := dExt.FindTextByOCR(text) _, err := dExt.FindScreenTextByOCR(text)
return err == nil return err == nil
} }
func (dExt *DriverExt) IsImageExist(text string) bool { func (dExt *DriverExt) IsImageExist(text string) bool {
_, _, _, _, err := dExt.FindImageRectInUIKit(text) _, err := dExt.FindImageRectInUIKit(text)
return err == nil return err == nil
} }
+3 -3
View File
@@ -10,9 +10,9 @@ func TestDriverExtOCR(t *testing.T) {
driverExt, err := iosDevice.NewDriver(nil) driverExt, err := iosDevice.NewDriver(nil)
checkErr(t, err) checkErr(t, err)
x, y, width, height, err := driverExt.FindTextByOCR("抖音") point, err := driverExt.FindScreenTextByOCR("抖音")
checkErr(t, err) checkErr(t, err)
t.Logf("x: %v, y: %v, width: %v, height: %v", x, y, width, height) t.Logf("point.X: %v, point.Y: %v", point.X, point.Y)
driverExt.Driver.TapFloat(x+width*0.5, y+height*0.5-20) driverExt.Driver.TapFloat(point.X, point.Y-20)
} }
+115 -157
View File
@@ -34,7 +34,85 @@ type ResponseOCR struct {
OCRResult []OCRResult `json:"ocrResult"` OCRResult []OCRResult `json:"ocrResult"`
} }
type veDEMOCRService struct{} type OCRText struct {
Text string
Rect image.Rectangle
}
type OCRTexts []OCRText
func (t OCRTexts) texts() (texts []string) {
for _, text := range t {
texts = append(texts, text.Text)
}
return texts
}
func (t OCRTexts) FindText(text string, options ...DataOption) (
point PointF, err error) {
dataOptions := NewDataOptions(options...)
var rects []image.Rectangle
for _, ocrText := range t {
rect := ocrText.Rect
// not contains text
if !strings.Contains(ocrText.Text, text) {
continue
}
rects = append(rects, rect)
// contains text while not match exactly
if ocrText.Text != text {
continue
}
// match exactly, and not specify index, return the first one
if dataOptions.Index == 0 {
return getRectangleCenterPoint(rect), nil
}
}
if len(rects) == 0 {
return PointF{}, errors.Wrap(code.OCRTextNotFoundError,
fmt.Sprintf("text %s not found in %v", text, t.texts()))
}
// get index
idx := dataOptions.Index
if idx > 0 {
// NOTICE: index start from 1
idx = idx - 1
} else if idx < 0 {
idx = len(rects) + idx
}
// index out of range
if idx >= len(rects) {
return PointF{}, errors.Wrap(code.OCRTextNotFoundError,
fmt.Sprintf("text %s found %d, index %d out of range", text, len(rects), idx))
}
return getRectangleCenterPoint(rects[idx]), nil
}
func (t OCRTexts) FindTexts(texts []string, options ...DataOption) (points []PointF, err error) {
for _, text := range texts {
point, err := t.FindText(text, options...)
if err != nil {
continue
}
points = append(points, point)
}
if len(points) != len(texts) {
return nil, errors.Wrap(code.OCRTextNotFoundError,
fmt.Sprintf("texts %s not found in %v", texts, t.texts()))
}
return points, nil
}
func newVEDEMOCRService() (*veDEMOCRService, error) { func newVEDEMOCRService() (*veDEMOCRService, error) {
if err := checkEnv(); err != nil { if err := checkEnv(); err != nil {
@@ -43,18 +121,7 @@ func newVEDEMOCRService() (*veDEMOCRService, error) {
return &veDEMOCRService{}, nil return &veDEMOCRService{}, nil
} }
func checkEnv() error { type veDEMOCRService struct{}
if env.VEDEM_OCR_URL == "" {
return errors.Wrap(code.OCREnvMissedError, "VEDEM_OCR_URL missed")
}
if env.VEDEM_OCR_AK == "" {
return errors.Wrap(code.OCREnvMissedError, "VEDEM_OCR_AK missed")
}
if env.VEDEM_OCR_SK == "" {
return errors.Wrap(code.OCREnvMissedError, "VEDEM_OCR_SK missed")
}
return nil
}
func (s *veDEMOCRService) getOCRResult(imageBuf *bytes.Buffer) ([]OCRResult, error) { func (s *veDEMOCRService) getOCRResult(imageBuf *bytes.Buffer) ([]OCRResult, error) {
bodyBuf := &bytes.Buffer{} bodyBuf := &bytes.Buffer{}
@@ -138,32 +205,6 @@ func (s *veDEMOCRService) getOCRResult(imageBuf *bytes.Buffer) ([]OCRResult, err
return ocrResult.OCRResult, nil return ocrResult.OCRResult, nil
} }
func getLogID(header http.Header) string {
if len(header) == 0 {
return ""
}
logID, ok := header["X-Tt-Logid"]
if !ok || len(logID) == 0 {
return ""
}
return logID[0]
}
type OCRText struct {
Text string
Rect image.Rectangle
}
type OCRTexts []OCRText
func (t OCRTexts) Texts() (texts []string) {
for _, text := range t {
texts = append(texts, text.Text)
}
return texts
}
func (s *veDEMOCRService) GetTexts(imageBuf *bytes.Buffer, options ...DataOption) ( func (s *veDEMOCRService) GetTexts(imageBuf *bytes.Buffer, options ...DataOption) (
ocrTexts OCRTexts, err error) { ocrTexts OCRTexts, err error) {
@@ -203,157 +244,74 @@ func (s *veDEMOCRService) GetTexts(imageBuf *bytes.Buffer, options ...DataOption
return return
} }
func (s *veDEMOCRService) FindText(text string, imageBuf *bytes.Buffer, options ...DataOption) ( func checkEnv() error {
rect image.Rectangle, err error) { if env.VEDEM_OCR_URL == "" {
return errors.Wrap(code.OCREnvMissedError, "VEDEM_OCR_URL missed")
ocrTexts, err := s.GetTexts(imageBuf, options...)
if err != nil {
log.Error().Err(err).Msg("GetTexts failed")
return
} }
if env.VEDEM_OCR_AK == "" {
dataOptions := NewDataOptions(options...) return errors.Wrap(code.OCREnvMissedError, "VEDEM_OCR_AK missed")
var rects []image.Rectangle
for _, ocrText := range ocrTexts {
rect = ocrText.Rect
// not contains text
if !strings.Contains(ocrText.Text, text) {
continue
}
rects = append(rects, rect)
// contains text while not match exactly
if ocrText.Text != text {
continue
}
// match exactly, and not specify index, return the first one
if dataOptions.Index == 0 {
return rect, nil
}
} }
if env.VEDEM_OCR_SK == "" {
if len(rects) == 0 { return errors.Wrap(code.OCREnvMissedError, "VEDEM_OCR_SK missed")
return image.Rectangle{}, errors.Wrap(code.OCRTextNotFoundError,
fmt.Sprintf("text %s not found in %v", text, ocrTexts.Texts()))
} }
return nil
// get index
idx := dataOptions.Index
if idx > 0 {
// NOTICE: index start from 1
idx = idx - 1
} else if idx < 0 {
idx = len(rects) + idx
}
// index out of range
if idx >= len(rects) {
return image.Rectangle{}, errors.Wrap(code.OCRTextNotFoundError,
fmt.Sprintf("text %s found %d, index %d out of range", text, len(rects), idx))
}
return rects[idx], nil
} }
func (s *veDEMOCRService) FindTexts(texts []string, imageBuf *bytes.Buffer, options ...DataOption) ( func getLogID(header http.Header) string {
rects []image.Rectangle, err error) { if len(header) == 0 {
return ""
ocrTexts, err := s.GetTexts(imageBuf, options...)
if err != nil {
log.Error().Err(err).Msg("GetTexts failed")
return
} }
var success bool logID, ok := header["X-Tt-Logid"]
for _, text := range texts { if !ok || len(logID) == 0 {
var found bool return ""
for _, ocrText := range ocrTexts {
rect := ocrText.Rect
// not contains text
if !strings.Contains(ocrText.Text, text) {
continue
}
found = true
rects = append(rects, rect)
break
}
if !found {
rects = append(rects, image.Rectangle{})
}
success = found || success
} }
return logID[0]
if !success {
return rects, errors.Wrap(code.OCRTextNotFoundError,
fmt.Sprintf("texts %s not found in %v", texts, ocrTexts.Texts()))
}
return rects, nil
} }
type OCRService interface { type IOCRService interface {
GetTexts(imageBuf *bytes.Buffer, options ...DataOption) (ocrTexts OCRTexts, err error) GetTexts(imageBuf *bytes.Buffer, options ...DataOption) (ocrTexts OCRTexts, err error)
FindText(text string, imageBuf *bytes.Buffer, options ...DataOption) (rect image.Rectangle, err error)
FindTexts(texts []string, imageBuf *bytes.Buffer, options ...DataOption) (rects []image.Rectangle, err error)
} }
func (dExt *DriverExt) GetTextsByOCR(options ...DataOption) (texts OCRTexts, err error) { func (dExt *DriverExt) GetScreenTextsByOCR(options ...DataOption) (texts OCRTexts, err error) {
var bufSource *bytes.Buffer var bufSource *bytes.Buffer
if bufSource, err = dExt.TakeScreenShot(builtin.GenNameWithTimestamp("step_%d_ocr")); err != nil { if bufSource, err = dExt.TakeScreenShot(
builtin.GenNameWithTimestamp("screenshot_%d_ocr")); err != nil {
return return
} }
ocrTexts, err := dExt.ocrService.GetTexts(bufSource, options...) ocrTexts, err := dExt.OCRService.GetTexts(bufSource, options...)
if err != nil { if err != nil {
log.Error().Err(err).Msg("GetTexts failed") log.Error().Err(err).Msg("GetScreenTextsByOCR failed")
return return
} }
log.Debug().Interface("texts", ocrTexts).Msg("get screen texts by OCR")
return ocrTexts, nil return ocrTexts, nil
} }
func (dExt *DriverExt) FindTextByOCR(ocrText string, options ...DataOption) (x, y, width, height float64, err error) { func (dExt *DriverExt) FindScreenTextByOCR(text string, options ...DataOption) (point PointF, err error) {
var bufSource *bytes.Buffer ocrTexts, err := dExt.GetScreenTextsByOCR(options...)
if bufSource, err = dExt.TakeScreenShot(builtin.GenNameWithTimestamp("step_%d_ocr")); err != nil { if err != nil {
return return
} }
point, err = ocrTexts.FindText(text, options...)
rect, err := dExt.ocrService.FindText(ocrText, bufSource, options...)
if err != nil { if err != nil {
log.Warn().Msgf("FindText failed: %s", err.Error()) log.Warn().Msgf("FindText failed: %s", err.Error())
return return
} }
log.Info().Str("ocrText", ocrText). log.Info().Str("text", text).
Interface("rect", rect).Msgf("FindTextByOCR success") Interface("point", point).Msgf("FindScreenTextByOCR success")
x, y, width, height = dExt.MappingToRectInUIKit(rect)
return return
} }
func (dExt *DriverExt) FindTextsByOCR(ocrTexts []string, options ...DataOption) (points [][]float64, err error) { func getRectangleCenterPoint(rect image.Rectangle) (point PointF) {
var bufSource *bytes.Buffer x, y := float64(rect.Min.X), float64(rect.Min.Y)
if bufSource, err = dExt.TakeScreenShot(builtin.GenNameWithTimestamp("step_%d_ocr")); err != nil { width, height := float64(rect.Dx()), float64(rect.Dy())
return point = PointF{
X: x + width*0.5,
Y: y + height*0.5,
} }
return point
rects, err := dExt.ocrService.FindTexts(ocrTexts, bufSource, options...)
if err != nil {
log.Warn().Msgf("FindTexts failed: %s", err.Error())
return
}
log.Info().Interface("ocrTexts", ocrTexts).
Interface("rects", rects).Msgf("FindTextsByOCR success")
for _, rect := range rects {
x, y, width, height := dExt.MappingToRectInUIKit(rect)
points = append(points, []float64{x, y, width, height})
}
return
} }
+5 -11
View File
@@ -113,25 +113,19 @@ func (dExt *DriverExt) FindAllImageRect(search string) (rects []image.Rectangle,
return return
} }
func (dExt *DriverExt) FindImageRectInUIKit(imagePath string, options ...DataOption) (x, y, width, height float64, err error) { func (dExt *DriverExt) FindImageRectInUIKit(imagePath string, options ...DataOption) (point PointF, err error) {
var bufSource, bufSearch *bytes.Buffer var bufSource, bufSearch *bytes.Buffer
if bufSearch, err = getBufFromDisk(imagePath); err != nil { if bufSearch, err = getBufFromDisk(imagePath); err != nil {
return 0, 0, 0, 0, err return PointF{}, err
}
if bufSource, err = dExt.TakeScreenShot(builtin.GenNameWithTimestamp("step_%d_cv")); err != nil {
return 0, 0, 0, 0, err
} }
var rect image.Rectangle var rect image.Rectangle
if rect, err = FindImageRectFromRaw(bufSource, bufSearch, float32(dExt.threshold), TemplateMatchMode(dExt.matchMode)); err != nil { if rect, err = FindImageRectFromRaw(bufSource, bufSearch, float32(dExt.threshold), TemplateMatchMode(dExt.matchMode)); err != nil {
return 0, 0, 0, 0, err return PointF{}, err
} }
// if rect, err = dExt.findImgRect(search); err != nil { point = getRectangleCenterPoint(rect)
// return 0, 0, 0, 0, err return point, nil
// }
x, y, width, height = dExt.MappingToRectInUIKit(rect)
return
} }
func getBufFromDisk(name string) (*bytes.Buffer, error) { func getBufFromDisk(name string) (*bytes.Buffer, error) {
+1 -1
View File
@@ -17,7 +17,7 @@ func (dExt *DriverExt) FindAllImageRect(search string) (rects []image.Rectangle,
return return
} }
func (dExt *DriverExt) FindImageRectInUIKit(imagePath string, options ...DataOption) (x, y, width, height float64, err error) { func (dExt *DriverExt) FindImageRectInUIKit(imagePath string, options ...DataOption) (point PointF, err error) {
log.Fatal().Msg("opencv is not supported") log.Fatal().Msg("opencv is not supported")
return return
} }
+1 -1
View File
@@ -151,7 +151,7 @@ func (dExt *DriverExt) swipeToTapApp(appName string, action MobileAction) error
} }
findAppCondition := func(d *DriverExt) error { findAppCondition := func(d *DriverExt) error {
var err error var err error
point, err = d.GetTextXY(appName, scopeOption, indexOption) point, err = d.FindScreenTextByOCR(appName, scopeOption, indexOption)
return err return err
} }
foundAppAction := func(d *DriverExt) error { foundAppAction := func(d *DriverExt) error {
+2 -2
View File
@@ -13,7 +13,7 @@ func TestSwipeUntil(t *testing.T) {
var point PointF var point PointF
findApp := func(d *DriverExt) error { findApp := func(d *DriverExt) error {
var err error var err error
point, err = d.GetTextXY("抖音") point, err = d.FindScreenTextByOCR("抖音")
return err return err
} }
foundAppAction := func(d *DriverExt) error { foundAppAction := func(d *DriverExt) error {
@@ -34,7 +34,7 @@ func TestSwipeUntil(t *testing.T) {
findLive := func(d *DriverExt) error { findLive := func(d *DriverExt) error {
var err error var err error
point, err = d.GetTextXY("点击进入直播间") point, err = d.FindScreenTextByOCR("点击进入直播间")
return err return err
} }
foundLiveAction := func(d *DriverExt) error { foundLiveAction := func(d *DriverExt) error {
+9 -50
View File
@@ -21,53 +21,10 @@ func (dExt *DriverExt) TapXY(x, y float64, options ...DataOption) error {
return dExt.TapAbsXY(x, y, options...) return dExt.TapAbsXY(x, y, options...)
} }
func (dExt *DriverExt) GetTextXY(ocrText string, options ...DataOption) (point PointF, err error) {
x, y, width, height, err := dExt.FindTextByOCR(ocrText, options...)
if err != nil {
return PointF{}, err
}
point = PointF{
X: x + width*0.5,
Y: y + height*0.5,
}
return point, nil
}
func (dExt *DriverExt) GetTextXYs(ocrText []string, options ...DataOption) (points []PointF, err error) {
ps, err := dExt.FindTextsByOCR(ocrText, options...)
if err != nil {
return nil, err
}
for _, point := range ps {
pointF := PointF{
X: point[0] + point[2]*0.5,
Y: point[1] + point[3]*0.5,
}
points = append(points, pointF)
}
return points, nil
}
func (dExt *DriverExt) GetImageXY(imagePath string, options ...DataOption) (point PointF, err error) {
x, y, width, height, err := dExt.FindImageRectInUIKit(imagePath, options...)
if err != nil {
return PointF{}, err
}
point = PointF{
X: x + width*0.5,
Y: y + height*0.5,
}
return point, nil
}
func (dExt *DriverExt) TapByOCR(ocrText string, options ...DataOption) error { func (dExt *DriverExt) TapByOCR(ocrText string, options ...DataOption) error {
dataOptions := NewDataOptions(options...) dataOptions := NewDataOptions(options...)
point, err := dExt.GetTextXY(ocrText, options...) point, err := dExt.FindScreenTextByOCR(ocrText, options...)
if err != nil { if err != nil {
if dataOptions.IgnoreNotFoundError { if dataOptions.IgnoreNotFoundError {
return nil return nil
@@ -81,7 +38,7 @@ func (dExt *DriverExt) TapByOCR(ocrText string, options ...DataOption) error {
func (dExt *DriverExt) TapByCV(imagePath string, options ...DataOption) error { func (dExt *DriverExt) TapByCV(imagePath string, options ...DataOption) error {
dataOptions := NewDataOptions(options...) dataOptions := NewDataOptions(options...)
point, err := dExt.GetImageXY(imagePath, options...) point, err := dExt.FindImageRectInUIKit(imagePath, options...)
if err != nil { if err != nil {
if dataOptions.IgnoreNotFoundError { if dataOptions.IgnoreNotFoundError {
return nil return nil
@@ -99,7 +56,7 @@ func (dExt *DriverExt) Tap(param string, options ...DataOption) error {
func (dExt *DriverExt) TapOffset(param string, xOffset, yOffset float64, options ...DataOption) (err error) { func (dExt *DriverExt) TapOffset(param string, xOffset, yOffset float64, options ...DataOption) (err error) {
dataOptions := NewDataOptions(options...) dataOptions := NewDataOptions(options...)
x, y, width, height, err := dExt.FindUIRectInUIKit(param, options...) point, err := dExt.FindUIRectInUIKit(param, options...)
if err != nil { if err != nil {
if dataOptions.IgnoreNotFoundError { if dataOptions.IgnoreNotFoundError {
return nil return nil
@@ -107,7 +64,8 @@ func (dExt *DriverExt) TapOffset(param string, xOffset, yOffset float64, options
return err return err
} }
return dExt.TapAbsXY(x+width*xOffset, y+height*yOffset, options...) // FIXME: handle offset
return dExt.TapAbsXY(point.X+xOffset, point.Y+yOffset, options...)
} }
func (dExt *DriverExt) DoubleTapXY(x, y float64) error { func (dExt *DriverExt) DoubleTapXY(x, y float64) error {
@@ -126,10 +84,11 @@ func (dExt *DriverExt) DoubleTap(param string) (err error) {
} }
func (dExt *DriverExt) DoubleTapOffset(param string, xOffset, yOffset float64) (err error) { func (dExt *DriverExt) DoubleTapOffset(param string, xOffset, yOffset float64) (err error) {
var x, y, width, height float64 point, err := dExt.FindUIRectInUIKit(param)
if x, y, width, height, err = dExt.FindUIRectInUIKit(param); err != nil { if err != nil {
return err return err
} }
return dExt.Driver.DoubleTapFloat(x+width*xOffset, y+height*yOffset) // FIXME: handle offset
return dExt.Driver.DoubleTapFloat(point.X+xOffset, point.Y+yOffset)
} }
+44 -3
View File
@@ -1,9 +1,50 @@
package uixt package uixt
import (
"time"
"github.com/rs/zerolog/log"
)
type VideoCrawlerConfigs struct { type VideoCrawlerConfigs struct {
Target struct{} AppPackageName string `json:"app_package_name"`
TargetFeedCount int `json:"target_feed_count"`
TargetLiveCount int `json:"target_live_count"`
} }
func (dExt *DriverExt) VideoCrawler(params map[string]interface{}) error { func (dExt *DriverExt) VideoCrawler(configs *VideoCrawlerConfigs) (err error) {
return nil // launch app
if configs.AppPackageName != "" {
if err = dExt.Driver.AppLaunch(configs.AppPackageName); err != nil {
return err
}
time.Sleep(5 * time.Second)
}
// loop until target count achieved
for {
// take screenshot and get screen texts by OCR
_, err := dExt.GetScreenTextsByOCR()
if err != nil {
log.Error().Err(err).Msg("OCR GetTexts failed")
return err
}
// TODO: check if text popup exists
// TODO: check if live video
// assert feed video type
// swipe to next video
if err = dExt.SwipeUp(); err != nil {
log.Error().Err(err).Msg("swipe up failed")
return err
}
time.Sleep(5 * time.Second)
}
// return nil
} }
+23
View File
@@ -0,0 +1,23 @@
//go:build localtest
package uixt
import "testing"
func TestVideoCrawler(t *testing.T) {
device, err := NewAndroidDevice()
if err != nil {
t.Fatal(err)
}
driver, err := device.NewDriver(nil)
if err != nil {
t.Fatal(err)
}
configs := &VideoCrawlerConfigs{
AppPackageName: "com.ss.android.ugc.aweme",
}
err = driver.VideoCrawler(configs)
if err != nil {
t.Fatal(err)
}
}