1 (изменено: DD, 2018-06-25 03:05:18)

Тема: AHK: Мониторинг стены ВКонтакта

Скрипт предназначен для отслеживания постов и комментариев в ВК-сообществе/профиле. После запуска логинится один раз (нужно для работы execute-процедуры, которая в зависимости от настроек, получает за один запрос изменения о до 2500 последних постов со стены), скачивает указанное количество постов и в последующем докачивает в них комментарии в случае изменений. Комментарии могут докачиваться не именно с добавленного и ниже, а на указанное количество комментариев выше него — на случай, если несколько комментов со стены были удалены и их позиция сместилась.
Таким образом, один вызов для получения общей картины об изменениях на стене, и при их наличии — точное обращение к добавленным комментариям.

В прикреплении скрипт можно скачать вместе с CSS-стилями, нужными для страниц. Для наглядности работают некоторые Tooltip.

;*******************************************************************************
; WallMonitor.ahk
;*******************************************************************************
#Persistent
#MaxMem 200
SetBatchLines -1
#SingleInstance Force
HTTP := ComObjCreate("WinHTTP.WinHTTPRequest.5.1")

; ========================= НАСТРОЙКИ ПОЛЬЗОВАТЕЛЯ =========================
email := "ВАШ_ИМЭЙЛ_НА_ВК"
password := "ВАШ_ПАРОЛЬ_НА_ВК"
OwnerId := -29534144      ; айди сообщества, которое мониторим
Pause := 20               ; пауза В СЕКУНДАХ между проверками (за слишком частые обращения блокируют)
PstIters := 1             ; До 25-ти. Количество итераций при получении инфы о постах и комментах,
                          ; увеличивать на один только если отслеживаемых постов больше 100
PstCount := 2             ; Сколько последних постов со стены отслеживать
                          ; До 2500, в зависмости от итерации, которую
                          ; с каждой сотней постов надо увеличивать на единицу. 

CmtMinus := 3             ; На сколько комментариев отступать назад при их докачке
                          ; (на случай удаления на сервере)
Dest_Path = %A_ScriptDir% ; путь к целевой папке (куда сохранять результат)
; ========================= КОНЕЦ НАСТРОЕК ПОЛЬЗОВАТЕЛЯ =========================

SetTimer, gogo, % Pause*1000
Return

gogo:

If not (LoginMode == 1)  ;при первом запуске логиниться однократно:
{
   gosub login
   LoginMode = 1
}

;--------------------------------------------
;ПОСТ:
;--------------------------------------------
HTTP.Open("POST", "https://vk.com/dev?act=a_run_method&al=1&hash=" PostHash "&method=execute&param_code=var%20owner_id%3D%22" OwnerId "%22%3Bvar%20offset%3D0%3Bvar%20ITERS%3D" PstIters "%3Bvar%20COUNT%3D" PstCount "%3Bvar%20posts%3D%5B%5D%3Bvar%20req_params%3D%7B%22owner_id%22%3Aowner_id%2C%22count%22%3ACOUNT%2C%22offset%22%3Aoffset%2C%22v%22%3A%225.78%22%7D%3Bvar%20i%3D0%3Bwhile(i%20%3C%20ITERS)%7Breq_params.offset%3Di*COUNT%2BITERS*COUNT*offset%3Bvar%20items%3DAPI.wall.get(req_params).items%3Bif%20(items.length%20%3D%3D%200)%20%7Breturn%20posts%3B%7Dvar%20ids%3Ditems%40.id%3Bvar%20tmp%3D%7B%7D%3Btmp.ids%3Dids%3Btmp.comments%3Ditems%40.comments%40.count%3Bposts.push(tmp)%3Bi%3Di%2B1%3B%7Dreturn%20posts%3B&param_v=5.78", true)
HTTP.SetRequestHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko)")
HTTP.SetRequestHeader("Pragma", "no-cache")
HTTP.SetRequestHeader("Cache-Control", "no-cache, no-store")
HTTP.SetRequestHeader("If-Modified-Since", "Sat, 1 Jan 2000 00:00:00 GMT")
HTTP.Send()
HTTP.WaitForResponse()
Wall_Info_List := HTTP.ResponseText

