1 (изменено: Michael, 2021-01-25 04:17:49)

Тема: AHK: Loop с условием и переменной

И снова здравствуйте

Начинаю завершать свой первый скрипт. [Огромное спасибо teadrinker, бОльшая часть кода именно его, и __Михаил__, за помощь с таймером].
Суть скрипта изложена в комментариях в самом скрипте.
Возникла следующая проблема, в строке ниже, значению 'value' необходимо присвоить переменную, которая будет меняться по мере выполнения скрипта.
Я сделал цикл того, что мне нужно повторить (есть в итоговом коде в самом низу данного сообщения [loop]).

page.Evaluate( "document.querySelector('input#search').value ='mafia definitive edition прохождение';"
             . "var button = document.querySelector('button#search-icon-legacy');"
             . "button.focus(); button.click();" )

Собственно, мне нужно, чтобы Loop был несколько раз, но при этом с каждым повтором менялось значение [value ='ТО ЧТО БУДЕТ МЕНЯТЬСЯ'].
Грубо говоря - каждый повтор - новый запрос в поисковик Ютуба, запросы естественно указываются вручную, мною.
Думаю уже сутки над решением данной ситуации, буду рад любой помощи / подсказкам / советам.

#NoEnv
SetBatchLines, -1

class Chrome
{
   static DebugPort := 9222
   
