Загрузка данных
#NoEnv
#SingleInstance Force
#Persistent
SendMode Input
SetWorkingDir %A_ScriptDir%
SetBatchLines, -1
CoordMode, Mouse, Screen
CoordMode, Pixel, Screen
; ============================================================
; ПОДКЛЮЧЕНИЕ GDI+
; ============================================================
#Include %A_ScriptDir%\Gdip_All.ahk
; ============================================================
; НАСТРОЙКИ
; ============================================================
; ---------- TESSERACT ----------
TesseractPath := "C:\Program Files\Tesseract-OCR\tesseract.exe"
; Язык OCR.
; eng = английский
; rus = русский
; Если установлен русский языковой пакет:
OCRLanguage := "rus+eng"
; ---------- ЦЕНА ----------
; Максимальная цена.
; Будут приниматься только цены НИЖЕ этого значения.
MaxPrice := 50000
; ============================================================
; КООРДИНАТЫ
; ============================================================
; ------------------------------------------------------------
; 1. Поле, куда вводится нужный текст
; ------------------------------------------------------------
InputX := 500
InputY := 300
; Текст, который необходимо вводить.
SearchText := "НУЖНЫЙ ТЕКСТ"
; ------------------------------------------------------------
; 2. Кнопка обновления списка
; ------------------------------------------------------------
RefreshX := 700
RefreshY := 300
; ------------------------------------------------------------
; 3. ОБЛАСТЬ OCR
;
; Именно эта область будет анализироваться Tesseract.
;
; X1/Y1 = левый верхний угол
; OCRWidth/OCRHeight = ширина и высота
; ------------------------------------------------------------
OCRX := 400
OCRY := 400
OCRWidth := 700
OCRHeight := 500
; ------------------------------------------------------------
; 4. КНОПКА ПОДТВЕРЖДЕНИЯ
;
; После нахождения подходящей цены:
;
; клик по найденной цене
; ↓
; ожидание
; ↓
; клик по этой кнопке
; ------------------------------------------------------------
ConfirmX := 1000
ConfirmY := 800
; ------------------------------------------------------------
; 5. ПОЛЗУНОК СПИСКА
;
; ScrollBarX/Y = положение ползунка
;
; ScrollPixels = насколько опускаем его за один шаг
; ------------------------------------------------------------
ScrollBarX := 1200
ScrollBarY := 500
ScrollPixels := 150
; Сколько раз можно опустить список
; на одной странице.
;
; Например:
; 5 шагов × 150 пикселей = 750 пикселей
;
MaxScrollSteps := 5
; ------------------------------------------------------------
; 6. КНОПКА ПЕРЕХОДА НА 2-Ю СТРАНИЦУ
; ------------------------------------------------------------
Page2X := 1100
Page2Y := 850
; ============================================================
; ЗАДЕРЖКИ
; ============================================================
; Небольшая задержка после движения мыши
MoveDelay := 100
; После клика
ClickDelay := 300
; После обновления списка
RefreshDelay := 700
; После ввода текста
InputDelay := 300
; После прокрутки
ScrollDelay := 400
; После перехода на другую страницу
PageDelay := 700
; После клика по найденному товару
SelectDelay := 400
; ============================================================
; СЛУЖЕБНЫЕ ПЕРЕМЕННЫЕ
; ============================================================
ScriptRunning := false
CurrentPage := 1
CurrentScrollStep := 0
; ============================================================
; F3 — ЗАПУСК
; ============================================================
F3::
if (ScriptRunning)
return
ScriptRunning := true
CurrentPage := 1
CurrentScrollStep := 0
ToolTip, СКРИПТ ЗАПУЩЕН
Sleep, 700
ToolTip
SetTimer, MainLoop, -10
return
; ============================================================
; F6 — ОСТАНОВКА
; ============================================================
F6::
ScriptRunning := false
ToolTip, СКРИПТ ОСТАНОВЛЕН
Sleep, 700
ToolTip
return
; ============================================================
; ГЛАВНЫЙ ЦИКЛ
; ============================================================
MainLoop:
if (!ScriptRunning)
return
; ========================================================
; ПУНКТ 1
; Наводимся на поле, кликаем и вводим текст
; ========================================================
MouseMove, %InputX%, %InputY%, 0
Sleep, %MoveDelay%
Click
Sleep, %ClickDelay%
; Очищаем старый текст
Send, ^a
Sleep, 100
; Вводим нужный текст
SendInput, %SearchText%
Sleep, %InputDelay%
; ========================================================
; ПУНКТ 2
; Обновляем список
; ========================================================
MouseMove, %RefreshX%, %RefreshY%, 0
Sleep, %MoveDelay%
Click
Sleep, %RefreshDelay%
; Начинаем с верхней позиции
CurrentScrollStep := 0
; ========================================================
; ПОИСК НА ПЕРВОЙ СТРАНИЦЕ
; ========================================================
SearchPage1:
if (!ScriptRunning)
return
; --------------------------------------------------------
; Делаем OCR выбранной области
; --------------------------------------------------------
OCRResult := OCR_GetPrices(
OCRX,
OCRY,
OCRWidth,
OCRHeight,
TesseractPath,
OCRLanguage,
MaxPrice
)
; --------------------------------------------------------
; Если подходящая цена найдена
; --------------------------------------------------------
if (OCRResult != "")
{
; OCRResult возвращает:
; X|Y|Price
StringSplit, Found, OCRResult, |
FoundX := Found1
FoundY := Found2
FoundPrice := Found3
ToolTip, НАЙДЕНА ЦЕНА: %FoundPrice%
Sleep, 500
ToolTip
; --------------------------------------------
; Кликаем по найденной цене
; --------------------------------------------
MouseMove, %FoundX%, %FoundY%, 0
Sleep, %MoveDelay%
Click
Sleep, %SelectDelay%
; --------------------------------------------
; Нажимаем кнопку подтверждения
; --------------------------------------------
MouseMove, %ConfirmX%, %ConfirmY%, 0
Sleep, %MoveDelay%
Click
Sleep, %RefreshDelay%
; --------------------------------------------
; После выбора начинаем сначала.
;
; То есть возвращаемся к пункту 1,
; затем пункт 2.
; --------------------------------------------
CurrentPage := 1
CurrentScrollStep := 0
SetTimer, MainLoop, -10
return
}
; ========================================================
; ПОДХОДЯЩЕЙ ЦЕНЫ НЕТ
; ========================================================
CurrentScrollStep++
; --------------------------------------------------------
; Если ещё не дошли до конца страницы —
; двигаем ползунок вниз
; --------------------------------------------------------
if (CurrentScrollStep <= MaxScrollSteps)
{
ScrollListDown()
Sleep, %ScrollDelay%
Goto, SearchPage1
}
; ========================================================
; ПУНКТ 5
; Дошли до конца первой страницы
; Переходим на вторую
; ========================================================
if (CurrentPage = 1)
{
CurrentPage := 2
CurrentScrollStep := 0
; Переход на вторую страницу
MouseMove, %Page2X%, %Page2Y%, 0
Sleep, %MoveDelay%
Click
Sleep, %PageDelay%
; Начинаем искать на второй странице
Goto, SearchPage2
}
; ========================================================
; Если мы уже были на второй странице и ничего не нашли
; ========================================================
if (CurrentPage = 2)
{
; Возвращаемся к пункту 2.
;
; То есть обновляем список и начинаем новый поиск.
CurrentPage := 1
CurrentScrollStep := 0
MouseMove, %RefreshX%, %RefreshY%, 0
Sleep, %MoveDelay%
Click
Sleep, %RefreshDelay%
Goto, SearchPage1
}
return
; ============================================================
; ПОИСК НА ВТОРОЙ СТРАНИЦЕ
; ============================================================
SearchPage2:
if (!ScriptRunning)
return
; --------------------------------------------------------
; OCR
; --------------------------------------------------------
OCRResult := OCR_GetPrices(
OCRX,
OCRY,
OCRWidth,
OCRHeight,
TesseractPath,
OCRLanguage,
MaxPrice
)
; --------------------------------------------------------
; Если нашли подходящую цену
; --------------------------------------------------------
if (OCRResult != "")
{
StringSplit, Found, OCRResult, |
FoundX := Found1
FoundY := Found2
FoundPrice := Found3
ToolTip, НАЙДЕНА ЦЕНА: %FoundPrice%
Sleep, 500
ToolTip
; Кликаем по найденному варианту
MouseMove, %FoundX%, %FoundY%, 0
Sleep, %MoveDelay%
Click
Sleep, %SelectDelay%
; Подтверждаем
MouseMove, %ConfirmX%, %ConfirmY%, 0
Sleep, %MoveDelay%
Click
Sleep, %RefreshDelay%
; Начинаем новый цикл
CurrentPage := 1
CurrentScrollStep := 0
SetTimer, MainLoop, -10
return
}
; ========================================================
; Ничего не нашли — опускаем список
; ========================================================
CurrentScrollStep++
if (CurrentScrollStep <= MaxScrollSteps)
{
ScrollListDown()
Sleep, %ScrollDelay%
Goto, SearchPage2
}
; ========================================================
; На второй странице тоже дошли до конца
; ========================================================
CurrentPage := 1
CurrentScrollStep := 0
; Возвращаемся к пункту 2 —
; обновляем список
MouseMove, %RefreshX%, %RefreshY%, 0
Sleep, %MoveDelay%
Click
Sleep, %RefreshDelay%
Goto, SearchPage1
return
; ============================================================
; ФУНКЦИЯ ПРОКРУТКИ
; ============================================================
ScrollListDown()
{
global ScrollBarX
global ScrollBarY
global ScrollPixels
global MoveDelay
; Наводимся на ползунок
MouseMove, %ScrollBarX%, %ScrollBarY%, 0
Sleep, %MoveDelay%
; Зажимаем левую кнопку
Click, Down
Sleep, 100
; Опускаем ползунок вниз
MouseMove, %ScrollBarX%, % ScrollBarY + ScrollPixels, 300
; Отпускаем кнопку
Click, Up
}
; ============================================================
; OCR
; ============================================================
;
; Делает скриншот заданной области экрана,
; передаёт его Tesseract,
; получает TSV с координатами распознанного текста,
; ищет цену меньше MaxPrice.
;
; Возвращает:
;
; X|Y|PRICE
;
; либо пустую строку, если подходящей цены нет.
;
; ============================================================
OCR_GetPrices(X, Y, Width, Height, TesseractPath, Language, MaxPrice)
{
; --------------------------------------------------------
; Создаём временные файлы
; --------------------------------------------------------
TempImage := A_Temp "\ahk_ocr_screen.png"
TempBase := A_Temp "\ahk_ocr_result"
; --------------------------------------------------------
; Скриншот
; --------------------------------------------------------
pToken := Gdip_Startup()
if (!pToken)
return ""
pBitmap := Gdip_BitmapFromScreen(X "|" Y "|" Width "|" Height)
if (!pBitmap)
{
Gdip_Shutdown(pToken)
return ""
}
; Сохраняем PNG
Gdip_SaveBitmapToFile(pBitmap, TempImage)
; Освобождаем память
Gdip_DisposeImage(pBitmap)
Gdip_Shutdown(pToken)
; --------------------------------------------------------
; Запускаем Tesseract
;
; TSV нужен для получения координат текста.
; --------------------------------------------------------
RunWait, "%TesseractPath%" "%TempImage%" "%TempBase%" -l %Language% --psm 6 tsv,, Hide
TSVFile := TempBase ".tsv"
; Если файл не создан — OCR не сработал
if (!FileExist(TSVFile))
return ""
; --------------------------------------------------------
; Читаем результат
; --------------------------------------------------------
FileRead, TSV, %TSVFile%
if (ErrorLevel)
return ""
; --------------------------------------------------------
; Обрабатываем строки TSV
; --------------------------------------------------------
Loop, Parse, TSV, `n, `r
{
Line := A_LoopField
; Пропускаем заголовок
if (InStr(Line, "level page_num"))
continue
; Разбиваем строку TSV
StringSplit, Col, Line, %A_Tab%
; В TSV Tesseract:
;
; Col6 = left
; Col7 = top
; Col8 = width
; Col9 = height
; Col12 = распознанный текст
if (Col12 = "")
continue
Text := Trim(Col12)
; ----------------------------------------------------
; Чистим возможные символы цены
; ----------------------------------------------------
CleanPrice := Text
CleanPrice := StrReplace(CleanPrice, "₽", "")
CleanPrice := StrReplace(CleanPrice, "$", "")
CleanPrice := StrReplace(CleanPrice, "€", "")
CleanPrice := StrReplace(CleanPrice, " ", "")
CleanPrice := StrReplace(CleanPrice, ".", "")
CleanPrice := StrReplace(CleanPrice, ",", "")
; Убираем всё, кроме цифр
CleanPrice := RegExReplace(CleanPrice, "[^\d]")
; Если после очистки ничего нет
if (CleanPrice = "")
continue
Price := CleanPrice + 0
; ----------------------------------------------------
; Проверяем цену
; ----------------------------------------------------
if (Price > 0 && Price < MaxPrice)
{
; Координаты относительно экрана
FoundX := X + Col6 + (Col8 / 2)
FoundY := Y + Col7 + (Col9 / 2)
return FoundX "|" FoundY "|" Price
}
}
return ""
}