If NOT InStr(Wall_Info_List, """ids"":[")  ;если прежний хэш не действует — перелогиниться:
{
   sleep, 5000
   gosub login
   fileappend  login в %a_now%`n, %Dest_Path%\_login.txt, UTF-8
   Return
}

;Обработка вывода execute-процедуры
Wall_Info_List := RegExReplace(Wall_Info_List, "s)(""\w+"":\[)", "`n$1")
Wall_Info_List := RegExReplace(Wall_Info_List, "s)[\][^`n]*`n|\]|\}]", "`n")

Cont := Wall_Info_List, arrA := [], arrC := [] 
Loop, parse, Cont, `n, `r 
{ 
   str := A_LoopField 
   Loop, parse, str, [`,] 
   if A_LoopField != 
   { 
      if InStr(str, "ids") 
      arrA[A_Index] := A_LoopField, LastA := A_Index 
      if InStr(str, "comments") 
      arrC[A_Index] := A_LoopField, LastC := A_Index 
   } 
   if InStr(str, "comments") 
   { 
      num ++ 
      Loop, % LastA 
      if A_Index > 1 
      Wall_Info_List_Out .= arrA[A_Index] "-" arrC[A_Index] "`n" 
      if (LastA != LastC)    ;ПРОВЕРКА 
      Msgbox, 0x1030, , Ошибка в блоке %num%`, строка ~ %A_Index% исходных данных.`n`nКоличество чисел не совпало. 
      arrA := [], arrC := [], LastA :=LastC := str :="" 
   } 
} 

Wall_Info_List_Out1 := Wall_Info_List_Out

If (FirstMode == 1)  ;при первом запуске пропустить
{
   Loop, parse, Wall_Info_List_Out_Prev, `n, `r
      Wall_Info_List_Out := RegExReplace(Wall_Info_List_Out, "m`a)^\n|^\Q" A_LoopField "\E$")
   Wall_Info_List_Out_Uniq := Wall_Info_List_Out

   tooltip Обновление в постах: `n%Wall_Info_List_Out_Uniq%
   sleep 1500

   if (Wall_Info_List_Out_Uniq = "")  ;если перемен пуста
      Return
}

FirstMode = 1

if (Wall_Info_List_Out_Uniq = "")  ;если перемен пуста
   Wall_Info_List_Out_Uniq := Wall_Info_List_Out1

Wall_Info_List_Out_Uniq := RegExReplace(Wall_Info_List_Out_Uniq, "\R+\s*", "`n") ;удал пуст строки
Wall_Info_List_Out_Uniq := RegExReplace(Wall_Info_List_Out_Uniq, "\R$", "") ;удал последн пуст

Wall_Info_List_Out =
Loop, parse, Wall_Info_List_Out_Uniq, `n, `r
{

   RegExMatch(A_LoopField, "s)(\d+)-(\d+)", match)
   PostId := match1
   CmtCount := match2

   If NOT PostId~="\d"
     Continue

   pfile = %Dest_Path%\%OwnerId%_%PostId%.html
   if (NOT FileExist(pfile))
   {
      HTTP.Open("GET", "https://vk.com/wkview.php?act=show&al=1&w=wall" OwnerId "_" PostId "&offset=999999", true)
      HTTP.SetRequestHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko)")
      HTTP.SetRequestHeader("Pragma", "no-cache")
      HTTP.SetRequestHeader("Cache-Control", "no-cache, no-store")
      HTTP.SetRequestHeader("If-Modified-Since", "Sat, 1 Jan 2000 00:00:00 GMT")
      HTTP.Send()
      HTTP.WaitForResponse()
      ResponseText := HTTP.ResponseText

      Gosub, PstProc
      Gosub, NewTitle
      Gosub, htmlcode

      fileappend, %htmlcode%%ResponseText%`n`n`n`n, %Dest_Path%\%OwnerId%_%PostId%.html, UTF-8
      FileCreate = 1
      CmtCountInFile := 0
   }
   Else
   {
      FileCreate = 0
      FileRead, Post_File, %pfile%
      StrReplace(Post_File, "<div id=""post-",, CmtCountInFile) ;подсчёт комментов в файле
   }
   ResponseText =

   if StrLen(CmtCount) > 0
   {
      loop % CmtCount
      {
         if (FileCreate == 0)
         {
            cn := A_Index - 1 + CmtCountInFile - CmtMinus
            tooltip файл сущ----`nВсего коментов: %CmtCount%/%cn%`nPostId: %PostId%
            sleep 900
            If InStr(cn, "-")
               Continue
            if (cn = CmtCount)
               break
            if cn > CmtCount
               break
         }
         if (FileCreate == 1)
         {
            cn := A_Index - 1
            tooltip файл НЕ сущ----`nВсего коментов: %CmtCount%/%cn%`nPostId: %PostId%
         }

         ;--------------------------------------------
         ;ОПРЕДЕЛЕННЫЙ КОММ ПОСТА
         ;--------------------------------------------
         HTTP.Open("POST", "https://vk.com/al_wall.php", true)
         ;HTTP.SetRequestHeader("Cookie", "remixlang=0")   ; имена на русском
         HTTP.SetRequestHeader("Content-Type", "application/x-www-form-urlencoded")
         HTTP.SetRequestHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko)")
         HTTP.SetRequestHeader("Pragma", "no-cache")
         HTTP.SetRequestHeader("Cache-Control", "no-cache, no-store")
         HTTP.SetRequestHeader("If-Modified-Since", "Sat, 1 Jan 2000 00:00:00 GMT")
         HTTP.Send("act=get_replies&al=1&count=1&from=wkview&offset=" cn "&post=" OwnerId "_" PostId "&rev=0")
         HTTP.WaitForResponse()
         ResponseText := HTTP.ResponseText

         RegExMatch(ResponseText, "s)class=""post_link"" href=""[^""]*(_\d+\?reply=\d+"")", match)
         Cmt_Id := match1

         If InStr(Post_File, Cmt_Id)
            Continue

         ResponseText := RegExReplace(ResponseText, "s)^.*?(<div.*?)<!><!json>.*?$", "$1")
         Gosub, CmtProc

         fileappend, %ResponseText%, %Dest_Path%\%OwnerId%_%PostId%.html, UTF-8

         ResponseText =
         match =
         match1 =
         mattch =
         mattch1 =
         NewTitle =
         tSTRING =
         DateTime =
         arrA =
         str =
         Cont =
         Cmt_Id =
         Wall_Info_List =
         Wall_Info_List_Out_Uniq =
         ;Post_File =
         ;!!PostId
         ;!!CmtCount
         cn =
      }
   }
}
Wall_Info_List_Out_Prev := Wall_Info_List_Out1
FileCreate = 0
Return

NewTitle:
   ;захватить не более 100 символов в секции, с границей получаемого текста вне угловых скобок
   RegExMatch(ResponseText, "<div class=""wall_post_text"">(?!</div>)((.(?!</div>)){0,350}.)(?=.*</div>)", match)
   NewTitle := RegExReplace(match1, "<[^>]*$")
   NewTitle := RegExReplace(NewTitle, "<[^>]*>", " ")
   NewTitle := RegExReplace(NewTitle, "  ", " ")
   NewTitle := UnHTM(NewTitle)
return

PstProc:
ResponseText := RegExReplace(ResponseText, "s)<div id=""wl_replies_header"".+?</div>", "")
ResponseText := RegExReplace(ResponseText, "s).*?<!bool><!>(<div.*?</div>)<!><!json>.*", "$1")

ResponseText := RegExReplace(ResponseText, "s)<a([^>]*)base&quot;:&quot;([^>]*)(&quot;,&quot;[^>]*\[&quot;)([^}]*)(&quot;[^>]*)>", "<a$1base&huot;:&huot;$2$3$4$5 href=""$2$4.jpg""><img class=""my"" src=""$2$4.jpg""></a>`n`n`n")
ResponseText := RegExReplace(ResponseText, "s)(<a[^>]* )(style=""[^>]*><img class=""my"")", "$1X$2")
ResponseText := RegExReplace(ResponseText, "s)(<div[^>]* )(style=""[^>]*><a[^>]*><img class=""my"")", "$1X$2")

ResponseText := RegExReplace(ResponseText, "s) href=""(/away[^""]*)""([^>]* title=)""(https?:[^""]*)""", " href=""$3""$2""$3""") ;!!
ResponseText := RegExReplace(ResponseText, "s)aria-label=", "title=") ;!!
ResponseText := RegExReplace(ResponseText, "s)<div class=""ui_actions_menu_icons"".*?</a></div>|<div class=""ui_actions_menu _ui_menu"".*?</a></div>|<div id=""wl_reply_form_wrap"" class=""wl_reply_form_wrap""><div class=""wl_post_reply_form_forbidden"">.*?</div></div>|<button class=""flat_button.*?</button>|<span class=""blind_label""[^>]*>Показать список оценивших</span>|<span class=""blind_label"">Нравится</span>|\s+<span class=""post_like_link _link"">Нравится</span>\R", "")
ResponseText := RegExReplace(ResponseText, "s)<br><a class=""wall_\w+_more"" X?onclick=""hide\(this, domPS\(this\)\); show\(domNS\(this\)\);"">Показать полностью…</a><span style=""display: none"">", "")
ResponseText := RegExReplace(ResponseText, "s)<div[^>]*><div[^>]*>Автор ограничил возможность комментирования</div></div>", "")
ResponseText := RegExReplace(ResponseText, "m`a)^\s+<button class=""flat_button.*?>Вы подписаны</.*?</button>$", "")
ResponseText := RegExReplace(ResponseText, "s)<div id=""wl_replies_header_toggler"".*?$", "</div></div>`r`n</div></div>")
ResponseText := RegExReplace(ResponseText, "s)https://sun\d+-\d+\.userapi\.com/(https://sun\d+-\d+\.userapi\.com/)", "$1")
ResponseText := RegExReplace(ResponseText, "s) (onmouse[a-z]+=|onclick=|data-from-id=)""[^""]*""", " ") ;!!
ResponseText := RegExReplace(ResponseText, "s)=""/", "=""https://vk.com/")
ResponseText := RegExReplace(ResponseText, "s)<div id=""wl_post_actions_wrap"".*\Z", "</div><hr>")
return