   /*
      Escape a string in a manner suitable for command line parameters
   */
   CliEscape(Param)
   {
      return """" RegExReplace(Param, "(\\*)""", "$1$1\""") """"
   }
   
   /*
      Finds instances of chrome in debug mode and the ports they're running
      on. If no instances are found, returns a false value. If one or more
      instances are found, returns an associative array where the keys are
      the ports, and the values are the full command line texts used to start
      the processes.
      
      One example of how this may be used would be to open chrome on a
      different port if an instance of chrome is already open on the port
      you wanted to used.
      
      ```
      ; If the wanted port is taken, use the largest taken port plus one
      DebugPort := 9222
      if (Chromes := Chrome.FindInstances()).HasKey(DebugPort)
         DebugPort := Chromes.MaxIndex() + 1
      ChromeInst := new Chrome(ProfilePath,,,, DebugPort)
      ```
      
      Another use would be to scan for running instances and attach to one
      instead of starting a new instance.
      
      ```
      if (Chromes := Chrome.FindInstances())
         ChromeInst := {"base": Chrome, "DebugPort": Chromes.MinIndex(), PID: Chromes[Chromes.MinIndex(), "PID"]}
      else
         ChromeInst := new Chrome(ProfilePath)
      ```
   */
   FindInstances()
   {
      Out := {}
      for Item in ComObjGet("winmgmts:").ExecQuery("SELECT * FROM Win32_Process WHERE Name = 'chrome.exe'")
         if RegExMatch(Item.CommandLine, "i)chrome.exe""?\s+--remote-debugging-port=(\d+)", Match)
            Out[Match1] := {cmd: Item.CommandLine, PID: Item.ProcessId}
      return Out.MaxIndex() ? Out : False
   }
   
   /*
      ProfilePath - Path to the user profile directory to use. Will use the standard if left blank.
      URLs        - The page or array of pages for Chrome to load when it opens
      Flags       - Additional flags for chrome when launching
      ChromePath  - Path to chrome.exe, will detect from start menu when left blank
      DebugPort   - What port should Chrome's remote debugging server run on
   */
   __New(ProfilePath:="", URLs:="about:blank", Flags:="", ChromePath:="", DebugPort:="")
   {
      ; Verify ProfilePath
      if (ProfilePath != "" && !InStr(FileExist(ProfilePath), "D"))
         throw Exception("The given ProfilePath does not exist")
      this.ProfilePath := ProfilePath
      
      ; Verify ChromePath
      if (ChromePath == "")
         FileGetShortcut, %A_StartMenuCommon%\Programs\Google Chrome.lnk, ChromePath
      if (ChromePath == "")
         RegRead, ChromePath, HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\chrome.exe
      if !FileExist(ChromePath)
         throw Exception("Chrome could not be found")
      this.ChromePath := ChromePath
      
      ; Verify DebugPort
      if (DebugPort != "")
      {
         if DebugPort is not integer
            throw Exception("DebugPort must be a positive integer")
         else if (DebugPort <= 0)
            throw Exception("DebugPort must be a positive integer")
         this.DebugPort := DebugPort
      }
      
      ; Escape the URL(s)
      for Index, URL in IsObject(URLs) ? URLs : [URLs]
         URLString .= " " this.CliEscape(URL)
      
      Run, % this.CliEscape(ChromePath)
      . " --remote-debugging-port=" this.DebugPort
      . (ProfilePath ? " --user-data-dir=" this.CliEscape(ProfilePath) : "")
      . (Flags ? " " Flags : "")
      . URLString
      ,,, OutputVarPID
      this.PID := OutputVarPID
   }
   
   /*
      End Chrome by terminating the process.
   */
   Kill()
   {
      Process, Close, % this.PID
   }
   
   /*
      Queries chrome for a list of pages that expose a debug interface.
      In addition to standard tabs, these include pages such as extension
      configuration pages.
   */
   GetPageList()
   {
      http := ComObjCreate("WinHttp.WinHttpRequest.5.1")
      http.open("GET", "http://127.0.0.1:" this.DebugPort "/json")
      http.send()
      return LightJson.Parse(http.responseText)
   }
   
   /*
      Returns a connection to the debug interface of a page that matches the
      provided criteria. When multiple pages match the criteria, they appear
      ordered by how recently the pages were opened.
      
      Key        - The key from the page list to search for, such as "url" or "title"
      Value      - The value to search for in the provided key
      MatchMode  - What kind of search to use, such as "exact", "contains", "startswith", or "regex"
      Index      - If multiple pages match the given criteria, which one of them to return
      fnCallback - A function to be called whenever message is received from the page
   */
   GetPageBy(Key, Value, MatchMode:="exact", Index:=1, fnCallback:="")
   {
      Count := 0
      for n, PageData in this.GetPageList()
      {
         if (((MatchMode = "exact" && PageData[Key] = Value) ; Case insensitive
            || (MatchMode = "contains" && InStr(PageData[Key], Value))
            || (MatchMode = "startswith" && InStr(PageData[Key], Value) == 1)
            || (MatchMode = "regex" && PageData[Key] ~= Value))
            && ++Count == Index)
            return new this.Page(PageData.webSocketDebuggerUrl, fnCallback)
      }
   }
   
   /*
      Shorthand for GetPageBy("url", Value, "startswith")
   */
   GetPageByURL(Value, MatchMode:="startswith", Index:=1, fnCallback:="")
   {
      return this.GetPageBy("url", Value, MatchMode, Index, fnCallback)
   }
   
   /*
      Shorthand for GetPageBy("title", Value, "startswith")
   */
   GetPageByTitle(Value, MatchMode:="startswith", Index:=1, fnCallback:="")
   {
      return this.GetPageBy("title", Value, MatchMode, Index, fnCallback)
   }
   
   /*
      Shorthand for GetPageBy("type", Type, "exact")
      
      The default type to search for is "page", which is the visible area of
      a normal Chrome tab.
   */
   GetPage(Index:=1, Type:="page", fnCallback:="")
   {
      return this.GetPageBy("type", Type, "exact", Index, fnCallback)
   }
   
   /*
      Connects to the debug interface of a page given its WebSocket URL.
   */
   class Page
   {
      Connected := False
      ID := 0
      Responses := []
      
      /*
         wsurl      - The desired page's WebSocket URL
         fnCallback - A function to be called whenever message is received
      */
      __New(wsurl, fnCallback:="")
      {
         this.fnCallback := fnCallback
         this.BoundKeepAlive := this.Call.Bind(this, "Browser.getVersion",, False)
         
         ; TODO: Throw exception on invalid objects
         if IsObject(wsurl)
            wsurl := wsurl.webSocketDebuggerUrl
         
         wsurl := StrReplace(wsurl, "localhost", "127.0.0.1")
         this.ws := {"base": this.WebSocket, "_Event": this.Event, "Parent": this}
         this.ws.__New(wsurl)
         
         while !this.Connected
            Sleep, 50
      }
      
      /*
         Calls the specified endpoint and provides it with the given
         parameters.
         
         DomainAndMethod - The endpoint domain and method name for the
         endpoint you would like to call. For example:
         PageInst.Call("Browser.close")
         PageInst.Call("Schema.getDomains")
         
         Params - An associative array of parameters to be provided to the
         endpoint. For example:
         PageInst.Call("Page.printToPDF", {"scale": 0.5 ; Numeric Value
         , "landscape": LightJson.true ; Boolean Value
         , "pageRanges: "1-5, 8, 11-13"}) ; String value
         PageInst.Call("Page.navigate", {"url": "https://autohotkey.com/"})
         
         WaitForResponse - Whether to block until a response is received from
         Chrome, which is necessary to receive a return value, or whether
         to continue on with the script without waiting for a response.
      */
      Call(DomainAndMethod, Params:="", WaitForResponse:=True)
      {
         if !this.Connected
            throw Exception("Not connected to tab")
         
         ; Use a temporary variable for ID in case more calls are made
         ; before we receive a response.
         ID := this.ID += 1
         this.ws.Send(LightJson.Stringify({"id": ID
         , "params": Params ? Params : {}
         , "method": DomainAndMethod}))
         
         if !WaitForResponse
            return
         
         ; Wait for the response
         this.responses[ID] := False
         while !this.responses[ID]
            Sleep, 50
         
         ; Get the response, check if it's an error
         response := this.responses.Delete(ID)
         if (response.error)
            throw Exception("Chrome indicated error in response",, LightJson.Stringify(response.error))
         
         return response.result
      }
      
      /*
         Run some JavaScript on the page. For example:
         
         PageInst.Evaluate("alert(""I can't believe it's not IE!"");")
         PageInst.Evaluate("document.getElementsByTagName('button')[0].click();")
      */
      Evaluate(JS)
      {
         response := this.Call("Runtime.evaluate",
         ( LTrim Join
         {
            "expression": JS,
            "objectGroup": "console",
            "includeCommandLineAPI": LightJson.true,
            "silent": LightJson.false,
            "returnByValue": LightJson.false,
            "userGesture": LightJson.true,
            "awaitPromise": LightJson.false
         }
         ))
         
         if (response.exceptionDetails)
            throw Exception(response.result.description,, LightJson.Stringify(response.exceptionDetails))
         
         return response.result
      }
      
      /*
         Waits for the page's readyState to match the DesiredState.
         
         DesiredState - The state to wait for the page's ReadyState to match
         Interval     - How often it should check whether the state matches
      */
      WaitForLoad(DesiredState:="complete", Interval:=100)
      {
         while this.Evaluate("document.readyState").value != DesiredState
            Sleep, Interval
      }
      
      /*
         Internal function triggered when the script receives a message on
         the WebSocket connected to the page.
      */
      Event(EventName, Event)
      {
         ; If it was called from the WebSocket adjust the class context
         if this.Parent
            this := this.Parent
         
         ; TODO: Handle Error events
         if (EventName == "Open")
         {
            this.Connected := True
            BoundKeepAlive := this.BoundKeepAlive
            SetTimer, %BoundKeepAlive%, 15000
         }
         else if (EventName == "Message")
         {
            data := LightJson.Parse(Event.data)
            
            ; Run the callback routine
            fnCallback := this.fnCallback
            if (newData := %fnCallback%(data))
               data := newData
            
            if this.responses.HasKey(data.ID)
               this.responses[data.ID] := data
         }
         else if (EventName == "Close")
         {
            this.Disconnect()
         }
         else if (EventName == "Error")
         {
            throw Exception("Websocket Error!")
         }
      }
      
      /*
         Disconnect from the page's debug interface, allowing the instance
         to be garbage collected.
         
         This method should always be called when you are finished with a
         page or else your script will leak memory.
      */
      Disconnect()
      {
         if !this.Connected
            return
         
         this.Connected := False
         this.ws.Delete("Parent")
         this.ws.Disconnect()
         
         BoundKeepAlive := this.BoundKeepAlive
         SetTimer, %BoundKeepAlive%, Delete
         this.Delete("BoundKeepAlive")
      }
      
      class WebSocket
      {
         __New(WS_URL)
         {
            static wb
            
            ; Create an IE instance
            Gui, +hWndhOld
            Gui, New, +hWndhWnd
            this.hWnd := hWnd
            Gui, Add, ActiveX, vWB, Shell.Explorer
            Gui, %hOld%: Default
            
            ; Write an appropriate document
            WB.Navigate("about:<!DOCTYPE html><meta http-equiv='X-UA-Compatible'"
            . "content='IE=edge'><body></body>")
            while (WB.ReadyState < 4)
               sleep, 50
            this.document := WB.document
            
            ; Add our handlers to the JavaScript namespace
            this.document.parentWindow.ahk_savews := this._SaveWS.Bind(this)
            this.document.parentWindow.ahk_event := this._Event.Bind(this)
            this.document.parentWindow.ahk_ws_url := WS_URL
            
            ; Add some JavaScript to the page to open a socket
            Script := this.document.createElement("script")
            Script.text := "ws = new WebSocket(ahk_ws_url);`n"
            . "ws.onopen = function(event){ ahk_event('Open', event); };`n"
            . "ws.onclose = function(event){ ahk_event('Close', event); };`n"
            . "ws.onerror = function(event){ ahk_event('Error', event); };`n"
            . "ws.onmessage = function(event){ ahk_event('Message', event); };"
            this.document.body.appendChild(Script)
         }
         
         ; Called by the JS in response to WS events
         _Event(EventName, Event)
         {
            this["On" EventName](Event)
         }
         
         ; Sends data through the WebSocket
         Send(Data)
         {
            this.document.parentWindow.ws.send(Data)
         }
         
         ; Closes the WebSocket connection
         Close(Code:=1000, Reason:="")
         {
            this.document.parentWindow.ws.close(Code, Reason)
         }
         
         ; Closes and deletes the WebSocket, removing
         ; references so the class can be garbage collected
         Disconnect()
         {
            if this.hWnd
            {
               this.Close()
               Gui, % this.hWnd ": Destroy"
               this.hWnd := False
            }
         }
      }
   }
}

class LightJson
{
   static JS := LightJson.GetJS(), true := {}, false := {}, null := {}
   
   Parse(json, _rec := false) {
      if !_rec
         obj := this.Parse(this.JS.eval("(" . json . ")"), true)
      else if !IsObject(json)
         obj := json
      else if this.JS.Object.prototype.toString.call(json) == "[object Array]" {
         obj := []
         Loop % json.length
            obj.Push( this.Parse(json[A_Index - 1], true) )
      }
      else {
         obj := {}
         keys := this.JS.Object.keys(json)
         Loop % keys.length {
            k := keys[A_Index - 1]
            obj[k] := this.Parse(json[k], true)
         }
      }
      Return obj
   }
   
   Stringify(obj, indent := "") {
      if indent|1 {
         for k, v in ["true", "false", "null"]
            if (obj = this[v])
               Return v

         if IsObject( obj ) {
            isArray := true
            for key in obj {
               if IsObject(key)
                  throw Exception("Invalid key")
               if !( key = A_Index || isArray := false )
                  break
            }
            for k, v in obj
               str .= ( A_Index = 1 ? "" : "," ) . ( isArray ? "" : """" . k . """:" ) . this.Stringify(v, true)

            Return isArray ? "[" str "]" : "{" str "}"
         }
         else if !(obj*1 = "" || RegExMatch(obj, "^-?0|\s"))
            Return obj
         
         for k, v in [["\", "\\"], [A_Tab, "\t"], ["""", "\"""], ["/", "\/"], ["`n", "\n"], ["`r", "\r"], [Chr(12), "\f"], [Chr(8), "\b"]]
            obj := StrReplace( obj, v[1], v[2] )

         Return """" obj """"
      }
      sObj := this.Stringify(obj, true)
      Return this.JS.eval("JSON.stringify(" . sObj . ",'','" . indent . "')")
   }
   
   GetJS() {
      static Doc, JS
      if !Doc {
         Doc := ComObjCreate("htmlfile")
         Doc.write("<meta http-equiv=""X-UA-Compatible"" content=""IE=9"">")
         JS := Doc.parentWindow
         ( Doc.documentMode < 9 && JS.execScript() )
      }
      Return JS
   }
}


F10::

;открываем Ютуб
page:=Chrome.GetPageByTitle("Новая вкладка") 
page.Call("Page.navigate", {"url": "https://www.youtube.com/"})
page.WaitForLoad()
page:=Chrome.GetPageByTitle("YouTube")

;вбиваем запрос в поисковик Ютуба
loop, 2 ;колличество повторов
{
page.Evaluate( "document.querySelector('input#search').value ='mafia definitive edition прохождение';"
             . "var button = document.querySelector('button#search-icon-legacy');"
             . "button.focus(); button.click();" )
sleep (2000) ;ждем прогрузку    

;поиск нужного канала по имени + клик по видосу + скролл до результата
 ; let - переменная
 ; const - константа
 ; for - цикл
 ; break - пректатить цикл
 ; continue - прекратить и перейти к след. части цикла
 ; if / else - если / иначе

js =
(
((channelName) => {
   function searchCannel(channelName) {
      const coll = document.querySelectorAll('div#channel-info');
      let elem = '';
      for (let item of coll) {
         if ( item.innerText == channelName && (elem = item) )
            break;
      };
      return elem;
   }
   let channel = '', allElemsCount = 0, counter = 0;
   let timerId = setInterval(() => {
      if ( (channel = searchCannel(channelName)) || counter == 5 ) {
         clearInterval(timerId);
         if (channel)
            channel.parentNode.parentNode.querySelector('a#thumbnail').click();
         else
            alert('Not found!');
      }
      else {
         let newAllElemsCount = document.querySelectorAll('a#thumbnail').length;
         if (!(newAllElemsCount > allElemsCount))
            counter++;
         else {
            allElemsCount = newAllElemsCount;
            window.scrollTo(0, document.querySelector('ytd-app').scrollHeight);
         }
      }
   }, 2000);
})('НАЗВАНИЕ КАНАЛА');
)
page.Evaluate(js)

sleep (5000) ;ждем пока пройдет реклама

;узнаем длительность видоса + ставим таймер
page.Evaluate("document.querySelector('video').duration").value
Time := page.Evaluate("document.querySelector('video').duration").value

Sleep, % Round(Time*1000)
}

2

Re: AHK: Loop с условием и переменной

Запишите набор своих запросов в массив и итерируйте его, извлекая по элементу. Например:


list_query := ["mafia definitive edition прохождение"		; список запросов
			, "другой запрос"
			, "ещё какой-то запрос"]
eval_query := "document.querySelector('input#search').value ='{}';"
            . "var button = document.querySelector('button#search-icon-legacy');"
            . "button.focus(); button.click();"

For k, q in list_query {
	script :=  Format(eval_query, q)
	page.Evaluate(script)
	sleep (2000) ;ждем прогрузку
	
	; ... прочая логика
}

3 (изменено: Michael, 2021-01-25 19:32:50)

Re: AHK: Loop с условием и переменной

KusochekDobra
Написал список запросов, вставил прочую логику, запросы он вводит каждые 2-3 секунды, и рандомно переходит на нужный видос с указанного канала, где то косяк у меня получился, не могу найти.

;открываем Ютуб
page:=Chrome.GetPageByTitle("Новая вкладка") 
page.Call("Page.navigate", {"url": "https://www.youtube.com/"})
page.WaitForLoad()
page:=Chrome.GetPageByTitle("YouTube")

;---------------------------------------
list_query := ["mafia definitive edition прохождение"		;список запросов
			, "cyberpunk 2077 прохождение"
			, "doom eternal прохождение"]
eval_query := "document.querySelector('input#search').value ='{}';"
            . "var button = document.querySelector('button#search-icon-legacy');"
            . "button.focus(); button.click();"

For k, q in list_query {
	script :=  Format(eval_query, q)
	page.Evaluate(script)
	sleep (2000) ;ждем прогрузку
	
js =
(
((channelName) => {
   function searchCannel(channelName) {
      const coll = document.querySelectorAll('div#channel-info');
      let elem = '';
      for (let item of coll) {
         if ( item.innerText == channelName && (elem = item) )
            break;
      };
      return elem;
   }
   let channel = '', allElemsCount = 0, counter = 0;
   let timerId = setInterval(() => {
      if ( (channel = searchCannel(channelName)) || counter == 5 ) {
         clearInterval(timerId);
         if (channel)
            channel.parentNode.parentNode.querySelector('a#thumbnail').click();
         else
            alert('Not found!');
      }
      else {
         let newAllElemsCount = document.querySelectorAll('a#thumbnail').length;
         if (!(newAllElemsCount > allElemsCount))
            counter++;
         else {
            allElemsCount = newAllElemsCount;
            window.scrollTo(0, document.querySelector('ytd-app').scrollHeight);
         }
      }
   }, 2000);
})('StopGame.Ru');
)
page.Evaluate(js)

sleep (5000) ;ждем пока пройдет реклама

;узнаем длительность видоса + ставим таймер
page.Evaluate("document.querySelector('video').duration").value
Time := page.Evaluate("document.querySelector('video').duration").value

Sleep, % Round(Time*1000)
}

Порядок действий должен быть таков: ввел 1 запрос, нашел видос + кликнул по нему (js), далее просчет времени видоса и запись его в Sleep, далее вводится 2 запрос и так далее.

4

Re: AHK: Loop с условием и переменной

List_query - сам массив
Eval_query - действия массива
For - запускается цикл
script :=  Format(eval_query, q) - начинается перебор из list_query
Вот на этом моменте, как только он выбрал из list_query 1ый запрос, нужно перейти к выполнению “js” и таймера, и только потом перейти к запросу 2 и так далее.
page.Evaluate(script) - выполнить “script”
Это, если я всё правильно понял.
Но не понимаю, что необходимо сделать

5

Re: AHK: Loop с условием и переменной

Michael

Нет желания ковырять код - уж извиняюсь, но если для задержки используется 'SetTimer', то он работает вместе с другим кодом. То есть выгоднее использовать тогда обычный 'Sleep' если нужно дождаться каких либо действий.

Win10x64, AHK v1.1.33.09 (Unicode 64-bit) | AHK-Wiki | Переменные и выражения | RegEx101

6

Re: AHK: Loop с условием и переменной

__Михаил__
Так Sleep и используется, причём из кода, который вы мне дали, только это в другой теме было:


page.Evaluate("document.querySelector('video').duration").value
Time := page.Evaluate("document.querySelector('video').duration").value

Sleep, % Round(Time*1000)

7

Re: AHK: Loop с условием и переменной

Michael

Не могу понят что в итоге должно получиться? Накрутчик просмотров на Ютубе?

Win10x64, AHK v1.1.33.09 (Unicode 64-bit) | AHK-Wiki | Переменные и выражения | RegEx101

8 (изменено: Michael, 2021-01-26 00:21:20)

Re: AHK: Loop с условием и переменной

__Михаил__
Скажем так, помощь начинающим Ютуберам, безвозмездная.
Буду повышать статистику начинающим Ютуберам, выбирая их рандомно, потому что мусор в Трендах и верхних видосах в запросах уже надоел, а некоторые, гораздо более интересные ролики порой не замечают, на самые разные тематики.
Суть: Поиск по запросу 1, полное воспроизведение; поиск по запросу 2, полное воспроизведение... и т.д.

9

Re: AHK: Loop с условием и переменной

Michael пишет:

Скажем так, помощь начинающим Ютуберам, безвозмездная.
Буду повышать статистику начинающим Ютуберам, выбирая их рандомно

Думаете от вашего одного просмотра будет толк?
На кворке 4000 реальных просмотров разных людей стоит 500 рублей.

10

Re: AHK: Loop с условием и переменной

Оффтоп

+ открыть спойлер

Michael

Против системы не попрёшь. Ютуб использует сложные алгоритмы и наверняка отследит такую накрутку. Будут ли последствия - не знаю. Но если нужно накручивать по 'чёрному', то могу посоветовать следующее: открывать кучу вкладок, менять качество до минимума, повторять до тех пор пока процессор не нагрузится до предела, ну или видюха (у меня она слабее проца).
Далее после просмотра, дабы ютуб посчитал видео полезным, как говорят многие - нужно оставить не менее 4 слов в комментарии.

Win10x64, AHK v1.1.33.09 (Unicode 64-bit) | AHK-Wiki | Переменные и выражения | RegEx101

11

Re: AHK: Loop с условием и переменной

Malcev
Просмотров будет больше, чем достаточно, виртуалки с «реальным железом», «человекопохожие» аккаунты, прокси и прочие материалы уже готовы и протестированы. Мне бы автоматизировать данный процесс, я уже почти в финале, но, как это обычно бывает, попа нарисовывается в конце (в моем случае на протяжении создания всего этого скрипта, ибо тут я вообще не мастер).
И да, цены на кворке и прочих ресурсах я знаю, речь идёт именно о бесплатной помощи, людям, которые этого не просят, но у которых есть перспективы и талант.

12

Re: AHK: Loop с условием и переменной

Бесплатный совет: чтобы избежать ожидающей боли и эффективно обманывать тырнет в этом деле, Вам не AHK нужен, а BrowserAutomationStudio. На этой платформе, браузер целиком обёрнут в инструмент, позволяющий тонко настраивать свои атаки, вплоть до подмены отпечатка, WebRTS, туннелирование, прокси для каждого процесса и прочие ништяки.

Делал на нём несколько удачных проектов. Отталкивает только отсутствие внятной документации и интерфейс, заточенный на школьников и крайне громоздкий. Платная версия, к слову, эти недостатки не исправляет.

То, что Вы определяете как надёжный задел в 11 сообщении, разобьёт Вам сердце, сожрёт полезные ресурсы и кучу времени. Хотя бы только тем, что браузер не поддерживает проксификацию и мосты наводить придётся сразу для целого хоста, что чревато потерей выполняемого прогресса для других процессов, стреляющих в сеть по своим целям.

Удобства "Chrome.ahk", лучше для чего-то попроще использовать.

13

Re: AHK: Loop с условием и переменной

KusochekDobra У сервисов гугл стоит отличная идентификационная система пользователя, аналогичная амазону. В 20 году ужесточили политику учета просмотров на ютубе. Кроме сетевой и браузерной идентификации, могут использовать еще операционную и аппаратную. Не похоже что эту проблему можно решить браузерно, хотя могу и ошибаться не знаком с "BrowserAutomationStudio". Для такой задачи скорее нужна хорошая антифрод система. И сообщение тса "виртуалки с «реальным железом», «человекопохожие» аккаунты, прокси и прочие материалы" - похоже на то, что такая система у него есть.

GD

14

Re: AHK: Loop с условием и переменной

KusochekDobra
Слышал о BrowserAutomationStudio, но услышал слишком поздно видимо, но, отсутствие документации нормальной это серьезный минус, ибо даже в АХК, где документации и примеров куча, мне сложновато.
Насчет моего способа в 11 сообщении, для теста, я сделал 3 аккаунта, которые успешно прошли монетизацию, и чьи видосы отображаются на адекватных местах в поиске по определенным запросам (далеко не самым зашкварным), этим аккаунтам уже более полугода, и никаких проблем с ними нет.
Так что, на текущий момент хочу таки доделать всё это дело на AHK, раз уж начал, потом возможно попробую реализовать подобное на BrowserAutomationStudio или на чем-нибудь еще.
Очень обидно, когда почти дошел до финала, и опять застрял

15

Re: AHK: Loop с условием и переменной

Botsy, "BAS" имеет в своём арсенале набор инструментов, позволяющий полностью эмулировать любую конфигурацию системы и её окружения, при том, не просто уникализировать текущее соединение, а "притвориться" кем-то другим, уже, возможно, известным системе, что сохраняет и Вашу анонимность и не добавляет подозрительности. Для этого есть специальный сервис, работающий с ним в тандеме(платно).

Если побороть в себе чувство отторжения, вызванное внешним видом и тотальным неудобством интерфейса этой тулзы и потратить время на понимание, то эта инвестиция позволит ставить на поток различные регистраторы аккаунтов, накруток, спама... В абсолютно любых сервисах.

Michael, в этой попытке сравнить, Вы исходите из весьма и весьма скромного опыта относительно того, чем только собираетесь заниматься, а я исхожу из того, чем занимаюсь.

Michael пишет:

Очень обидно, когда почти дошел до финала, и опять застрял

Звучит как обвинение.
Если ищете помощи на этом форуме, будьте конкретны. Мало кому интересно разбираться в чужом коде и это меньшинство тем незначительней чем больше действий подразумевает Ваш пример.

Большинство новичков, почувствовав магию программирования на простых примерах, начинают "взламывать пентагон" своих мечтаний, считая, что разберутся "по пути". Как правило, их ожидает стена, за которой не видно остальных препятствий, надёжно скрывающих каждые следующие бастионы и стеночки. Не ведая о перспективе и не имея сравнительного опыта, каждый представляет себе, что вот эта стена — непременно последняя и дальше финиш, но чаще всего это совсем не так.

Я ни в коем разе не рекламирую сторонний софт и не пытаюсь Вас отговорить. Более того, я даже желаю Вам пройти этот тернистый путь не опустив руки. Только страдания, страдания и ещё раз страдания в купе с верой в успех, приведут Вас к правильному решению. Приведут к пониманию, что есть не только "AHK", но и другие способы, вероятно, более заточенные под конкретные ситуации.

16

Re: AHK: Loop с условием и переменной

KusochekDobra
Это обвинение скорее самого себя, в невозможности грамотно и конкретно объяснить проблему.
Не буду больше оффтопить, попробую еще раз объяснить:

list_query := ["Запрос1"		
			, "Запрос2"
			, "Запрос3"]
eval_query := "document.querySelector('input#search').value ='{}';"
            . "var button = document.querySelector('button#search-icon-legacy');"
            . "button.focus(); button.click();"

На данном этапе начинается перебор значений из list_query, вставка их в eval_query и выполение.

For k, q in list_query {
	script :=  Format(eval_query, q)
	page.Evaluate(script)
	sleep (2000) ;ждем прогрузку

Мне нужно, как только он вытащил 1 значение (в моем примере "Запрос1"), вставил его в eval_query и выполнил, началось бы выполнение иного скрипта / действия.
Как пример:

For k, q in list_query {
	script :=  Format(eval_query, q)
	page.Evaluate(script)
	sleep (2000) ;ждем прогрузку
      ;После выполнения "Запрос1 в eval_query" он начал делать всё что ниже
        ;Прочая логика
        ;Прочая логика
        ;Прочая логика
        ;Прочая логика
        ;Прочая логика
     ;И только сейчас он перешел к "Запрос2" и сделал всё ту же "прочую логику", как и после "запроса 1"

17

Re: AHK: Loop с условием и переменной

Какой то странный вопрос на фоне прогресса ТС, может я чего то не понял, или весь прогресс полностью состоит из чужих кусков.
Но если я всё правильно понял, то - "просто вставить код".


For k, q in list_query {
	MsgBox % q
	script :=  Format(eval_query, q)
	page.Evaluate(script)
	sleep (2000)
    MsgBox Прочая логика 
    MsgBox Прочая логика 
    MsgBox Прочая логика 
    MsgBox Прочая логика 
    MsgBox Прочая логика  
}
По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64 v20H2, AutoHotkey_L v1.1.33.09 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

18 (изменено: Michael, 2021-01-26 20:00:01)

Re: AHK: Loop с условием и переменной

serzh82saratov
В этом то и дело, что код я вставляю, но работает он не так, как задумано.
После "запроса1" он начинает перелистывать дальше, "запрос2", "запрос3"... итд, даже не прикасаясь к "прочей логике".
А мне нужно: "запрос1" - сразу после - прочая логика, "запрос2 - сразу после - прочая логика... и так далее...
Пост с проблемным скриптом

19 (изменено: serzh82saratov, 2021-01-26 21:46:49)

Re: AHK: Loop с условием и переменной

Да уж грамотно вы пытаетесь объяснить, сначала надо чтобы в принципе выполнялось, потом оказывается что оно всё таки выполняется, но просто не так как задумано. А как задумано сами догадайтесь и поправьте.
Вместо одного кода JS, сделано три куска, которые запускаются после паузы, то есть без всякой проверки того что произошло в предыдущем.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64 v20H2, AutoHotkey_L v1.1.33.09 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

20

Re: AHK: Loop с условием и переменной

Michael, попробуйте добавить отладочной информации в сценарий. Поместите в неё данные, которые однозначно показывают, что конкретно происходит на текущем шаге, а затем проанализируйте.

Как упомянул выше serzh82saratov, при работе с браузером, нет никаких гарантий, что ожидаемое действие выполнилось прямо сейчас. JavaScript — событийный язык, там всё несколько иначе происходит и чтобы быть уверенным, что с нужным элементом можно провзаимодействовать, всегда следует убедиться, что он в принципе существует в контексте страницы. То есть, последовательность должна состоять не только из инструкций, а так же из проверок, что предыдущие инструкции успешно/неудачно выполнились.

Имейте так же ввиду, что мы пытаемся Вас понять по тому, что Вы пишете в качестве примеров и сильно вряд ли тяготеем их запускать. Это связано ещё и с тем, что Ваши конечные цели нам не ясны, а тратить своё время на такое глобально погружение, слишком расточительное занятие, которое запросто может оказаться глупой затеей.

21

Re: AHK: Loop с условием и переменной

KusochekDobra
Собственно, после многочасового тестирования, опытным путем, выяснил, что проблема возникает только если для поиска используется листовка (скролл).
В 100% случаев, где необходимый канал находился в первых 20-ти результатах поиска (действие скролла при этом пропускалось), всё работало как задумано, а именно:
Ввелся запрос 1 - поиск по каналу - клик по соотв. видосу - sleep, равный длине видоса, далее запрос 2 и всё так же по кругу.
Что происходит, если для поиска канала необходимо применение скролла (скрипт тот же самый 1 в 1):
Ввелся запрос 1 - ввелся запрос 2 - ввелся запрос 3 - скролл до нужного канала, клик по видосу - sleep, равный длине видоса.
Соответственно, для запроса 1 и запроса 2 - действия в JS работают криво. Опять же, только, если нужен скролл.
Еще одна важная вещь, без записи набора запросов в массив и итерирации, извлекая по элементу, всё нормально, скролится, и вообще всё работает.
Вроде объяснил максимально подробно.

22

Re: AHK: Loop с условием и переменной

Вам уже дали ответ. Если не можете уловить его из посланий выше, дойдёт с практикой.

23 (изменено: Michael, 2021-01-27 22:50:58)

Re: AHK: Loop с условием и переменной

KusochekDobra
Я видел, у меня не получается сделать OutputDebug, смотрел примеры в notepad++ и SciTE (я в основном Scite использую), у меня тупо ничего не выводит... Объясните идиоту, как работает отладка, пожалуйста.
Кнопка debug в SciTE вообще перестала работать, раньше по нажатию на неё происходило "debugging" в строке названия окна SciTE. А сейчас вообще ничего.

24

Re: AHK: Loop с условием и переменной

Перейдя по ссылке, всё внимательно почитали, или только функционал?
Я лично для "OutputDebug" всегда использовал "DebugView", к которому ведёт ссылка с этой страницы.
Почитайте так же о ListVars и погуглите всё, что придёт в голову об отладке в AHK. Это достаточно распространённый вопрос, чтобы в нём разобраться самостоятельно.

И если в обсуждении отвечаете предыдущему спикеру, выделять его ник не имеет смысла, раз повествование не разрывается.

25

Re: AHK: Loop с условием и переменной

Прочитал с переводчиком, максимально подробно, насколько это возможно, у меня он не хочет работать, не пойму почему.

Удалось встроенными средствами АХК (дабл клик по иконке в трее) получить след. данные:

444: if indent|1  
445: For k,v in ["true", "false", "null"]
446: if (obj = this[v])  
446: if (obj = this[v])  
446: if (obj = this[v])  
449: if IsObject( obj )  
450: isArray := true
451: For key, in obj
452: if IsObject(key)  
454: if !( key = A_Index || isArray := false )  
455: Break
457: For k,v in obj
458: str .= ( A_Index = 1 ? "" : "," ) . ( isArray ? "" : """" . k . """:" ) . this.Stringify(v, true)  
444: if indent|1  
445: For k,v in ["true", "false", "null"]
446: if (obj = this[v])  
446: if (obj = this[v])  
446: if (obj = this[v])  
449: if IsObject( obj )  
462: if !(obj*1 = "" || RegExMatch(obj, "^-?0|\s"))  
463: Return,obj
458: str .= ( A_Index = 1 ? "" : "," ) . ( isArray ? "" : """" . k . """:" ) . this.Stringify(v, true)  
444: if indent|1  
445: For k,v in ["true", "false", "null"]
446: if (obj = this[v])  
446: if (obj = this[v])  
446: if (obj = this[v])  
449: if IsObject( obj )  
462: if !(obj*1 = "" || RegExMatch(obj, "^-?0|\s"))  
465: For k,v in [["\", "\\"], [A_Tab, "\t"], ["""", "\"""], ["/", "\/"], ["
", "\n"], ["
", "\r"], [Chr(12), "\f"], [Chr(8), "\b"]]
466: obj := StrReplace( obj, v[1], v[2] )
466: obj := StrReplace( obj, v[1], v[2] )
466: obj := StrReplace( obj, v[1], v[2] )
466: obj := StrReplace( obj, v[1], v[2] )
466: obj := StrReplace( obj, v[1], v[2] )
466: obj := StrReplace( obj, v[1], v[2] )
466: obj := StrReplace( obj, v[1], v[2] )
466: obj := StrReplace( obj, v[1], v[2] )
468: Return,"""" obj """"
458: str .= ( A_Index = 1 ? "" : "," ) . ( isArray ? "" : """" . k . """:" ) . this.Stringify(v, true)  
444: if indent|1  
445: For k,v in ["true", "false", "null"]
446: if (obj = this[v])  
446: if (obj = this[v])  
446: if (obj = this[v])  
449: if IsObject( obj )  
450: isArray := true
451: For key, in obj
457: For k,v in obj
460: Return,isArray ? "[" str "]" : "{" str "}"
460: Return,isArray ? "[" str "]" : "{" str "}"
471: Return,this.JS.eval("JSON.stringify(" . sObj . ",'','" . indent . "')")
394: this.document.parentWindow.ws.send(Data)  
395: }
235: if !WaitForResponse  
236: Return
297: if this.Parent  
298: this := this.Parent
301: if (EventName == "Open")  
307: if (EventName == "Message")  
309: data := LightJson.Parse(Event.data)
423: if !_rec  
424: obj := this.Parse(this.JS.eval("(" . json . ")"), true)
423: if !_rec  
425: if !IsObject(json)  
427: if this.JS.Object.prototype.toString.call(json) == "[object Array]"  
433: obj := {}
434: keys := this.JS.Object.keys(json)
435: Loop,keys.length
436: k := keys[A_Index - 1]
437: obj[k] := this.Parse(json[k], true)  
423: if !_rec  
425: if !IsObject(json)  
426: obj := json
440: Return,obj
438: }
436: k := keys[A_Index - 1]
437: obj[k] := this.Parse(json[k], true)  
423: if !_rec  
425: if !IsObject(json)  
427: if this.JS.Object.prototype.toString.call(json) == "[object Array]"  
433: obj := {}
434: keys := this.JS.Object.keys(json)
435: Loop,keys.length
436: k := keys[A_Index - 1]
437: obj[k] := this.Parse(json[k], true)  
423: if !_rec  
425: if !IsObject(json)  
426: obj := json
440: Return,obj
438: }
436: k := keys[A_Index - 1]
437: obj[k] := this.Parse(json[k], true)  
423: if !_rec  
425: if !IsObject(json)  
426: obj := json
440: Return,obj
438: }
436: k := keys[A_Index - 1]
437: obj[k] := this.Parse(json[k], true)  
423: if !_rec  
425: if !IsObject(json)  
426: obj := json
440: Return,obj
438: }
436: k := keys[A_Index - 1]
437: obj[k] := this.Parse(json[k], true)  
423: if !_rec  
425: if !IsObject(json)  
426: obj := json
440: Return,obj
438: }
436: k := keys[A_Index - 1]
437: obj[k] := this.Parse(json[k], true)  
423: if !_rec  
425: if !IsObject(json)  
426: obj := json
440: Return,obj
438: }
439: }
440: Return,obj
438: }
439: }
440: Return,obj
440: Return,obj
312: fnCallback := this.fnCallback
313: if (newData := %fnCallback%(data))  
316: if this.responses.HasKey(data.ID)  
318: }
327: } (13.97)
225: if !this.Connected  
230: ID := this.ID += 1
231: this.ws.Send(LightJson.Stringify({"id": ID, "params": Params ? Params : {}, "method": DomainAndMethod}))  
444: if indent|1  
470: sObj := this.Stringify(obj, true)
444: if indent|1  
445: For k,v in ["true", "false", "null"]
446: if (obj = this[v])  
446: if (obj = this[v])  
446: if (obj = this[v])  
449: if IsObject( obj )  
450: isArray := true
451: For key, in obj
452: if IsObject(key)  
454: if !( key = A_Index || isArray := false )  
455: Break
457: For k,v in obj
458: str .= ( A_Index = 1 ? "" : "," ) . ( isArray ? "" : """" . k . """:" ) . this.Stringify(v, true)  
444: if indent|1  
445: For k,v in ["true", "false", "null"]
446: if (obj = this[v])  
446: if (obj = this[v])  
446: if (obj = this[v])  
449: if IsObject( obj )  
462: if !(obj*1 = "" || RegExMatch(obj, "^-?0|\s"))  
463: Return,obj
458: str .= ( A_Index = 1 ? "" : "," ) . ( isArray ? "" : """" . k . """:" ) . this.Stringify(v, true)  
444: if indent|1  
445: For k,v in ["true", "false", "null"]
446: if (obj = this[v])  
446: if (obj = this[v])  
446: if (obj = this[v])  
449: if IsObject( obj )  
462: if !(obj*1 = "" || RegExMatch(obj, "^-?0|\s"))  
465: For k,v in [["\", "\\"], [A_Tab, "\t"], ["""", "\"""], ["/", "\/"], ["
", "\n"], ["
", "\r"], [Chr(12), "\f"], [Chr(8), "\b"]]
466: obj := StrReplace( obj, v[1], v[2] )
466: obj := StrReplace( obj, v[1], v[2] )
466: obj := StrReplace( obj, v[1], v[2] )
466: obj := StrReplace( obj, v[1], v[2] )
466: obj := StrReplace( obj, v[1], v[2] )
466: obj := StrReplace( obj, v[1], v[2] )
466: obj := StrReplace( obj, v[1], v[2] )
466: obj := StrReplace( obj, v[1], v[2] )
468: Return,"""" obj """"
458: str .= ( A_Index = 1 ? "" : "," ) . ( isArray ? "" : """" . k . """:" ) . this.Stringify(v, true)  
444: if indent|1  
445: For k,v in ["true", "false", "null"]
446: if (obj = this[v])  
446: if (obj = this[v])  
446: if (obj = this[v])  
449: if IsObject( obj )  
450: isArray := true
451: For key, in obj
457: For k,v in obj
460: Return,isArray ? "[" str "]" : "{" str "}"
460: Return,isArray ? "[" str "]" : "{" str "}"
471: Return,this.JS.eval("JSON.stringify(" . sObj . ",'','" . indent . "')")
394: this.document.parentWindow.ws.send(Data)  
395: }
235: if !WaitForResponse  
236: Return
297: if this.Parent  
298: this := this.Parent
301: if (EventName == "Open")  
307: if (EventName == "Message")  
309: data := LightJson.Parse(Event.data)
423: if !_rec  
424: obj := this.Parse(this.JS.eval("(" . json . ")"), true)
423: if !_rec  
425: if !IsObject(json)  
427: if this.JS.Object.prototype.toString.call(json) == "[object Array]"  
433: obj := {}
434: keys := this.JS.Object.keys(json)
435: Loop,keys.length
436: k := keys[A_Index - 1]
437: obj[k] := this.Parse(json[k], true)  
423: if !_rec  
425: if !IsObject(json)  
426: obj := json
440: Return,obj
438: }
436: k := keys[A_Index - 1]
437: obj[k] := this.Parse(json[k], true)  
423: if !_rec  
425: if !IsObject(json)  
427: if this.JS.Object.prototype.toString.call(json) == "[object Array]"  
433: obj := {}
434: keys := this.JS.Object.keys(json)
435: Loop,keys.length
436: k := keys[A_Index - 1]
437: obj[k] := this.Parse(json[k], true)  
423: if !_rec  
425: if !IsObject(json)  
426: obj := json
440: Return,obj
438: }
436: k := keys[A_Index - 1]
437: obj[k] := this.Parse(json[k], true)  
423: if !_rec  
425: if !IsObject(json)  
426: obj := json
440: Return,obj
438: }
436: k := keys[A_Index - 1]
437: obj[k] := this.Parse(json[k], true)  
423: if !_rec  
425: if !IsObject(json)  
426: obj := json
440: Return,obj
438: }
436: k := keys[A_Index - 1]
437: obj[k] := this.Parse(json[k], true)  
423: if !_rec  
425: if !IsObject(json)  
426: obj := json
440: Return,obj
438: }
436: k := keys[A_Index - 1]
437: obj[k] := this.Parse(json[k], true)  
423: if !_rec  
425: if !IsObject(json)  
426: obj := json
440: Return,obj
438: }
439: }
440: Return,obj
438: }
439: }
440: Return,obj
440: Return,obj
312: fnCallback := this.fnCallback
313: if (newData := %fnCallback%(data))  
316: if this.responses.HasKey(data.ID)  
318: }
327: } (1.03)
225: if !this.Connected  
230: ID := this.ID += 1
231: this.ws.Send(LightJson.Stringify({"id": ID, "params": Params ? Params : {}, "method": DomainAndMethod}))  
444: if indent|1  
470: sObj := this.Stringify(obj, true)
444: if indent|1  
445: For k,v in ["true", "false", "null"]
446: if (obj = this[v])  
446: if (obj = this[v])  
446: if (obj = this[v])  
449: if IsObject( obj )  
450: isArray := true
451: For key, in obj
452: if IsObject(key)  
454: if !( key = A_Index || isArray := false )  
455: Break
457: For k,v in obj
458: str .= ( A_Index = 1 ? "" : "," ) . ( isArray ? "" : """" . k . """:" ) . this.Stringify(v, true)  
444: if indent|1  
445: For k,v in ["true", "false", "null"]
446: if (obj = this[v])  
446: if (obj = this[v])  
446: if (obj = this[v])  
449: if IsObject( obj )  
462: if !(obj*1 = "" || RegExMatch(obj, "^-?0|\s"))  
463: Return,obj
458: str .= ( A_Index = 1 ? "" : "," ) . ( isArray ? "" : """" . k . """:" ) . this.Stringify(v, true)  
444: if indent|1  
445: For k,v in ["true", "false", "null"]
446: if (obj = this[v])  
446: if (obj = this[v])  
446: if (obj = this[v])  
449: if IsObject( obj )  
462: if !(obj*1 = "" || RegExMatch(obj, "^-?0|\s"))  
465: For k,v in [["\", "\\"], [A_Tab, "\t"], ["""", "\"""], ["/", "\/"], ["
", "\n"], ["
", "\r"], [Chr(12), "\f"], [Chr(8), "\b"]]
466: obj := StrReplace( obj, v[1], v[2] )
466: obj := StrReplace( obj, v[1], v[2] )
466: obj := StrReplace( obj, v[1], v[2] )
466: obj := StrReplace( obj, v[1], v[2] )
466: obj := StrReplace( obj, v[1], v[2] )
466: obj := StrReplace( obj, v[1], v[2] )
466: obj := StrReplace( obj, v[1], v[2] )
466: obj := StrReplace( obj, v[1], v[2] )
468: Return,"""" obj """"
458: str .= ( A_Index = 1 ? "" : "," ) . ( isArray ? "" : """" . k . """:" ) . this.Stringify(v, true)  
444: if indent|1  
445: For k,v in ["true", "false", "null"]
446: if (obj = this[v])  
446: if (obj = this[v])  
446: if (obj = this[v])  
449: if IsObject( obj )  
450: isArray := true
451: For key, in obj
457: For k,v in obj
460: Return,isArray ? "[" str "]" : "{" str "}"
460: Return,isArray ? "[" str "]" : "{" str "}"
471: Return,this.JS.eval("JSON.stringify(" . sObj . ",'','" . indent . "')")
394: this.document.parentWindow.ws.send(Data)  
395: }
235: if !WaitForResponse  
236: Return
297: if this.Parent  
298: this := this.Parent
301: if (EventName == "Open")  
307: if (EventName == "Message")  
309: data := LightJson.Parse(Event.data)
423: if !_rec  
424: obj := this.Parse(this.JS.eval("(" . json . ")"), true)
423: if !_rec  
425: if !IsObject(json)  
427: if this.JS.Object.prototype.toString.call(json) == "[object Array]"  
433: obj := {}
434: keys := this.JS.Object.keys(json)
435: Loop,keys.length
436: k := keys[A_Index - 1]
437: obj[k] := this.Parse(json[k], true)  
423: if !_rec  
425: if !IsObject(json)  
426: obj := json
440: Return,obj
438: }
436: k := keys[A_Index - 1]
437: obj[k] := this.Parse(json[k], true)  
423: if !_rec  
425: if !IsObject(json)  
427: if this.JS.Object.prototype.toString.call(json) == "[object Array]"  
433: obj := {}
434: keys := this.JS.Object.keys(json)
435: Loop,keys.length
436: k := keys[A_Index - 1]
437: obj[k] := this.Parse(json[k], true)  
423: if !_rec  
425: if !IsObject(json)  
426: obj := json
440: Return,obj
438: }
436: k := keys[A_Index - 1]
437: obj[k] := this.Parse(json[k], true)  
423: if !_rec  
425: if !IsObject(json)  
426: obj := json
440: Return,obj
438: }
436: k := keys[A_Index - 1]
437: obj[k] := this.Parse(json[k], true)  
423: if !_rec  
425: if !IsObject(json)  
426: obj := json
440: Return,obj
438: }
436: k := keys[A_Index - 1]
437: obj[k] := this.Parse(json[k], true)  
423: if !_rec  
425: if !IsObject(json)  
426: obj := json
440: Return,obj
438: }
436: k := keys[A_Index - 1]
437: obj[k] := this.Parse(json[k], true)  
423: if !_rec  
425: if !IsObject(json)  
426: obj := json
440: Return,obj
438: }
439: }
440: Return,obj
438: }
439: }
440: Return,obj
440: Return,obj
312: fnCallback := this.fnCallback
313: if (newData := %fnCallback%(data))  
316: if this.responses.HasKey(data.ID)  
318: }
327: } (12.23)