CmtProc:
ResponseText := RegExReplace(ResponseText, "s) href=""(/away[^""]*)""([^>]* title=)""(https?:[^""]*)""", " href=""$3""$2""$3""") ;!!

ResponseText := RegExReplace(ResponseText, "s)<a([^>]*)base&quot;:&quot;([^>]*)(&quot;,&quot;[^>]*\[&quot;)([^}]*)(&quot;[^>]*)>", "<a$1base&huot;:&huot;$2$3$4$5 href=""$2$4.jpg""><img class=""my"" src=""$2$4.jpg""></a>`n`n`n")
ResponseText := RegExReplace(ResponseText, "s)(<a[^>]* )(style=""[^>]*><img class=""my"")", "$1X$2")
ResponseText := RegExReplace(ResponseText, "s)(<div[^>]* )(style=""[^>]*><a[^>]*><img class=""my"")", "$1X$2")

ResponseText := RegExReplace(ResponseText, "s)aria-label=", "title=") ;!!
ResponseText := RegExReplace(ResponseText, "s)data-from-id=""(\d+)"">", "data-from-id=""$1"">id$1|")

;ResponseText := RegExReplace(ResponseText, "s) rid=""(\d+)(""[^>]*>)", " rid=""$1$2to$1|")
ResponseText := RegExReplace(ResponseText, "s)</a> (ответил.?) <a href=""([^""]*)""[^>]*'(-?\d+_\d+)', event\)"" rid=""(\d+)""[^>]*>", "</a> <a class=""reply_to"" href=""#post$3"">$1</a> <a class=""reply_to"" href=""$2"">to$4|")
ResponseText := RegExReplace(ResponseText, "s) <div class=""reply_link_wrap""> <a[^>]*>Ответить</a>\R</div>", "")
ResponseText := RegExReplace(ResponseText, "s)<br><a class=""wall_\w+_more"" X?onclick=""hide\(this, domPS\(this\)\); show\(domNS\(this\)\);"">Показать полностью…</a><span style=""display: none"">", "")
ResponseText := RegExReplace(ResponseText, "s)<span class=""blind_label""[^>]*>Показать список оценивших</span>\s?|\s?<span class=""blind_label""[^>]*>Нравится</span>", "")
ResponseText := RegExReplace(ResponseText, "s)https://sun\d+-\d+\.userapi\.com/(https://sun\d+-\d+\.userapi\.com/)", "$1")

;ПРАВКА "минут назад" и "только что"
If RegexMatch(ResponseText, "s)\s?time=""(\d+)"">(только.+?|.+?назад)</span>", mattch)
{
   DateTime := FormatSeconds(mattch1)
   ResponseText := RegExReplace(ResponseText, "s)\s?time=""(\d+)"">(.+?)</span>", " time=""" mattch1 """>" DateTime "</span>")
}

;ПРАВКА "сегодня в"
If RegexMatch(ResponseText, "s)<span class=""rel_date"">сегодня в\s", mattch)
{
   FormatTime, DateTime,, LongDate
   StringReplace, DateTime, DateTime, %A_Space%г., `,, All
   ResponseText := RegExReplace(ResponseText, "s)<span class=""rel_date"">сегодня в", "<span class=""rel_date"">" DateTime)
}

;ПРАВКА "вчера в"
If RegexMatch(ResponseText, "s)<span class=""rel_date"">вчера в\s", mattch)
{
   FormatTime, DateTime,, LongDate
   StringReplace, DateTime, DateTime, %A_Space%г., `,, All
   ResponseText := RegExReplace(ResponseText, "s)<span class=""rel_date"">вчера в", "<span class=""rel_date"">[" DateTime "] вчера в")
}

ResponseText := RegExReplace(ResponseText, "s) (onmouse[a-z]+=|onclick=|data-from-id=)""[^""]*""", " ") ;!!
ResponseText := RegExReplace(ResponseText, "s)=""/", "=""https://vk.com/")
ResponseText := RegExReplace(ResponseText, "s)<div class=""like_wrap .*?</div> <div class=""reply_date"">", " <div class=""reply_date"">")
return

login:
SplashImage,, y-2 x200 w40 h14 M C11 ZH0 ZW0 ZX1 ZY1 B0 CT000000 CWffff00 FM8 FS6 WM600 WS400,, login
;--------------------------------------------
;Авторизация:
;--------------------------------------------
;email := "*****************"
;password := "*****************"
;HTTP := ComObjCreate("WinHTTP.WinHTTPRequest.5.1")
HTTP.Open("GET", "https://vk.com/", true)
HTTP.SetRequestHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko)")
HTTP.SetRequestHeader("Pragma", "no-cache")
HTTP.SetRequestHeader("Cache-Control", "no-cache, no-store")
HTTP.SetRequestHeader("If-Modified-Since", "Sat, 1 Jan 2000 00:00:00 GMT")
HTTP.Send()
HTTP.WaitForResponse()
RegexMatch(HTTP.ResponseText, "s)name=""ip_h"" value=""(.+?)"".+?name=""lg_h"" value=""(.+?)""", match)
PostData := "act=login&role=al_frame&expire=&recaptcha=&captcha_sid=&captcha_key=&_origin=https`%3A`%2F`%2Fvk.com&ip_h=" match1 "&lg_h=" match2 "&email=" email "&pass=" password