26

Re: AHK: Loop с условием и переменной

Тогда, самое простое — сделать текстовый лог.
Принцип тот же самый. В контрольных местах выводите в лог информацию о том, что происходит, конкатенируя с A_LineNumber для удобства. Можно так же время выводить.

27

Re: AHK: Loop с условием и переменной

Моё мнение, что не стоит ему пока голову забивать с OutputDebug, тут MsgBox вполне. А вот alert очень пригодится в бесконечном допиливании JS.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64 v20H2, AutoHotkey_L v1.1.33.09 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

28 (изменено: Michael, 2021-01-29 17:50:51)

Re: AHK: Loop с условием и переменной

На данный момент удалось получить отладку только этими средствами: https://github.com/Lexikos/DebugVars.ahk#debugvars
Вот что получилось:
https://i.ibb.co/C03Sv0c/image.png
Это хотя бы то, что нужно? По крайней мере некоторую инфу по действиям я там нашел, переменные, значения и так далее.

29

Re: AHK: Loop с условием и переменной

Можно и так. И здесь действительно MsgBox подойдёт вместо брэйкпоинтов. Но это лютый гемор. Вам нужно смотреть на состояние ключевых моментов, подозрения по которым у Вас есть, а тут весь стейт показан. Это будет отнимать больше времени, чем прогнать сценарий через логгер и за тем изучить десяток другой интересующих строк с указанием этапов/итераций, условий выполнения и прочих тонкостей.

Но, пробуйте.
"Истина, где-то рядом."(с)

30

Re: AHK: Loop с условием и переменной

У меня всё - ступор. Я не понимаю как отследить именно те моменты, к которым у меня подозрения. Чем больше информации смотрю, видеоуроков и прочего - тем больше запутываюсь. Начинаю что-то пробовать - вообще мозг отрубается.

31

Re: AHK: Loop с условием и переменной

Так это нормально, если вместо того чтобы писать код, и начинать понимать что это за каракули, вы зачем то начинаете учиться отлаживать, не понятно что и как написанное. Причём я в ваших постах до этого не видел ни намёка на то что вы сомневаетесь в каком то конкретном месте кода (а видно только полное непонимание происходящего), и не знаете как это исправить. Отладка - звучит обнадёживающе.

Вам в №20 всё объяснили, надо всё писать на JS, а вы прочитали только про debug анк, который там к слову пришёлся.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64 v20H2, AutoHotkey_L v1.1.33.09 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

32

Re: AHK: Loop с условием и переменной

Более того, в 21 сообщении Michael сделал выводы, что как раз таки весь гемор в браузере творится.