HTTP.Open("POST", "https://login.vk.com/?act=login", true)
HTTP.SetRequestHeader("Content-Type", "application/x-www-form-urlencoded")
HTTP.SetRequestHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko)")
HTTP.SetRequestHeader("Pragma", "no-cache")
HTTP.SetRequestHeader("Cache-Control", "no-cache, no-store")
HTTP.SetRequestHeader("If-Modified-Since", "Sat, 1 Jan 2000 00:00:00 GMT")
HTTP.Send(PostData)
HTTP.WaitForResponse()

sleep, 1000

;третья — для получения хэша:
HTTP.Open("GET", "https://vk.com/dev/execute", true)
HTTP.SetRequestHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko)")
HTTP.SetRequestHeader("Pragma", "no-cache")
HTTP.SetRequestHeader("Cache-Control", "no-cache, no-store")
HTTP.SetRequestHeader("If-Modified-Since", "Sat, 1 Jan 2000 00:00:00 GMT")
HTTP.Send()
HTTP.WaitForResponse()
RegexMatch(HTTP.ResponseText, "s)Dev.methodRun\('([^']*)'", match)
StringReplace, match1, match1, :, `%3A, All
PostHash := match1
ResponseText =
;--------------------------------------------
SplashImage, OFF
Return

htmlcode:
htmlcode=
(
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ru" lang="ru">
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<title>%NewTitle%</title>
<link type="text/css" rel="stylesheet" href="css\common.css"></link>
<link type="text/css" rel="stylesheet" href="css\fonts-cnt.css"></link>
<link type="text/css" rel="stylesheet" href="css\page.css"></link>
<link type="text/css" rel="stylesheet" href="css\post.css"></link>
<link type="text/css" rel="stylesheet" href="css\ui-common.css"></link>
<link type="text/css" rel="stylesheet" href="css\uncommon.css"></link>
<link type="text/css" rel="stylesheet" href="css\wall.css"></link>
<link type="text/css" rel="stylesheet" href="css\wide-dd.css"></link>
<Xbase href="https://vk.com/">
</head>
<body style="background-color:#ffffff!important;">

<div class="wall_wrap clear_fix">
  <div class="big_wall">
    <div class="wall_module">`n`n`n`n
)
Return

FormatSeconds(TimeInSec)
{
   TimeInSec := TimeInSec, UTCOffset_sec :="", DateTime := 19700101   ; первое января 1970 года 
   DateTime += TimeInSec, sec
   UTCOffset_sec -= A_NowUTC, sec ; учитываем часовой пояс 
   DateTime += UTCOffset_sec, sec 
   FormatTime, DateTime1, %DateTime%, LongDate
   FormatTime, DateTime2, %DateTime%, H:mm ;:ss
   StringReplace, DateTime1, DateTime1, %A_Space%г., , All
   DateTime = %DateTime1%`, %DateTime2%
   return DateTime
}

UnHTM(HTM) { ; Remove HTML formatting / Convert to ordinary text     by SKAN 19-Nov-2009
   Static HT     ; Forum Topic: www.autohotkey.com/forum/topic51342.html
   IfEqual,HT,,   SetEnv,HT, % "&aacuteá&acircâ&acute´&aeligæ&agraveà&amp&aringå&atildeã&au"
 . "mlä&bdquo„&brvbar¦&bull•&ccedilç&cedil¸&cent¢&circˆ&copy©&curren¤&dagger†&dagger‡&deg"
 . "°&divide÷&eacuteé&ecircê&egraveè&ethð&eumlë&euro€&fnofƒ&frac12½&frac14¼&frac34¾&gt>&h"
 . "ellip…&iacuteí&icircî&iexcl¡&igraveì&iquest¿&iumlï&laquo«&ldquo“&lsaquo‹&lsquo‘&lt<&m"
 . "acr¯&mdash—&microµ&middot·&nbsp &ndash–&not¬&ntildeñ&oacuteó&ocircô&oeligœ&ograveò&or"
 . "dfª&ordmº&oslashø&otildeõ&oumlö&para¶&permil‰&plusmn±&pound£&quot""&raquo»&rdquo”&reg"
 . "®&rsaquo›&rsquo’&sbquo‚&scaronš&sect§&shy&sup1¹&sup2²&sup3³&szligß&thornþ&tilde˜&tim"
 . "es×&trade™&uacuteú&ucircû&ugraveù&uml¨&uumlü&yacuteý&yen¥&yumlÿ"

   HTM := RegExReplace( HTM,"&amp;(\w+;)", "&$1" )   ;!! для обработки &amp;lt; 
   HTM := RegExReplace( HTM,"&amp;(#\d+;)", "&$1" )  ;!! для обработки &amp;#60;

   TXT := RegExReplace( HTM,"<[^>]+>", " " )               ; Remove all tags between  "<" and ">"
   Loop, Parse, TXT, &`;                              ; Create a list of special characters
      L := "&" A_LoopField ";", R .= (!(A_Index&1)) ? ( (!InStr(R,L,1)) ? L:"" ) : ""
   StringTrimRight, R, R, 1
   Loop, Parse, R , `;                                ; Parse Special Characters
      If F := InStr( HT, A_LoopField )                  ; Lookup HT Data
         StringReplace, TXT,TXT, %A_LoopField%`;, % SubStr( HT,F+StrLen(A_LoopField), 1 ), All
   Else If ( SubStr( A_LoopField,2,1)="#" )
      StringReplace, TXT, TXT, %A_LoopField%`;, % Chr(SubStr(A_LoopField,3)), All

   TXT := RegExReplace(TXT, " +", " ")       ;!! множественные пробелы на один
   TXT := RegExReplace(TXT, "m)(*UCP)(?<=\s|^)""(?=\w)", "«")      ;!! кавычки
   TXT := RegExReplace(TXT, "m)(*UCP)(?<=[^\s""])""(?=\W|$)", "»") ;!! кавычки

;!! кавычки
loop, 10
{
      TXT := RegExReplace(TXT, "«([^«»]*)«([^«»]*)»", "«$1«$2»")
      TXT := RegExReplace(TXT, " ""([\s?\)\]\}\,\.\:\;\!\?…""'])", "n~b~s~p""$1")
      TXT := RegExReplace(TXT, "((^|[\s]|&nbsp;)([\(\[\{""]|\d+)*)([""])(\S([^""]*?|.*?\x20[""]\x20.*?)\S|[^""\s])[""]((\d+|[\)\]\}\,\.\:\;\!\?…""])*($|[\s]|&nbsp;))", "$1«$5»$7")
      TXT := RegExReplace(TXT, "n~b~s~p", " ")
      TXT := RegExReplace(TXT, "«([^«»]*)«([^«»]*)»", "«$1„$2“")
}

   Return RegExReplace( TXT, "(^\s*|\s*$)")            ; Remove leading/trailing white spaces
}
Post's attachments

WallMonitor.rar 65.23 kb, 2 downloads since 2018-06-25 

You don't have the permssions to download the attachments of this post.