|
|
||
По состоянию на 19 октября 2024 года. |
См. также:
? Как узнать популярность произведения в "Самиздате" ("где/что смотреть" - основное, вкратце).
~ Рейтинг siTopTexts "Произведения" ("Самиздат", самое популярное за 30 дней).
+ Рейтинг siTopAuthors "Авторы" ("Самиздат" намедни).
* История-Р, "прикопанное" прошлое (ссылки на подборки старых рейтингов по полугодиям).
Disclaimer: Я не несу никакой ответственности за последствия касаемо. Далеко не факт, что у вас получится то, на что вы рассчитываете, если станете использовать нижеприведённое. Пользуйтесь оным исключительно на свой страх и риск. ;-|
… В любом случае, на вопросы касаемо — отвечу, если смогу…
/\ /\
·--·--·--·
\/
/\
·--·
Исходные тексты скриптов задач "siTop…"
(от: 2024.10.19)
NB. В публикации приведен комплект оригинальных исходных текстов скриптов, не подвергавшихся какой-либо предварительной правке (за исключением преобразования: «OEM→ANSI» кириллицы в скриптах CMD). Этот комплект работает в ОС WindowsXP-x86-RUS+SP3+SRK, использует некоторые бесплатные утилиты (порт из UNIX) и ориентирован на полуавтоматическое применение в моей рабочей среде. Влад.
Перечень задействованных скриптов:
- Задача: «Разделы "Самиздата"»
- Задание: "0form" — выявление скрытых разделов /"потеряшки"/
- Задание: "1hidn" — вычленение активных "потеряшек"
- Задание: "aHits" — обновление локальной копии рейтинга "по количеству посетителей"
- Задача: «Рейтинг siTopTexts "Произведения"»
- Задание: "bStat" — обновление локальных копий статистик топовых разделов, сборка шорт-листа к siTopTexts
- Задание: "cChkH" — контроль даты "Размещен" произведений в шорт-листе siTopTexts
- Задание: "dText" — сбор сведений о произведениях (объём, оценки, отклики, …)
- Задание: "fHtml" — оформление таблиц рейтинга siTopTexts
- Задача: «Рейтинг siTopAuthors "Авторы"»
- Задание: "gAuth" — составление и наполнение шорт-листа siTopAuthors
- Задание: "iNetR" — оформление таблиц siTopAuthors
- Задача: «Оценка доступа к доменам "Самиздата", ожидание обновления статистик разделов »
- Задание: "zChk.cmd" — обнаружение факта "«сегодня» обновлено"
- Универсальный скрипт "качалка" для скачивания страниц "Самиздата"
Имя файла скрипта: "0form.awk" V-текст скрипта-V- - - - - - - - - BEGIN{ # 0form.awk - вычленение a_Id отсутствующих в aHits разделов # 2023.07.08, nvv, creation на входе - страницы произведений по 18 формам СИ # 2023.07.13, nvv, turning # 2024.05.23, nvv, вых.список упорядочен НЕ по числу текстов у автора, а по алфавиту # 2024.09.09, nvv, в шапку добавлен отчёт по изменению сосотава: # на выходе - список id разделов, ОТСУТСТВУЮЩИХ в aHits # test=1 errS="no inPut files" jDat=strftime("%Y.%m.%d") if(ARGV[1]=="")exit # защита от случайного пуска for(str2 in ENVIRON){ # ! регистр букв в имени переменной может быть любой if(tolower(str2)=="fhit")fHit=ENVIRON[str2] # опорный aHits список if(tolower(str2)=="jlst")jLst=ENVIRON[str2] # место для итогового списка } if(fHit==""){ # если вызов НЕ из CMD, aHits ищем сами if(test){ str0="U:\\Jobs\\_siTop.#" while((getline line<str0)>0){ # ищем последнюю запись успешного скачивания этого списка # ;1A hits 5:xNam 457:xNum 104555:xPas 2023.06.15:hDat 505501:hMax 1051:hPag 1111:dnLd 0.08~ratW 2023.06.16:done 05:22:08~wrks 14:47 if(match(line,/^;1A .+ 20([\.0-9]{8}):hDat /,arr0))fHit=arr0[1] } close(str0) if(fHit==""){ errS="] NO *.aHits found in "str0 exit } jLst="_lost.addF" fHit="U:\\Jobs\\20"fHit".aHits" # строим полное имя нужного списка }else{ errS="NO fHit envVar" exit } } # ; 18:form 7934:pags 1584692:txts 105335:auth 1928:hidn 2024.09.06:done # ;txTot id_P # 2 2/2021mart while((getline line<jLst)>0){ split(line,aj) if(match(aj[1],/^[0-9]+$/)){ aOld[aj[2]]=aj[1] # }else if(match(line,/^; 18:form .+ ([^ ]+):done/,aj)){ oldD=aj[1] } } close(jLst) # всё/не_всё, - старый список тогось # # 201661 21 846 3 k/kadawr "Кадавр" "no•comments" # # ] hitP numP sizK sizN id_P "namP" "moto" # # 1 2 3 4 5 6 7 while((getline line<fHit)>0){ # fHit: like 2020.03.01.aHits split(line,aj) if(match(aj[1],/^[0-9]+$/)){ # в опоре "потеряшки" неуместны if(aj[2])aHit[ aj[5]]=line # aj[1] == 201661 aj[5] == k/kadawr p_id }else aHre[++nHre]=line j0++ } close(fHit) # всё/не_всё, - старый список тогось if(99999-j0>0){ errS=j0" LOW aHits.recs" exit } errS="" nCam=0 nGon=0 } { if(FNR==1){ pagF++ # учитываем страницы форм if(pagF%10){printf(".")}else{printf(":")} # оживляж... if(!(pagF%100))printf("%5s\n",pagF) } if(match($0,/<DL><DT><li>.*<a href=\/([^>]+)><font color=#555555>([^<]*)</,aj)){ aFrm[aj[1]]++ # учитываем id_P и тексты в них } } function mkSec(dat){ # дата "гггг.мм.дд" -> UNIX-секунды с 1970.01.01 return(mktime(\ substr(dat,1,4)" "substr(dat,6,2)" "substr(dat,9,2)" 00 00 00"\ )) } END{ if(errS!=""){ # проблем-с... print("] "errS) exit -1 } printf("%5s\n",pagF) txtF=0 autF=0 for(j0 in aFrm){ if(!(j0 in aHit)){ aNot[++nNot]=j0 if(j0 in aOld)delete aOld[j0] else nCam++ } txtF=txtF+aFrm[j0] autF++ } nGon=length(aOld) j3="; 18:form "pagF":pags "txtF":txts "autF":auth "nNot":hidn "jDat":done" asort(aNot) print(j3) > jLst print(aHre[nHre]) > jLst j3=(mkSec(jDat)-mkSec(oldD))/86400 j3=oldD":preD "j3".dGap "nCam".came "nGon".gone" print(";txTot id_P",j3) > jLst for(j0=1;j0<=nNot;j0++)printf("%5s %s\n",aFrm[aNot[j0]],aNot[j0]) > jLst # if(!(j0 in aHit))aNot[++nNot]=sprintf("%5s %s",aFrm[j0],j0) print(j3) }
Имя файла скрипта: "0form.cmd" V-текст скрипта-V- - - - - - - - - @if not defined pMod @echo off set nJob=addF echo %date% %time:~0,8% %nJob% Begs :: 1hidn.cmd - составление /по спискам форм/ списка _lost.addF разделов, отсутствующих в aHits- :: 0. для старта нужнен список aHits (хиты) :: 1. обновляется страницы списков "формы" 01.0001.form.htm .. 18.NNNN.form.htm :: основной и резервный URL Самиздата (желательно работать с резервом) if NOT defined siUrl if exist \siUrl.budclub set siUrl=budclub.ru if NOT defined siUrl set siUrl=samlib.ru :: 2024.10.19, nvv, +выдача в протокол изменений: "K.dGap L.came M.gone" :: история изменений в подвале скрипта! :: основные сеты и прочая подготовка к работе... set jDat=%date% set errInf= :: wrks - общее время работы процесса (пуск общего таймера) for /F %%A in ('gawk.exe "BEGIN{print(systime());exit}"') do set wrks=%%A :: aScr - скрипт вычленения потеряшек из страниц списков произведений по формам set aScr=%~dpn0.awk if NOT exist %aScr% set errInf=NO %aScr% found & goto errExit :: wDir - общее рабочее место set wDir=%~d0\Jobs :: jDir - место для оперативных файлов set jDir=%wDir%\_%nJob% :: zDir - общий подкаталог для посуточных подкаталогов с итоговыми списками set zDir=%~d0\Stor\wOld\%jDat% :: jLst - конечный результат процесса в формате *.mig.bStat set jLst=%wDir%\_lost.%nJob% :: jRpt - общий отчёт с итоговыми сводками процессов set jRpt=%wDir%\_siTop.# :: fil1 - первая страница первой формы set fil1=%jDir%\01.0001.form.htm :: fOld дата файла наличного рейтинга *.aHits set fOld= :: dnLd - счётчик скачанного ([пере]запустим "таймер" ratW) set dnLd=0 :: wGetSiz - размер скачанного файла (default 1b минимум) set wGetSiz=1 :: проверить/создать нужные структуры для работы (оперативные площадки) if NOT exist %jDir%\*.* ( mkDir %jDir% if errorLevel 1 set errInf=fail mkDir %jDir% & goto errExit ) if NOT exist %zDir%\*.* ( mkDir %zDir% if errorLevel 1 set errInf=fail mkDir %zDir% & goto errExit ) :: проверка наличия,.. для корректной работы нужен aHits /рейтинг по хитам/ set fHit= for %%A in (%wDir%\20??.??.??.aHits) do set fHit=%%A if NOT defined fHit set errInf=NO *.aHits found, no job 2do & goto errExit :: ок, работать можно, смотрим наше хозяйство сегодняшнего нет... побежали дальше :: htm jLst :: non any качаем :: old any чистим+качаем :: cur non/older качаем :: cur newer -- нечего делать, всё уже if NOT exist %jDir%\*.form.htm goto chkDl :: смотрим дату создания 01.0001.form.htm set oDat= for %%A in (%fil1%) do set oDat=%%~tA :: если НЕ сегодняшняя, надо чистить и качать if NOT %jDat%. == %oDat:~0,10%. goto doJob :: смотрим U:\Jobs\_lost.addF /список годных "потеряшек"/ берём дату в нём set tmp0= for %%A in (%jLst%) do set tmp0=%%~tA :: итог свежий или нет? if NOT defined tmp0 goto chkDl :: в накопителе файлы *.html свежее, чем итог _lost.addF if "%oDat%" GEQ "%tmp0%" ( goto chkDl ) else ( echo == all is done today already goto :eof ) :doJob чистим старое в накопителе echo erasing ~7.7k old pages of 18 form... if exist %jDir%\*.htm ( erase /F /Q %jDir%\*.htm if errorLevel 1 set errInf=fail erase %jDir%\*.htm & goto errExit ) :chkDl скачивание недостающего; ratW - темп скачивания for /F %%A in ('gawk.exe "BEGIN{print(systime());exit}"') do set ratW=%%A :: собственно перебор/запуск_скачивания echo ? dnLd %nJob% fresh pages... for /L %%A in ( 1, 1, 18 ) do if NOT defined errInf call :gainThis %%A if defined errInf goto nExit :: вычислим темп скачивания ratW if %dnLd% == 0 (set ratW=0) else ( for /F %%A in ( ' gawk.exe "BEGIN{print(sprintf(\"%%3.2f\",(systime()-%ratW%)/%dnLd%));exit}" ' ) do set ratW=%%A ) echo. echo = %dnLd%:pages 18:forms %ratW%:ratW scaning... :: формы у нас, соберём из них список скрытых id_P gawk.exe -f %aScr% %jDir%\*.form.htm if NOT %errorLevel% == 0 set errInf=%aScr% problem in %jDir%\*.form.htm & goto errExit rem ; 18:form 7687:pags 1535762.txts 104310:auth 1948:hidn 2023.06.28:done for /F "tokens=1-9,*" %%A in ( ' gawk.exe "{if(match($2,/^18:form$/))print($3,$4,$5,$6);exit}" %jLst% ' ) do ( set pags=%%A set txts=%%B set auth=%%C set hidn=%%D ) :: почистим, вычленив цифры set pags=%pags:~0,-5% set txts=%txts:~0,-5% set auth=%auth:~0,-5% set hidn=%hidn:~0,-5% rem ;txTot id_P 2024.09.18:preD 10.dGap 2.came 5.gone for /F "tokens=1-9,*" %%A in ( ' gawk.exe "{if(NR==3){print($4,$5,$6);exit}}" %jLst% ' ) do ( set dGap=%%A set came=%%B set gone=%%C ) :: почистим, вычленив цифры set dGap=%dGap:~0,-5% set came=%came:~0,-5% set gone=%gone:~0,-5% :: остановим "таймер", : преобразуем секунды в время работы (в обычном формате "чч:мм:сс") for /F %%A in ('gawk.exe "BEGIN{print(strftime(\"%%H:%%M:%%S\",systime()-%wrks%+46800));exit}"') do set wrks=%%A :: ;0F addF 1943:hidn 7338:FdlS 1.21~FrwS 2023.07.02:done 02:29:22~wrks 16:38 set tmp0=;0F form ^ %pags%:pags ^ %auth%:auth ^ %hidn%:hidn ^ %dGap%:dGap ^ %came%:came ^ %gone%:gone ^ %ratW%~ratW ^ %jDat%:done ^ %wrks%~wrks ^ %time:~0,5% echo %tmp0% >> %jLst% echo %tmp0% >> %jRpt% rem echo = Ok %hidn%.hidn %dnLd%:FdlS %ratW%~FrwS :: скинем результаты в хранилище copy /y /b %jLst% %zDir%\ > nul if errorLevel 1 set errInf=fail copy %jLst% TO %zDir% & goto errExit :: подудим где нада "готово-с!" set itog=%jLst% :nExit if defined errInf if NOT defined errF echo ! %errInf% echo %date% %time:~0,8% %~nx0 Ends goto :eof rem gawk.exe -f %aScr% %jDir%\*.htm rem goto :eof :gainThis %%Z скачивание всех страниц указанного типа set typB=0%1 set typB=%typB:~-2% :: wReq - общая часть адреса страниц указанного рейтинга set wReq=%siUrl%/type/index_type_%1- call :reqSI 1 if defined errInf goto :eof :: выясним pMax /общее число страниц рейтинга/ set pMax= for /F %%J in ( ' gawk.exe "{if(match($0,/<\/td><\/tr><\/table><center><b>.+\.shtml>([0-9]+)<\/a> *<\/center>/,a)){print(a[1]);exit}}" %wFil% ' ) do set pMax=%%J if NOT defined pMax ( set errInf=NO pMax in %wFil% goto errExit ) gawk.exe "BEGIN{printf(\" next.%pMax% ones \n.\");exit}" for /L %%J in (2,1,%pMax%) do if NOT defined errInf call :reqSI %%J if defined errInf goto :eof if NOT "%pNum:~-2%" == "00" echo. rem echo.= %typB%.%pNum% pages gawk.exe "BEGIN{printf(\"= %typB%.%pNum% pages\");exit}" goto :eof :reqSI %%J притаскивает type в кодировке cp1251 (win) set wUrl=%wReq%%1.shtml set pNum=000%1 set tmp0= %1 :: pNum - 4-х значное число с лидирующими нулями (для красивой сортировки пронумерованных страниц рейтинга) set pNum=%pNum:~-4% set tmp0=%tmp0:~0,2% :: wFil - конечный локальный файл для скачиваемого set wFil=%jDir%\%typB%.%pNum%.form.htm if %pNum:~-1% == 0 (set mark=%pNum:~-2,1%) else (set mark=.) :: оживляж, если уже есть if exist %wFil% ( if NOT %pNum:~-1% == 0 (set mark=~) ) :: первая странимца очередного списка по форме нужна для выяснения числа страниц этой формы if %1 == 1 goto doDl gawk.exe "BEGIN{printf(\"%mark%\");exit}" if NOT "%pNum:~-2%" == "00" goto doDl echo. = %pNum:~0,2% %time:~0,8% :doDl if exist %wFil% goto :eof call wGetUrl2fil.cmd %wUrl% %wFil% :: проблема? if %wGetErr% == 1 set errInf=no %wUrl% if %wGetErr% == 3 set errInf=no web{SI} :errExit реакция на проблему: в пакете - выход if defined pMod goto :eof :: автономно - на экран + прекращение работы echo %errInf% exit :: 2023.06.20, nvv, сознано на основе aHits.cmd от 2023.05.30 :: 2023.07.10, nvv, turning... :: 2024.03.03, nvv, исправлена реакция на проблемы запуска /NO z!!!.!!!/ :: 2024.03.10, nvv, minor cosmetics :: 2024.03.24, nvv, запрос для: обновления старого ИЛИ перестройки ЗАНОВО сегодняшнего :: 2024.05.23, nvv, вых.список упорядочен НЕ по числу текстов у автора, а по алфавиту :: 2024.08.12, nvv, вместо вопроса или работа, или выход по "уже есть"
Имя файла скрипта: "1hidn.awk" V-текст скрипта-V- - - - - - - - - BEGIN{ # 0addS.awk scan+select *.stat.htm for addition 2 top SI stats # 2023.06.26, nvv, creation на основе bStat.awk 2023.06.22 # 2024.03.03, nvv, last upDates # 2024.06.03, nvv, п/п pack -> pack4cmd # 2024.09.15, nvv, отключено условие "datJ == maxD" # ; stat 1939:allS 824:good 2023.07.19:dEnd 2023.07.23:done # ; datS_timS.1 datJ.2 hitP.3 id_P.4 "namP".5 "moto".6 id_F.7 # 2023.07.20_01:54:05 2023.07.19 9073 n/neon13 "Neon13" "Авторский" n~neon13 # у ГОДНЫХ скрытых разделов: # - в порядке шапка, # + hitP >0 - хиты за 12мес. # X + datJ == maxD - т.е. статистика обновлена к расчёту # id_P == n/neon13 # ~ прочие данные носят справочный характер /для наблюдателя/ # на выходе: # allS - число не нулевых файлов *.stat.htm # good - число годных скрытых разделов для включения в aHits # dEnd - граница расчёта nMig=0 # число годных к расчёту разделов-потеряшек maxD="----.--.--" # верзняя граница интервала дат расчёта errS="NO file" if(ARGV[1]=="")exit # защита от случайного пуска # объявим массивыы для общего использования в подпрограммах split("",aSel) # в ячейках статистики: url,title,hits:all,12mon,mon0..monC-11,day0..day0-61 split("",aMig) # список timeStamp's статистик split("",aj) # рабочий массив for(str2 in ENVIRON){ # ! регистр букв в имени переменной может быть любой str1=tolower(str2) # Temp и temp - РАЗНЫЕ имена для gAwk... if(str1=="wdir")wDir=ENVIRON[str2]"\\" # место для всех ВЫХ.списков } # if((wDir=="")&&!test){ # errS="NO wDir envVar" # exit # } # массив имён месяцев для преобразования их в числа с лидирующим нулём 01..12 mNum["Jan"]="01" # .1 January . Jan. 31 . winter wint mNum["Feb"]="02" # .2 February .Feb. 28/29 mNum["Mar"]="03" # .3 March . . Mar. 31 . spring sprn mNum["Apr"]="04" # .4 April . . Apr. 30 mNum["May"]="05" # .5 May . . . May. 31 mNum["Jun"]="06" # .6 June . . .Jun. 30 . summer summ mNum["Jul"]="07" # .7 July . . .Jul. 31 mNum["Aug"]="08" # .8 August . .Aug. 31 mNum["Sep"]="09" # .9 September Sep. 30 . autumn autm mNum["Oct"]="10" # 10 October . Oct. 31 mNum["Nov"]="11" # 11 November .Nov. 30 mNum["Dec"]="12" # 12 December .Dec. 31 . winter wint errS="" tIni=systime() } # ; upDat_datS 1-st_day numS xDel/=Keep hitP numP hitT id_P id_T # ; 0000.00.00-_bad_file_ 2 0.0% x ~ ~ ~ ~ ~ # ; 2024.07.31-2024.07.30 1 0.0% x ~ ~ ~ ~ ~ # ; 2024.08.01-2024.07.31 1 0.0% x ~ ~ ~ ~ ~ # ; 2024.08.15-2024.08.14 1 0.0% x ~ ~ ~ ~ ~ # ; 2024.08.17-2024.08.16 1 0.0% x ~ ~ ~ ~ ~ # ; 2024.08.19-2024.08.18 3 0.0% x ~ ~ ~ ~ ~ # ; 2024.08.20-2024.08.19 1 0.0% x ~ ~ ~ ~ ~ # ; 2024.08.21-2024.08.20 1 0.0% x ~ ~ ~ ~ ~ # ; 2024.08.25-2024.08.24 7 0.0% x ~ ~ ~ ~ ~ # ; 2024.08.26-2024.08.25 15 0.0% x ~ ~ ~ ~ ~ # ; 2024.08.27-2024.08.26 11 0.0% x ~ ~ ~ ~ ~ # ; 2024.08.28-2024.08.27 14 0.0% x ~ ~ ~ ~ ~ # ; 2024.08.29-2024.08.28 27 0.1% x ~ ~ ~ ~ ~ # ; 2024.08.30-2024.08.29 60 0.2% x ~ ~ ~ ~ ~ # ; 2024.08.31-2024.08.30 117 0.4% x ~ ~ ~ ~ ~ # ; 2024.09.01-2024.08.31 121 0.4% x ~ ~ ~ ~ ~ # ; 2024.09.02-2024.09.01 109 0.4% x ~ ~ ~ ~ ~ # ; 2024.09.03-2024.09.02 192 0.6% x ~ ~ ~ ~ ~ # ; 2024.09.04-2024.09.03 275 0.9% x ~ ~ ~ ~ ~ # ; 2024.09.05-2024.09.04 663 2.2% x ~ ~ ~ ~ ~ # ; 2024.09.06-2024.09.05 3697 12.2% x ~ ~ ~ ~ ~ # ; 2024.09.07-2024.09.06 4575 15.1% x 374 20256 286 w/wolkowa_natalxja_stepanowna kosturiaballadadocx # ; 2024.09.08-2024.09.07 20457 67.4% x 434577 1 43816 r/raba_b_i molitva-112 function mkLn() { # if(hitP-9>0){ if(hitP+0){ aMig[++nMig]=datS"_"timS" "datJ sprintf("%7s %s %s %s %s",hitP,id_P,namP,moto,fNam) if(maxD<datJ)maxD=datJ dGap=datS"-"datJ aDat[dGap]++ if(aHit[dGap]-hitP<0)aHit[dGap]=hitP numS++ } } { # // -=- основной блок скрипта begs if(FNR==1){ # секция завершения работ с одним файлом и подготовки к работе со следущим if(NR!=1)mkLn() # оценка данных обработанной статистики, отбор годных step=0 # 0-владелец, 1-дата обновления, 2-id раздела, 3-разбор строк таблиц статистики fNam=split(FILENAME,aj,"\\") # NEW/NEXT входной файл as-is (с полным путём) fNam=split(aj[fNam],aj,".") # файл: чистое nam.ext (like "0~0.stat.htm") fNam=aj[1] # fNam чистое имя (like "0~0" in "0~0.stat.htm") hitP=0 # выясняется в stat id_P=substr(fNam,1,1)"/"substr(fNam,3) # - "" -- "" -- "" - namP="\"\"" # - "" -- "" -- "" - moto="\"\"" # - "" -- "" -- "" - inTab=0 # сначала - мы НЕ "в таблице" numT=0 # счётчик таблиц в файле статистики numR=0 # счётчик строк в текущей таблице selN=0 # счётчик ячеекк в строке таблицы fNum++ if(fNum%100==0) print(sprintf(": %4s",fNum/100)) else if(fNum%10)printf(".") else printf(":") # оживляж... } gsub(/( )+|\xA0+|[\0-\31]+/," ",$0) # цепочки " " и прочих "пробелов" -> " " (пробел) if(step==0) { # ищем (для контроля) ФИО автора # <h3>Статистика раздела "<a href=./>Влад</a>":</h3> if (match($0,/<h3>Статистика раздела \"<a href=\.\/>(.*)<\/a>\":<\/h3>/,aj)) { if(aj[1]==""){ # errS="] step."step" (NO nick in: " fNam " )" nextfile }else namP=pack4cmd(aj[1]) step=5 # проверка ОК } }else if(step==5){ # вычленеие даты обновления статистики # <center><h2>Журнал "Самиздат": Живопись</h2> if (match($0,/<center><h2>Журнал \"Самиздат\": (.*)<\/h2>/,aj)) { moto=pack4cmd(aj[1]) step=1 # проверка ОК } }else if(step==1){ # вычленеие даты обновления статистики if(match($0,\ /<li><i>Статистика рассчитывается .+\. \(.+ (...) +([0-9]+) (..:..:..) (20[0-9][0-9])\)<\/i>/\ ,aj)){ if(length(aj[2])==1) aj[2]="0"aj[2] # причешем первые дни месяца "1" -> "01" ticS=mktime(aj[4]" "mNum[aj[1]]" "aj[2]" 12 00 00") # тики на 12 часов даты статистики datS=aj[4]"."mNum[aj[1]]"."aj[2] # дата обновления статистики timS=aj[3] # время обновления статистики step++ # дату статистики оптичили } }else if(step==2){ # ищем authID (!должен быть и совпадать с префиксом имени файла) # [<a href=http://top.mail.ru/pages?id=77427&period=0&date=2018-10-02&filter_type=0 # &filter=n/nosow_w_w&pp=20&gender=0&agegroup=0>по дням</a>] if (match($0,/\[<a href=http.+&filter=([0-9a-z]\/[\-0-9a-z_]+)&pp=.+>по дням<\/a>]/,aj)) { if(id_P!=aj[1]){ # это ПОЛНЫЙ криминал!# errS="] step."step" ("aj[1]" != fNam:"fNam")" nextfile } step++ # проверка ОК } }else if(step==3){ # таблицы статистики, просмотр строк, сборка данных в ячейках if($0=="<!--------- Подножие ------------------------------->"){ # разбор закончен step++ nextfile } if(inTab){ # Мы ВНУТРИ таблицы, собираем строки таблицы с хитами текстов buf0=buf0" "$0 # gain inpLines to buf0, then check contents while((match(buf0,/<tr ?[^>]*>/))||(int0=index(buf0,"</tr"))){ # seek <tr .. </tr for tabRow if(RSTART){ # new/next line begs numR++ # счётчик строк buf0=substr(buf0,RSTART+RLENGTH) # del всё до начала строки таблицы <tr>, в т.ч. и его } if(int0=index(buf0,"</tr")){ # this line ends getSels(substr(buf0,1,int0-1)) # tabl_row -> arrow:sell_values buf0=substr(buf0,int0+4) # убрали эту строку из буфера и окультуриваем... id_T=aSel[0] # имя+расшир файла с текстом (или "./" для раздела) namT=aSel[1] # пока фактическое (as-is) название текста в статистике # if(minT-aSel[3]>0)nextfile # в ЭТОЙ строке за "12мес" МЕНЬШЕ границы, дальше неинтересно if((numT==1)&&(numR==2)){ # хиты по разделу (спец.обслуживание) hitP=aSel[3] # хиты раздела за "12мес" ЕСЛИ нет в aHits nextfile } } } if(int0=index(buf0,"</table")){ # this tabl ends buf0=substr(buf0,int0+4) # update buf0 inTab=0 } }else{ # ищем начало таблицы if(int0=index($0\ ,"<table border=1 cellspacing=0 cellpadding=0><tr><td><td colspan=2><b>Итого</b></td>")){ numT++ # new table numR=1 # певая строка каждой таблицы - календарь хитов статистики раздела buf0=substr($0,int0+80) if(numT==1){ # 1-st table 1-st row -> get col-dates & so-on match(buf0,/<tr[^>]*>(.+)<\/tr[^>]*>/,aj) # собственно строка с календарём getSels(aj[1]) # но самую первую такую - разберём-с tic0=ticS # и привяжем дату к нулевому (самому левому) дню посуточных данных while(strftime("%d",tic0)!=aSel[16])tic0=tic0-86400 # сдвинем стат.дату к нулевому дню datJ=strftime("%Y.%m.%d",tic0-86400) # полная дата первого дня в интервале 30 дней } inTab=1 # мы ВНУТРИ таблицы buf0="" # буфер чист! } } } } # // -=- основной блок скрипта ends function getSels(rowLn){ # разделение строки таблицы статистики на массив значений selN=0 # sells count split("",aSel) aSel[0]="" while(match(rowLn,/<td[^>]*>/)){ # это объявление ячейки selN++ # 0.1-имя/ссылка; хиты: 2-всего, 3-12мес, 4..15-заМес, 16..77-заСутки rowLn=substr(rowLn,RSTART+RLENGTH) # выкусим объявление ячейки f3n2=index(rowLn,"</td") # это конец ячейки f3s2=substr(rowLn,1,f3n2-1) # это сама ячейка (с возможными внутренними тегами) if(selN==1){ # в ПЕРВОЙ ячейке - название текста и ссылка на него match(f3s2,/<a href=([^>]+)>(.*)<\/a>/,f3a1) # выцепим и разложим: aSel[1]=f3a1[2] # название текста aSel[0]=f3a1[1] # ссылка на текст: name.shtml }else aSel[selN]=rmTags(f3s2) # в ПРОЧИХ ячейках - только значение ячейки, очищенное от тегов rowLn=substr(rowLn,f3n2) # выкусим оптиченную ячейку } if(selN==77)return # row HAVE had 77 sells nextfile # битая таблица == битый файл } function rmTags(f2s1){ # удаление ВСЕХ тегов в литерале while(match(f2s1,/<\/?[a-zA-Z][1-6a-zA-Z]?[a-zA-Z]*[ \/]?[^>]*>/)) f2s1=substr(f2s1,1,RSTART-1) substr(f2s1,RSTART+RLENGTH) return(f2s1) } function pack4cmd(s0){ # упаковка строки для CMD; s0 - вх.строка; вых. - в двойных кавычках # Меняутся на HTML-эквивалент символ: "•" на "•" # + меняются на HTML-эквиваленты символы: "&", "%" и '"' /двойные кавычки/ # + левые символы в диапазоне 0-31 таблицы ASCII, пробел и неразрывный_пробел меняются на "•" # + эти символы /"•"/ - оставляются НЕ БОЛЬШЕ одного ПОДРЯД и только ВНУТРИ строки # nvv, 2024.06.03 while(n1=index(s0,"•") ){s0=substr(s0,1,n1-1)"•"substr(s0,n1+1)} # '•' -> '•' while(n1=index(s0,"%") ){s0=substr(s0,1,n1-1)"%"substr(s0,n1+1)} # '%' -> '%' while(n1=index(s0,"\"")){s0=substr(s0,1,n1-1)"""substr(s0,n1+1)} # '"' -> '"' gsub(/[\x0-\x9\xB\xC\xE-\x1F \xA0]+/,"•",s0) # замена ЦЕПОЧЕК пробелов/левых_символов на "•" gsub(/^•/,"",s0) # удаление лидирующего пробела gsub(/•$/,"",s0) # удаление завершающего пробела return ("\""s0"\"") # возвращается свёрнутая строка } END{ # отстрелялись; ну почти... if(errS!=""){ print("") print("] "errS) # есть проблем-с => подудим exit 1 # и на выход с вещами } mkLn() if(fNum%100)print("") else print(" = "fNum) jDat=strftime("%Y.%m.%d") jLst=wDir maxD".hidn.addS" split("",aSel) nSel=0 for(j0=1;j0<=nMig;j0++){ # вычленим записи со свежей datJ split(aMig[j0],aj) # if(aj[2]==maxD)aSel[++nSel]=aMig[j0] aSel[++nSel]=aMig[j0] } asort(aSel) j1=fNum":allS "nSel":good "maxD":dEnd "jDat":done" print("; stat "j1) > jLst # ; 2024.09.07-2024.09.06 4575 15.1% x 374 20256 286 w/wolkowa_natalxja_stepanowna kosturiaballadadocx for(dGap in aDat){ if(aHit[dGap])j0=aHit[dGap] else j0=0 aLst[++nLst]="; "dGap sprintf("%5s %4.1f%% %5s",aDat[dGap],aDat[dGap]*100/numS,j0) } asort(aLst) print("; upDat_datS 1-st_day numS %% hitP") > jLst for(j0=1;j0<=nLst;j0++)print(aLst[j0]) > jLst print("; datS_timS.1 datJ.2 hitP.3 id_P.4 \"namP\".5 \"moto\".6 id_F.7") > jLst for(j0=1;j0<=nSel;j0++)print(aSel[j0]) > jLst print(j1,systime()-tIni":sec") }
Имя файла скрипта: "1hidn.cmd" V-текст скрипта-V- - - - - - - - - @if not defined pMod @echo off set nJob=addS echo %date% %time:~0,8% %nJob% Begs :: 0addS.cmd - сборка дополнительного списка гггг.мм.дд.hidn.addS разделов-невидипок по спискам форм :: 0. нужны списки: _lost.addF /что качать/ и *.~.mig.bStat (можно строить наше новое) :: 1. проверяется наличность и окружение :: 2. скачиваются статистики скрытников :: 3. строится список "datJ.stat,aadS" с пригодными статистиками 200 или более хитов за "12мес" :: 4. обновляется U:\Jobs\1hidn.err - недоступные статистики /для контроля ситуации/ :: основной и резервный URL Самиздата (желательно работать с резервом) if NOT defined siUrl if exist \siUrl.budclub set siUrl=budclub.ru if NOT defined siUrl set siUrl=samlib.ru :: 2024.08.12, nvv, вместо вопроса или работа, или выход по "уже есть" :: история изменений в подвале скрипта! :: основные сеты и прочая подготовка к работе... set jDat=%date% set errInf= :: wrks - общее время работы процесса (пуск общего таймера) for /F %%A in ('gawk.exe "BEGIN{print(systime());exit}"') do set wrks=%%A :: aScr - скрипт вычленения годных потеряшек по страницам их статистик set aScr=%~dpn0.awk if NOT exist %aScr% set errInf=NO %aScr% found & goto errExit :: wDir - общее рабочее место set wDir=%~d0\Jobs :: jDir - место для оперативных файлов set jDir=%wDir%\_%nJob% :: zDir - общий подкаталог для посуточных подкаталогов с итоговыми списками set zDir=%~d0\Stor\wOld\%jDat% :: jRpt - общий отчёт с итоговыми сводками процессов set jRpt=%wDir%\_siTop.# :: jErr - перечень отсутствующих статистик разделов set jErr=%wDir%\%~n0.err echo. >nul 2>%jErr% :: nErr - счётчик отсутствующих статистик разделов set nErr=0 :: dnLd - счётчик скачанного ([пере]запустим "таймер" ratW) set dnLd=0 :: wGetSiz - размер скачанного файла (default 1b минимум) set wGetSiz=1 :: проверить/создать нужные структуры для работы (оперативные площадки) if NOT exist %jDir%\*.* ( mkDir %jDir% if errorLevel 1 set errInf=fail mkDir %jDir% & goto errExit ) if NOT exist %zDir%\*.* ( mkDir %zDir% if errorLevel 1 set errInf=fail mkDir %zDir% & goto errExit ) :: для работы нужно наличие *.~.lst.bStat /ПОЧТИ готовый расчёт/ из имени берём datJ :: htm jLst :: non any качаем :: old any чистим+качаем :: cur non/older качаем :: cur newer -- нечего делать, всё уже :: для работы нужен список потеряшек _lost.addF set inFl=%wDir%\_lost.addF if NOT exist %inFl% set errInf=NO %inFl% found & goto errExit set tmp0= for %%A in ( %wDir%\*.hidn.%nJob% ) do set tmp0=%%~tA if NOT defined tmp0 goto chkDl if %tmp0:~0,10% == %jDat% ( echo == all is done today already goto :eof ) :doJob сегодня ничего пока не сделано... а старое есть/?/ проверим-с set tmp0= for %%A in ( %jDir%\*.stat.htm ) do if NOT defined tmp0 call :chkDat %%~tA if NOT defined tmp0 goto chkDl if exist %jDir%\*.stat.htm ( erase /F /Q %jDir%\*.stat.htm if errorLevel 1 set errInf=fail erase %jDir%\*.stat.htm & goto nExit ) :: и устаревший итоговый список туда же /нафик/ erase /F /Q %wDir%\*.hidn.%nJob% if errorLevel 1 set errInf=fail erase *.hidn.%nJob% & goto nExit rem ; 18:form 7689:pags 1536388:txts 104325:auth 1927:hidn 2023.07.03:done :chkDl выясним имеющийся расклад по потеряшкам после обработки /процессом rAddF.cmd/ форм for /F "tokens=1-9,*" %%A in ( ' gawk.exe "{if(match($2,/^18:form$/))print($3,$4,$5,$6);exit}" %inFl% ' ) do ( set pags=%%A set txts=%%B set auth=%%C set hidn=%%D ) :: почистим, вычленив цифры set pags=%pags:~0,-5% set txts=%txts:~0,-5% set auth=%auth:~0,-5% set hidn=%hidn:~0,-5% echo = %pags%.pags %txts%.txts %auth%.auth %hidn%.hidn.stats dnLd... :: ок, скачаем статистики ВСЕХ этих /скрытых/ разделов set cNum=0 set dnLd=0 :: ratW - темп скачивания for /F %%J in ('gawk.exe "BEGIN{print(systime());exit}"') do set ratW=%%J :: скачивание недостающего for /F "tokens=*" %%A in (%inFl%) do if NOT defined errInf call :dLit %%A if defined errInf goto :eof :: вычислим темп скачивания ratW if %dnLd% == 0 ( set ratW=0 ) else ( for /F %%A in ( ' gawk.exe "BEGIN{print(sprintf(\"%%3.2f\",(systime()-%ratW%)/%dnLd%));exit}" ' ) do set ratW=%%A ) :: ок, статистики у нас echo = %dnLd%:dnLd.stats %ratW%:ratW looking for good id_P :: вычленим годные/нужные для расчёта /в список %datJ%.stat.add2h/ gawk.exe -f %aScr% %jDir%\*.stat.htm if NOT %errorLevel% == 0 set errInf=%aScr% problem in %jDir%\*.stat.htm & goto nExit rem ; stat 1940:allS 20:good 2023.06.28:dEnd 41:tNum 2023.07.03:done rem ; stat 1939:allS 1112:good 2023.07.19:dEnd 2023.07.23:done set jLst= for %%A in ( %wDir%\*.hidn.%nJob% ) do set jLst=%%A if NOT defined jLst set errInf=AWK fails make *.hidn.%nJob% & goto nExit for /F "tokens=1-9,*" %%A in ( ' gawk.exe "{if(match($2,/^stat$/))print($3,$4,$5);exit}" %jLst% ' ) do ( set allS=%%A set good=%%B set dEnd=%%C ) :: почистим, вычленив цифры set allS=%allS:~0,-5% set good=%good:~0,-5% set dEnd=%dEnd:~0,-5% echo = %allS%.allS %good%.good %dEnd%.dEnd :: остановим общий "таймер", : преобразуем секунды в время работы (в обычном формате "чч:мм:сс") for /F %%A in ('gawk.exe "BEGIN{print(strftime(\"%%H:%%M:%%S\",systime()-%wrks%+46800));exit}"') do set wrks=%%A set tmp0=;0S add2 ^ %pags%.pags ^ %txts%.txts ^ %auth%.auth ^ %hidn%.hidn ^ %good%.good ^ %dnLd%:dnLd ^ %nErr%:nErr ^ %dEnd%:dEnd ^ %ratW%~ratW ^ %jDat%:done ^ %wrks%~wrks ^ %time:~0,5% echo %tmp0% >> %jLst% echo %tmp0% >> %jRpt% echo = Ok %hidn%:hidn %good%:good %dnLd%:dnLd %ratW%~ratW :: скинем результаты в хранилище copy /y /b %jLst% %zDir%\ > nul if errorLevel 1 set errInf=fail copy %jLst% TO %zDir% & goto nExit :: подудим где нада "готово-с!" set itog=%jLst% :nExit if defined errInf if NOT defined errF echo ! %errInf% echo %date% %time:~0,8% %~nx0 Ends %nErr%:nErr goto :eof rem ;txTot id_P rem 25 k/koroljuk_m_a :dLit %%A скачивание статистик по id_P {like e/etno} из списка lost.add2h set id_P=%2 set wFil=%id_P% set wFil=%jDir%\%wFil:~0,1%~%wFil:~2%.stat.htm if exist %wFil% ( call :show ~ goto :eof ) call :show . set wUrl=%siUrl%/%id_P%/stat.shtml call wGetUrl2fil.cmd %wUrl% %wFil% if %wGetErr% == 0 goto :eof :: проблема? if %wGetErr% == 1 ( if exist %wFil% erase %wFil% echo %id_P% >> %jErr% set /A nErr+=1 set errInf= goto :eof ) set errInf=no web{SI} {%wUrl%} goto :eof :show оживляж скачивания статистик set /a cNum+=1 set mark=%1 rem if exist %wFil% set mark=~ if %cNum:~-1% == 0 set mark=%cNum:~-2,1% gawk.exe "BEGIN{printf(\"%mark%\");exit}" rem if NOT "%cNum:~-2%" == "00" if NOT "%cNum:~-2%" == "50" goto :eof if NOT "%cNum:~-2%" == "00" goto :eof :: по 50 отметок на строку set tmp0= %cNum% set tmp0=%tmp0:~-5,3% gawk.exe "BEGIN{printf(strftime(\"%tmp0% %%H:%%M:%%S\n\",systime()-%ratW%,-1));exit}" goto :eof :chkDat %%~tA "сегодня"==ОК, иначе - старьё-с if %1 == %jDat% goto :eof set tmp0=%1 goto :eof :errExit реакция на проблему: в пакете - выход if defined pMod goto :eof :: автономно - на экран + прекращение работы echo %errInf% exit :: 2023.06.28, nvv, сознано на основе aHits.cmd от 2023.05.30 :: 2023.08.12, nvv, last upDates :: 2024.02.05, nvv, исправлена обработка отсутствия сети или файла в ней :: 2024.02.23, nvv, исправлена ошибка НЕ переключения по переменной siUrl :: 2024.03.03, nvv, исправлена ошибка в п/п скачивания статистик :: + работа отвязана от даты в bStat + мелкие изменения в логике :: 2024.03.17, nvv, no toDay`s job == no toDay`s wait :: 2024.06.24, nvv, errs count added and file: U:\Jobs\1hidn.err
Имя файла скрипта: "aHits.awk" V-текст скрипта-V- - - - - - - - - BEGIN{ # aHits.awk - просмотр локальных страниц рейтинга и создание списка разделов с хитами # add2="U:\\Jobs\\2024.06.02.hidn.addS" # если вызов НЕ из CMD # 2024.10.02, nvv, иначе ищем h30k и n30k +a30k /после добавки add2, а НЕ до/ # ! прочая история в подвале # В процессе: считывается дата обновления рейтинга, и количество страница рейтинга хитов # Источник - рейтинг "по хитам": /rating/hits/ может использоваться самостоятельно. # Для правильной нумерации мест разделов, ИМЯ входных файлов должно начинаться с ЧИСЛА # (номер страницы рейтинга,например: 0025.html). Расширение - любое. # Причём, итоговые списки (пере)создаются РЯДОМ (jDir) с входными файлами: # - fOut=jDir"]aHits.lst" # основной список - OK_элементы ]aHits.lst # - fBad=jDir"]aHits.bad" # список брака - BAD_элементы ]aHits.bad # + выдача на StdUot: hDat,pMax,xNam,xNum,xPas,hMax,h30k,hTot # hitP - par.hits - хиты раздела за "год" # numP - par.number - место раздела в рейтинге СИ по посещаемости (1..10000) первые 10k # sizK - общий объём (в kb) текстов раздела # sizN - общее количество текстов в разделе # id_P - partition (par.) - раздел СИ (like: n/nosow_w_w) # namP - "par.name" - название раздела (псевдоним автора, like: "Влад" или "Уксус•Сергей") # НЕштат (НЕ рейтинг или НЕ в порядке) выдача на StdUot: # "] Hole or no data ("step" lines) in file:" fNam) # "] DifDates;" hDat "!=" cYea"."cMth"."cDay "! in file:" fNam) # "] DifPageNums;" pMax "!=" pNum "! in file:" fNam) # с немедленным завершением работы # в fOut: исправные записи с хитами разделов за "12мес": # hitP numP sizK sizN id_P "namP" "sigP" # 24620 192 14754 25 n/nosow_w_w "Влад" "nvv_Lazy_Tiger" # 901899 1 931 5 d/dront_n "Дронт•Николай" "Записки•о•том,•чего•не•было" # 18625 385 18053 29 n/nosow_w_w "Влад" "nvv_Lazy_Tiger" # в fBad: записи с проблемами: # ] Err:2 no nick: 829 8443 u/ulybin_w_w "" # ] Err:1 no text: 44158 147 s/sherbakow_a "Щербаков•Александр" if(ARGV[1]=="")exit # защита от случайного пуска # j1=split(ARGV[1],aj,"\\") for(str2 in ENVIRON){ # ! регистр букв в имени переменной может быть любой if(tolower(str2)=="wdir")wDir=ENVIRON[str2]"\\" # место для итогового списка aHits if(tolower(str2)=="add2")add2=ENVIRON[str2] # место для итогового списка aHits } # ; datS_timS.1 datJ.2 hitP.3 id_P.4 "namP".5 "moto".6 id_F.7 # 2023.07.20_01:54:05 2023.07.19 9073 n/neon13 "Neon13" "Авторский" n~neon13 if(add2=="")add2="U:\\Jobs\\2024.09.30.hidn.addS" nAdd=0 while((getline line<add2)>0){ # список потеряшек split(line,aj) if(match(aj[1],/^20/)){ # строка с данными скрытого раздела j0=1000000-aj[3] aAdd[++nAdd]=sprintf("%7s%7s%9s%7s",j0,0,0,1)" "aj[4]" "aj[5] # это на включение в итог aIdA[aj[5]]=nAdd # это для контроля отсутствия включаемого в итоге } } close(add2) # всё/не_всё, - старый список тогось add2=0 # 500779 1 46664 126 g/goncharowa_g_d "Гончарова•Галина•Дмитриевна" "Писатель•должен•быть•талантлив•и•дьявольски•трудолюбив" # 3 105072 0 0 d/dura "Не•Писатель" # ; hitP.1 numP.2 sizK.3 sizN.4 id_P.5 "namP".6 "moto".6 # if(j1==1)jDir=".\\" # иесто для результатов ТАМ ЖЕ, где исходные файлы # else for(j2=1;j1-j2>0;j2++)jDir=jDir aj[j2]"\\" # fBad=jDir"]aHits.bad" # список брака - BAD_элементы ]aHits.bad jTic=systime() # ДВЕ проверки: дата(step==-1) + полнота(==0) jYea=strftime("%Y",jTic) jMth=strftime("%m",jTic) xNam=0 # счёчик разделов (записей) без ФИО xNum=0 # счёчик разделов без наполнения (без объёмя и кол-ва файлов раздела) xPas=0 # счёчик разделов "всего OK" hTot=0 # счёчик "hits total" hMax=0 # хиты 30k разделов "макс" h30k=0 # хиты 30k разделов "мин" n30k=0 # номер замыкающего раздела в aHits с хитами == h30k a30k=0 # число скрытых разделов в первых 30k разделов pMax="" # номер страницы рейтинга (в имени файлов) } { # // -=- основной блок скрипта if(FNR==1){ # секция завершения работ с одним файлом и подготовки к работе со следущим if(NR!=1)chkSteps() # страница пройдена; она в порядке? fNam=FILENAME # U:\Jobs\#aHits\0001.hits.htm p100=split(FILENAME,aj,"\\") # NEW/NEXT входной файл разделим на подкаталоги и имя.расширение p100=split(aj[p100],aj,".") # имя.расширение входного файла разделим на части p100=(aj[1]-1)*100 # p100 чистые сотни (начиная с нуля, like: "1400" для "0015.hits.htm") step=-1 # -1 == date, 0 - nPgs, 1..100 dataLine fNum++ if(fNum%100==0) print(sprintf(": %4s",fNum/100)) else if(fNum%10)printf(".") else printf(":") # оживляж... } # <b>СТАТИСТИКА за 22/11:</b> if (step==-1) { # считывание обязательной ДАТЫ рейтига if(match($0,/^<b>СТАТИСТИКА за ([0-3][0-9])\/([01][0-9]):<\/b>$/,aj)){ # 30 09 (30/09) cMth=aj[2] cDay=aj[1] step++ } } # <center><b>Страниц (970):</b> <b>1</b> <a href= if (step==0) { # проверка ПОЛНОТЫ статистики if(match($0,/^<center><b>Страниц \(([0-9]+)\):<\/b> /,a2)){ pNum=a2[1] step++ } } # <DL><b>44158</b> <a href=/s/sherbakow_a/>Щербаков Александр</a> "Творчество как бы"<DD><font color=#555555><i>Почитал ГкН, Лунного скульптора, Игру... и зачесались ручки как бы... что получится - будет видно)</i></font></DD></DL> # <DL><b>43514</b> <a href=/a/aizmash/>Aizmash</a> "aizmash" (1603k,5)</DL> # <DL><b>721</b> <a href=/g/glinka_i_s/></a> "Ярина" (924k,16)</DL> # <DL><b>593</b> <a href=/a/amelichewa_a_a/>Амеличева Алиса Анатольевна</a> "" (4k,23)</DL> if (step+0>0) { # извлечение хитов, authID и ФИО(псевдонима) numP=p100+step if (match($0,/<b>([0-9]+)<\/b> <a href=\/(.)\/(.+)\/>(.*)<\/a>/,aj)){ # это обязательно! hitP=aj[1] # хиты раздела за "12мес" id_P=aj[2]"/"aj[3] # ID раздела if(aj[4]==""){ # no: ФИО/псевдоним/nick xNam++ # errInf hitP numP id_P namP="\"\"" # ВМЕСТО ФИО/ник_владельца - спец.отметка }else{ namP=pack4cmd(aj[4]) # ФИО/ник_владельца раздела } if(match($0,/<\/a> "(.*)" \(([0-9]+)k,([0-9]+)\)/,a2)){ # (3776k,10) это - если не пусто xPas++ moto=pack4cmd(a2[1]) # девиз раздела (может отсутствовать) sizK=a2[2] # общий объём текстов в разделе sizN=a2[3] # кол-во текстов в разделе } else { # пусто (нет наполнения раздела) xNum++ # список брака - BAD_элементы ]aHits.bad moto="" sizK=0 sizN=0 } aHit[++nHit]=sprintf("%7s%7s%9s%7s",1000000-hitP,numP,sizK,sizN)" "id_P" "namP" "moto aIdH[id_P]=numP hTot=hTot+hitP # счёчик "hits total" # if(!h30k){ # хиты 30.000-го раздела выяснены? # if(numP==30000)h30k=hitP # хиты 30-и тысячного раздела # } if(hMax-hitP<0)hMax=hitP # хиты - "макс" step++ } } } function pack4cmd(s0){ # упаковка строки для CMD; s0 - вх.строка; вых. - в двойных кавычках # Меняутся на HTML-эквивалент символ: "•" на "•" # + меняются на HTML-эквиваленты символы: "&", "%" и '"' /двойные кавычки/ # + левые символы в диапазоне 0-31 таблицы ASCII, пробел и неразрывный_пробел меняются на "•" # + эти символы /"•"/ - оставляются НЕ БОЛЬШЕ одного ПОДРЯД и только ВНУТРИ строки # nvv, 2024.06.03 while(n1=index(s0,"•") ){s0=substr(s0,1,n1-1)"•"substr(s0,n1+1)} # '•' -> '•' while(n1=index(s0,"%") ){s0=substr(s0,1,n1-1)"%"substr(s0,n1+1)} # '%' -> '%' while(n1=index(s0,"\"")){s0=substr(s0,1,n1-1)"""substr(s0,n1+1)} # '"' -> '"' gsub(/[\x0-\x9\xB\xC\xE-\x1F \xA0]+/,"•",s0) # замена ЦЕПОЧЕК пробелов/левых_символов на "•" gsub(/^•/,"",s0) # удаление лидирующего пробела gsub(/•$/,"",s0) # удаление завершающего пробела return ("\""s0"\"") # возвращается свёрнутая строка } function chkSteps() { # страница пройдена; она в порядке? if((step!=101)&&(pNum*100!=p100+100)){ #количество записей на странице штатное? если НЕ последняя print pNum*100,p100 print("] Hole or no data ("step-1" lines) in file:" fNam) # нет! (мало записей) exit 3 }else{ if(hDat==""){ # это ПЕРВЫЙ файл страницы с хитами cYea=jYea # отпределимся с датой статистики (относительно "сегодня") if(jMth!=cMth) if(cMht==12)cYea-- # если месяц иной + предыдущий - декабрь => прошлый год hDat=cYea"."cMth"."cDay # полная дата для: "СТАТИСТИКА за дд/мм" }else if(hDat!=cYea"."cMth"."cDay){ # это второй и последующие файлы, даты совпабают? print("] DifDates: " hDat "!=" cYea"."cMth"."cDay " in file:" fNam) # нет! exit 1 } if(pMax=="")pMax=pNum # это ПЕРВЫЙ файл с хитами, запомним общее кол-во страниц в рейтинге else if(pMax!=pNum){ # это вторай и последующие файлы "с хитами", это кол-во тоже самое? print("] DifPageNums: " pMax "!=" pNum " in file:" fNam) # нет! exit 2 } } } # 2018.10.25, nvv, created # ... # 2019.01.02, nvv, update # 2019.02.05, nvv, ФИО/nick упаковывается + новое поле size,num раздела (like "10496k,32") # 2019.04.19, nvv, added hTot - summ for all hits of 100 partitions, paged # 2019.07.10, nvv, мелкая косметика # 2019.07.27, nvv, добавлено поле "девиз раздела" # +наполнение раздела - теперь это два поля(объём/кол-во) +поля слегка переставлены # 2020.01.27, nvv, мелкая косметика # 2020.03.13, nvv, переделано и обустроено всё потребное (слегка-с новая концепция) # 2020.08.21, nvv, исправлена мелкая, но неприятная ошибка отбраковки разделов с пустым девизом # 2020.09.10, nvv, нештат НЕ исключается из итогового списка, НО кол-во у них всегда(!) 0 # + соответственно, список "плохого" (fBad) НЕ создаётся # 2020.11.01, nvv, последняя страница рейтинга не обязана иметь 100 записей. ;) # + на прочих - показывает точное число (без +1) # 2021.05.02, nvv, переименовано (убран префикс "siTip-") # 2023.07.23, nvv, переделано для включения потеряшек add2 в aHits # 2024.05.09, nvv, param:n30k added /last h30k.hits line number in aHits/ # 2024.06.05, nvv, п/п pack -> pack4cmd # 2024.09.08, nvv, место под sizK увеличено до 99Gb (8+1 знако-место) END{ if(ARGV[1]==""){ # защита от случайного пуска print("NO in file(s)") exit -1 } if(fNum%100)print("") else print(" = "fNum) chkSteps() # страница пройдена; она в порядке? for(id_P in aIdA)if(!(id_P in aIdH)){ aHit[++nHit]=aAdd[aIdA[id_P]] add2++ } fOut=wDir hDat".aHits" # основной список - OK_элементы ]aHits.lst jDat=strftime("%Y.%m.%d") # ;1A hits 5:xNam 451:xNum 104642:xPas 2023.07.09:hDat 507217:hMax 1051:hPag 15:add2 1086:dnLd 0.17~ratW 2023.07.11:done 03:12:17~wrks 15:02 # ; aHit 5:xNum 451:xNum 104642:xPas 507217:hMax 1051:hPag 15:add2 381:h30k 42411880:hTot 2023.07.09:hDat 2023.07.14:done asort(aHit) for(j0=1;j0<=nHit;j0++){ j1=1000000-substr(aHit[j0],1,7) print(sprintf("%7s",j1),substr(aHit[j0],9)) > fOut if(j0==30000)h30k=j1 # запись 30k if(!n30k){ if(h30k-j1>0){ n30k=j0-1 # место последнего раздела с хитами h30k }else if(substr(aHit[j0],8,7)+0==0){ # это скрытый раздел a30k++ # сосчитаем-с } } } # общая сводка работы с рейтингом "по хитам" print("; hitP.1 numP.2 sizK.3 sizN.4 id_P.5 \"namP\".6 \"moto\".6") > fOut print("; aHit "xNam":xNam",xNum":xNum",xPas":xPas",hMax":hMax",pMax":hPag",add2":add2"\ ,n30k":n30k",h30k":h30k",a30k":a30k",hTot":hTot",hDat":hDat",jDat":done ") >fOut # общая сводка работы с рейтингом "по хитам" print("; aHit "hDat,pMax":pMax",xPas":xPas "add2":add2 "n30k":n30k "h30k":h30k "a30k":a30k") }
Имя файла скрипта: "aHits.cmd" V-текст скрипта-V- - - - - - - - - @if not defined pMod @echo off set nJob=aHits echo %date% %time:~0,8% %nJob% Begs :: aHits.cmd - сборка полного списка авторов СИ по рейтнгу хитов :: основной и резервный URL Самиздата (желательно работать с резервом) if NOT defined siUrl if exist \siUrl.budclub set siUrl=budclub.ru if NOT defined siUrl set siUrl=samlib.ru :: %time% - HH:MM:SS,tt HH<=9 -> "HH" == " H" лидирующий пробел для часа меньше 10 :: %date% - YYYY.mm.dd :: 2024.10.13, nvv, minor cosmetic + ini wait == 10 min :: история изменений в подвале скрипта! :: основные сеты и прочая подготовка к работе... set jDat=%date% set errInf= set jSiD=%jDat:~8%/%jDat:~5,2% :: wrks - общее время работы процесса (пуск общего таймера) for /F %%A in ('gawk.exe "BEGIN{print(systime());exit}"') do set wrks=%%A :: aScr - скрипт обработки страниц рейтинга "по хитам" set aScr=%~dpn0.awk if NOT exist %aScr% set errInf=! NO %aScr% found & goto errExit :: wDir - общее рабочее место set wDir=%~d0\Jobs :: jDir - место для оперативных файлов set jDir=%wDir%\#%nJob% :: jRpt - общий отчёт с итоговыми сводками процессов set jRpt=%wDir%\_siTop.# :: zDir - общий подкаталог для посуточных подкаталогов с итоговыми списками set zDir=%~d0\Stor\wOld\%jDat% :: hDir - скоад первых страниц скачанных рейтингов aHits set hDir=%~d0\Stor\hist.aHits :: проверить/создать нужные структуры для работы (оперативные площадки) if NOT exist %jDir%\*.* ( mkDir %jDir% if errorLevel 1 set errInf=fail mkDir %jDir% & goto nExit ) if NOT exist %zDir%\*.* ( mkDir %zDir% if errorLevel 1 set errInf=fail mkDir %zDir% & goto nExit ) if NOT exist %hDir%\*.* ( mkDir %hDir% if errorLevel 1 set errInf=fail mkDir %hDir% & goto nExit ) :: 0. ищем последний aHits в логе общей истории jRpt _siTop.# rem ;1A hits 6:xNam 450:xNum 103984:xPas 2024.10.02:hDat 436220:hMax 1045:hPag 1884:add2 30022:n30k 271:h30k 1045:dnLd 0.08~ratW 2024.10.03:done 00:18:58~wrks 9:03 set oDrD= for /F "tokens=1-9,*" %%A in ( ' gawk.exe "{if(match($0,/^;1A hits.* ([^ ]+):hDat,* ([^ ]+):hMax ([^ ]+):hPag .* ([^ ]+):done/,a))print a[1],a[2],a[3],a[4]}" %wDir%\_siTop.# ' ) do ( set oDat=%%A set oMax=%%B set oPgs=%%C set oDrD=%%D ) if NOT defined oDrD set errInf=NO aHits rec(s) in %jRpt% & goto errExit if %oDat% == %jDat% ( echo == all is done today already goto :eof ) :: add2 - список потеряшек к расчёту для включений в aHits set add2= rem set tmp0= for %%A in ( %wDir%\20??.??.??.hidn.addS ) do ( set add2=%%A set tmp0=%%~tA ) if NOT defined add2 set errInf=NO *.hidn.addS & goto errExit if NOT %tmp0:~0,10% == %jDat% set errInf=OLD *.hidn.addS & goto errExit :: last - последний актуальный список aHits set last=%~d0\Stor\wOld\%oDrD%\%oDat%.%nJob% if NOT exist %last% set errInf=no last %last% found & goto nExit set oSiD=%oDat:~8%/%oDat:~5,2% rem # loc: 02/10 oMax:436220 pOld:1045 echo # loc: %oSiD% oMax:%oMax% pOld:%oPgs% oDat:%oDat% add2.Ok :: fil1 - первый файл комплекта страниц aHits set fil1=%jDir%\0001.hits.htm :: dnLd - счётчик скачанного ([пере]запустим "таймер" ratW) set dnLd=0 :: wGetErr - уточнённый статус завершения wGet set wGetErr=0 :: wait - ФЛАГ/таймер зацикливания ожидания полного списка aHits set wait=%1 set wait=600 :: 1. смотрим наличие aHits в Jobs - нет == переходим к п.4 if NOT exist %wDir%\%oDat%.%nJob% goto doJob :begJob 4. нужно! ...а старые *,htm есть/?/ == стираем if exist %jDir%\*.hits.htm ( erase /F /Q %jDir%\*.hits.htm if errorLevel 1 set errInf=fail erase %jDir%\*.hits.htm & goto nExit ) :: и устаревший итоговый список *.aHits туда же /нафик/ if exist %wDir%\%oDat%.%nJob% ( move /Y %wDir%\%oDat%.%nJob% %wDir%\%oDat%.%nJob%.old if errorLevel 1 set errInf=fail move %oDat%.%nJob% 2old & goto nExit ) :doJob выяснение ситуации с "потеряшками" Добавляем их? :: - скачиваем fil1 и переходим на анализ п.1.... :: 4. смотрим fil1 :: - нет fil1 или он НЕ сегодняшний == СКАЧИВАЕМ сегодняшний dnLd++ :: 5. анализ сегодняшнего статуса :: - fil1 - "НЕ годный" :: -- dnLd>=1 выход или цикл ожидания :: -- dnLd==0 скачиваем свежую копию + переход на р5. :: - fil1 - "ГОДНЫЙ" докачиваем и строим :Again curM - кол-во секунд с момента начала цикла ожидания if NOT exist %fil1% ( call :reqSI 1 if defined errInf goto nExit ) if NOT exist %fil1% set errInf=fail dnLd 0001.hits.htm & goto nExit call :scan01 if defined errInf goto nExit :: если в СИ дата СЕГОДНЯ, скачиваем! if %jSiD% == %cDat% goto dlAll :: в СИ или то же самое, или мало страниц, скачивать нельзя. erase %fil1% if errorLevel 1 set errInf=fail erase %fil1% & goto nExit rem if %oMax% == %hMax% ( rem set tmp2=NO diff {was:%oMax%.oMax} rem ) else ( rem set tmp2=too LOW {was:%oPgs%.oPgs} rem ) :: неполный список; цикл заказывали? if NOT defined wait ( set errInf=x web: %cDat% hMax:%hMax% pMax:%pMax% NOT toDay, no wait, exit goto nExit ) :: если заказано зацикливание, цикл ожидания - 10 мин. ДО 10:30, 1 мин после set /a tmp0=((%time:~0,2%*60)+1%time:~3,2%)-100 rem set wait=60 set wait=600 if %tmp0% GTR 615 set wait=60 :: а заказано именно ЧИСЛО (секунд в цикле ожидания)? for /F %%A in ( 'gawk "BEGIN{print(strftime(\"%%H:%%M:%%S\",systime()+%wait%));exit}"' ) do set tmp0=%%A :: не число - не судьба... ;) if %tmp0% == 0 goto nExit :: иначе ждём-с ;) echo ! web: %cDat% hMax:%hMax% pMax:%pMax% now:%jSiD%, WAITing till %tmp0% call :waitSecs %wait% rem gawk "BEGIN{t=systime()+%wait%;while(t>systime()){printf(\"%%s\",\".\");j=systime()+1;while(j>systime()){k=1}};exit}" rem echo. goto Again :dlAll скачивание всего комплекта страниц aHits echo v web: %cDat% hMax:%hMax% pMax:%pMax% OK, dnLd... :: ratW - темп скачивания (секунд на один файл в среднем) for /F %%A in ('gawk.exe "BEGIN{print(systime());exit}"') do set ratW=%%A gawk.exe "BEGIN{printf(\"%pMax%.pMax %hMax%.hMax\n.\");exit}" for /L %%A in (2,1,%pMax%) do if NOT defined errInf call :reqSI %%A if defined errInf goto :eof if NOT "%pNum:~-2%" == "00" echo. = %pNum% %time:~0,8% :: вычислим темп скачивания ratW if %dnLd% == 0 (set ratW=0) else ( for /F %%A in ('gawk.exe "BEGIN{print(sprintf(\"%%3.2f\",(systime()-%ratW%)/%dnLd%-1));exit}"') do set ratW=%%A ) echo = dnLd ok, scaning... gawk.exe -f %aScr% %jDir%\*.hits.htm if NOT %errorLevel% == 0 set errInf=fail %aScr% with *.hits.htm & goto nExit set jLst= :: ищем готовый ПОЛНЫЙ 20??.??.??.aHits, берём дату в его имени for %%A in (%wDir%\20??.??.??.%nJob%) do ( set hDat=%%~nA set jLst=%%A ) if NOT defined jLst set errInf=fail make %jLst% & goto nExit rem ; aHit 5:xNam 451:xNum 104642:xPas 507217:hMax 1051:hPag 15:add2 381:h30k 42411880:hTot 2023.07.09:hDat 2023.07.14:done rem 1 ; rem 2 aHit rem 3 5 xNam 1 rem 4 451 xNum 2 rem 5 104642 xPas 3 rem 6 507217 hMax 4 rem 7 1051 hPag 5 rem 8 15 add2 6 rem 9 381 h30k 7 rem 10 42411880 hTot 8 rem 11 2023.07.09 hDat 9 rem 12 2023.07.14 done :: считаем итоги сборки списка aHits for /F "tokens=1-9,*" %%A in ( ' gawk.exe "{if(match($2,/^aHit$/)){print $3,$4,$5,$6,$7,$8,$9,$10;exit}}" %jLst% ' ) do ( set xNam=%%A set xNum=%%B set xPas=%%C set hMax=%%D set hPag=%%E set add_=%%F set n30k=%%G set h30k=%%H ) :: вычленим значения данных set xNam=%xNam:~0,-5% set xNum=%xNum:~0,-5% set xPas=%xPas:~0,-5% set hMax=%hMax:~0,-5% set hPag=%hPag:~0,-5% set add_=%add_:~0,-5% set n30k=%n30k:~0,-5% set h30k=%h30k:~0,-5% :: остановим "таймер", : преобразуем секунды в время работы (в обычном формате "чч:мм:сс") for /F %%A in ('gawk.exe "BEGIN{print(strftime(\"%%H:%%M:%%S\",systime()-%wrks%+46800));exit}"') do set wrks=%%A :: оформим подвал списка... :: ;1A hits 5:xNam 451:xNum 104642:xPas 2023.07.09:hDat 507217:hMax 1051:hPag 15:add_ 1086:dnLd 0.17~ratW 2023.07.11:done 03:12:17~wrks 15:02 set tmp0=;1A hits ^ %xNam%:xNam ^ %xNum%:xNum ^ %xPas%:xPas ^ %hDat%:hDat ^ %hMax%:hMax ^ %hPag%:hPag ^ %add_%:add2 ^ %n30k%:n30k ^ %h30k%:h30k ^ %dnLd%:dnLd ^ %ratW%~ratW ^ %jDat%:done ^ %wrks%~wrks ^ %time:~0,5% echo %tmp0% >> %jLst% echo %tmp0% >> %jRpt% echo = Ok %xNam%:xNam %xNum%:xNum %xPas%:xPas %hMax%:hMax %h30k%:h30k %add_%:add2 %hDat% :: прикопаем итоги для истории... copy /b %jLst% %zDir% > nul if errorLevel 1 set errInf=fail copy %jLst% TO %zDir% & goto nExit rem copy /b %fil1% U:\Jobs\#aHits\hist.aHits\0001.hits.%jDat%.htm > nul copy /b %fil1% %hDir%\0001.hits.%jDat%.htm > nul if errorLevel 1 set errInf=fail copy %fil1% TO hist.aHits & goto nExit rem for %%A in ( %fil1% ) do echo %%~tA >> U:\Jobs\#aHits\hist.aHits\daTim_of_0001.hits.~.htm.# for %%A in ( %fil1% ) do echo %%~tA >> %hDir%\daTim_of_0001.hits.~.htm.# :: и устаревший итоговый список *.aHits туда же /нафик/ if exist %wDir%\%oDat%.%nJob%.old ( erase /F /Q %wDir%\%oDat%.%nJob%.old if errorLevel 1 set errInf=fail erase %oDat%.%nJob%.old & goto nExit ) :: подудим где нада "готово-с!" set itog=%jLst% :nExit if defined errInf ( echo ! %errInf% if NOT defined wait set errInf= ) echo %date% %time:~0,8% %~nx0 Ends goto :eof :reqSI %%J притаскивает file:///U:/Jobs/#aHits/index-3.shtml set pNum=000%1 set tmp0= %1 :: pNum - 4-х значное число с лидирующими нулями (для красивой сортировки пронумерованных страниц рейтинга) set pNum=%pNum:~-4% set tmp0=%tmp0:~0,2% :: wUrl - первая /дефолтная/ страница рейтинга set wUrl=%siUrl%/rating/hits/index-%1.shtml :: wFil - конечный локальный файл для скачиваемого set wFil=%jDir%\%pNum%.hits.htm :: оживляж... set mark=. if exist %wFil% set mark=~ if %pNum:~-1% == 0 set mark=%pNum:~-2,1% :: первая странимца нужна для выяснения числа страниц if %1 == 1 ( set wUrl=%siUrl%/rating/hits/index.shtml goto doDl ) gawk.exe "BEGIN{printf(\"%mark%\");exit}" if NOT "%pNum:~-2%" == "00" goto doDl echo. %pNum:~0,2% %time:~0,8% :doDl if exist %wFil% goto :eof call wGetUrl2fil.cmd %wUrl% %wFil% :: проблема? if %wGetErr% == 1 set errInf=no %wUrl% if %wGetErr% == 3 set errInf=no web{SI} goto :eof rem <DL><b>95347</b> <a href=/z/zhan/>Tony</a> :scan01 выченение кличевых значений из первой страницы рейтинга aHits :: pMax - общее число страниц set pMax= :: hMax - хиты топового раздела /лидер/ set hMax= :: cDat - СИ-шная дата рейтинга set cDat= set tmp0= for /F "tokens=1-9,*" %%J in ( ' gawk.exe "{if(match($0,/\.shtml>([0-9]+)<\/a> *<\/center><DL><b>([0-9]+)</,a)){print(a[1],a[2]);exit}}" %fil1% ' ) do ( set pMax=%%J set hMax=%%K ) for /F "tokens=1-9,*" %%J in ( ' gawk.exe "{if(match($0,/ ([0-3][0-9]\/[01][0-9]):<\/b>/,a)){print(a[1]);exit}}" %fil1% ' ) do set cDat=%%J if NOT defined pMax set tmp0=NO pMax if NOT defined cDat set tmp0=NO cDat %tmp0% if defined tmp0 set errInf=%tmp0% in %fil1% goto :eof :errExit реакция на проблему: в пакете - выход if defined pMod goto :eof :: автономно - на экран + прекращение работы echo %errInf% exit ===v=== комплект п/п для обустройства заданных ожиданий в CMD :waitSecs %%A организовать паузу в заданное число секунд /%1/ оживляж с новой строки, если /%2/ for /f "tokens=1-9,*" %%Q in ( ' gawk.exe "BEGIN{t=systime();print(t,t+%1);exit}" ' ) do ( set jSec=%%Q set eSec=%%R ) if NOT %2. == . echo. :: начальная фиксация момента старта call :ticSet goto sleep6 :ticShow оживляж - это наше всё gawk.exe "BEGIN{if(%curM%==%preM%){printf(\".\")}else{printf(%curM%)}exit}" :: строка терминируется 10-й минутой /"0"/ if %curM% == 0 if NOT %curM% == %preM% echo. rem %curT% :: проверка истечения заданного срока; "да"==вЫход if %curS% GEQ %eSec% ( if NOT %curM% == 0 echo. rem %curT% goto :eof ) :sleep6 шаг задержки - 6 секунд sleep 6 :: рабочая фиксация очередного момента call :ticSet goto ticShow :ticSet запомним старое значение момента времени относительно начального /jSec/ set preM=%curM% for /f "tokens=1-9,*" %%P in ( ' gawk.exe "BEGIN{t=systime();print(t,strftime(\"%%H:%%M %%M\",t-%jSec%,1));exit}" ' ) do ( set curS=%%P set curT=%%Q set curM=%%R ) :: и текущее /новое/ значение минут /последняя цифра/ set curM=%curM:~1% goto :eof ===^=== комплект п/п для обустройства заданных ожиданий в CMD :: 2018.08.05, nvv, creation :: ... :: 2019.11.29, nvv, samlib.ru budclub.ru - основной и альтернативный адреса "Самиздата" :: + переменная nJob блокирует пилотную команду @echo off :: 2019.12.06, nvv, current unification :: 2020.03.13, nvv, улучшайзинг послегка-с... :: 2020.04.06, nvv, улучшен алгоритм распознавания свежека, ЕСЛИ дата та же, а данные - свежие :: 2020.04.29, nvv, minor corrections :: 2020.05.23, nvv, set pGet=115 -> 120; set oPag=990 -> 999 :: 2020.05.23, nvv, set pGet=200 :: 2020.07.29, nvv, set pGet=250 :: 2020.09.12, nvv, set pGet=300 + отказ от отделения брака, всё вместе + у брака sizN==0 :: 2020.11.13, nvv, будКлуб - глупость :: 2020.11.16, nvv, будКлуб - глупость? не факт... ;( :: 2020.11.28, nvv, будКлуб - отнюдь... + мелкая косметика :: 2021.05.11, nvv, очередная оптимизация с унификацией... :: 2022.02.04, nvv, мелкий улучшайзинг оживляжа :: 2022.02.07, nvv, прикапывание первой страницы полного рейтинга в U:\Jobs\#aHits\2022.hist.aHits :: 2022.02.16, nvv, мелкое улучцение оживляжа :: 2022.06.07, nvv, мелкое улучшение оживляжа и логики + возможность возобновления после падения сети :: 2023.07.11, nvv, пауза между запросами свежака в СИ через sleep, а не через цикл в gawk :: 2023.07.22, nvv, поддержка включения "потеряшек" add2 в общий список aHits :: 2023.07.30, nvv, исправлена мелкая неточность выхода по несоблюдению условий для работы :: 2023.10.11, nvv, до 10:00 и после 14:00 интервал опроса СИ - 1 минута, иначе - 20 минут :: 2024.03.01, nvv, изменился рисунок публикации данных учёта посетителей СИ, выясняем детали... :: 2024.03.05, nvv, ожидание в цикле теперь всегда 1 минута /wait=60/ для выяснения-с расписания для :: 2024.03.16, nvv, ожидание в цикле теперь 5 минута ДО 10:00 и 1 ПОСЛЕ /wait=60/ + мелочь :: 2024.03.17, nvv, no toDay`s job == no toDay`s wait :: 2024.04.03, nvv, за сутки список похудел сразу на 11 страниц == контроль числа оных /oPag/ отключен :: 2024.04.06, nvv, склад первых страничек переехал в hDir :: 2024.05.08, nvv, param:n30k added /last h30k.hits line number in aHits/ :: 2024.05.22, nvv, убрана в CMD работа с значением hTot /хитов всего/ :: 2024.08.13, nvv, вместо вопроса или работа, или выход по "уже есть" :: 2024.09.19, nvv, ожидание в цикле готовности и БЕЗ параметра :: 2024.10.03, nvv, нужен именно сегодняшний список: "СТАТИСТИКА за дд/мм"
Имя файла скрипта: "bStat.awk" V-текст скрипта-V- - - - - - - - - BEGIN{ # bStat.awk scan+check *.stat.htm +mkLst книг-кандидатов в siTopTexts # 2024.05.27, nvv, уточнения и подгонка под ежедневное обновление статистик # ! история изменений - в подвале # (!) для СКРЫТЫХ разделов нужны только эти данные: # из stat aHitP == 201661 p12m хиты за 12мес. # из stat aNamP == "Кадавр" # "0" (!) aNumP == 21 pNum место в aHits minT=200 # минимальное кол-во хитов текста "за 30 дней", дабы "прорехи штопать" (если есть;) hitL=0 # нижняя граница хитов "12мес" для отсечения от учёта неуспешных текстов и разделов # hitL=374 # !!! 2024.04.29 nHit=0 # число учитываемых топовых разделов в aHits gisF=1 # флаг "нужны гистограммы" nTxt=0 # кол-во отобранных текстов tNum=0 # число принятых ГОДНЫХ текстов hitT=0 # сумма хитов "за 30 дней" ripN=0 # число пустых суток (там же) ripP=0 # число разделов-кандидатов на "штопку" endH=0 # последний НЕ ноль "за 30 дней" rip1=0 # первый ноль (там же) hitY=0 # хиты произведения за "12мес" mifN=0 # счётчик призраков СИ (текстов нет, хиты есть) nErr=0 # счётчик проблемных файлов nGis=0 # счётчик строк в файле с гистограммами nLow=0 # счётчик текстов, выпавших из-за НЕ обновлённых статристик dEnd="2000.01.01" # макс.дата: 'datJ' (самая последняя - оперативная) dPre="2000.01.01" # макс.дата: 'datJ' (предыдущая - "рассчётная" errS="] step.0 (NO file)" if(ARGV[1]=="")exit # защита от случайного пуска # объявим массивыы для общего использования в подпрограммах split("",aDatI) # чьи-с ;) -v- max хиты split("",aDatM) # макс хиты каждой найденной пары дат split("",aDatN) # счётчики пар дат: "fresh"-"datJ" split("",aHitP) # хиты раздела за 12мес. (из aHits) split("",aNamP) # ник автора в aHits split("",aNumP) # место раздела в aHits split("",aErr) # описания замеченных проблем со статистиками split("",aLow) # массив текстов с хитами >= hitL, но < hStD split("",aSel) # в ячейках статистики: url,title,hits:all,12mon,mon0..monC-11,day0..day0-61 split("",aMig) # список timeStamp's статистик split("",aTxt) # перечень принятых текстов split("",aGis) # перечень гистограммных разделов split("",aStD) # перечень "хиты_текста datJ id_P id_T" split("",arr0) # рабочий массив split("",arr1) # рабочий массив # print hitL".hitL" mark="" # max dateTime statRefresh for(str2 in ENVIRON){ # ! регистр букв в имени переменной может быть любой str1=tolower(str2) # Temp и temp - РАЗНЫЕ имена для gAwk... if(str1=="fhit")fHit=ENVIRON[str2] # опорный aHits список if(str1=="mint")minT=ENVIRON[str2] # минимальные допустимые хиты текста (меньше - брак) if(!hitL)if(str1=="hitl")hitL=ENVIRON[str2] # нижняя граница хитов "12мес" (для отсечения) if(str1=="wdir")wDir=ENVIRON[str2]"\\" # место для всех ВЫХ.списков if(str1=="ratw")ratW=ENVIRON[str2] # минимальное кол-во топовых разделов из aHits # print "hitL."hitL,str1 } if(!ratW)ratW=0 # ratW сетится прискачивании, нужно для итога if(fHit==""){ # если вызов НЕ из CMD, aHits ищем сами str0="U:\\Jobs\\_siTop.#" while((getline line<str0)>0){ # ищем последнюю запись успешного скачивания этого списка # ;1A hits 5:xNam 457:xNum 104555:xPas 2023.06.15:hDat 505501:hMax 1051:hPag 1111:dnLd 0.08~ratW 2023.06.16:done 05:22:08~wrks 14:47 if(match(line,/^;1A .+ 20([\.0-9]{8}):hDat /,arr0))fHit=arr0[1] } close(str0) if(fHit==""){ errS="] step.0 NO *.aHits found in "str0 exit } fHit="U:\\Jobs\\20"fHit".aHits" # строим полное имя нужного списка # fHit="\\Jobs\\2024.05.21.aHits" # строим полное имя нужного списка topN=30000 # topN=200 } fErr=wDir".upDatBad.bStat.#" # список проблем и проблемных статистик (если-с;) fGis=wDir".upDatGis.bStat.#" # гистограммы посуточных хитов разделов с "прорехами" fLow=wDir".upDatLow.bStat.#" # список текстов с хитами >= hitL, но < hStD # 201661 21 846 3 k/kadawr "Кадавр" "no•comments" # ; hitP numP sizK sizN id_P "namP" "moto" # 1 2 3 4 5 6 7 print("? load "fHit,"...") # заполним массив атрибутов разделов в *.aHits int1=0 while((getline line<fHit)>0){ # fHit: like 2020.03.01.aHits split(line,arr0) # arr0[5] == k/kadawr p_id if(match(arr0[1],/^[0-9]+$/)){ # это строка данных раздела aHitP[arr0[5]]=arr0[1] # hitP arr0[1] == 201661 p12m хиты за 12мес. aNumP[arr0[5]]=arr0[2] # numP arr0[2] == 21 место в aHits aNamP[arr0[5]]=arr0[6] # namP arr0[6] == "Кадавр" int1++ if((!hitL)&&(int1==topN))hitL=arr0[1] # мин. достаточные хиты текста if((!nHit)&&(hitL-arr0[1]>0))nHit=int1-1 # число учитываемых топовых разделов в aHits if((arr0[4])&&(!nHit))r2do++ # должное число непустых разделов в $bStat # ;1A hits 6:xNam 456:xNum 103830:xPas 2024.05.26:hDat 463185:hMax 1043:hPag 899:add2 30663:n30k 294:h30k 1043:dnLd 0.33~ratW 2024.05.26:done 00:23:15~wrks 11:08 }else if(match(line,/^;1A .+ ([0-9]+):h30k .+ 20([\.0-9]{8}):done /,arr0)){ hitL=arr0[1] # дата скачивания aHits datH=arr0[2] # дата скачивания aHits infH=line # для итогового списка отобранных текстов } } close(fHit) # всё/не_всё, - старый список тогось # nHit=0 # for(int1=1;) # print("= loaded; nHit:"nHit"."hitL" minT:"minT) # всё готово, начинаем сканирование статистик # exit int7=(r2do-(r2do%100))/100 if(r2do%100)int7=int7"+" if(int1==0){ errS="] step.0 (no or empty %fHit%: "fHit " )" exit } # массив имён месяцев для преобразования их в числа с лидирующим нулём 01..12 mNum["Jan"]="01" # .1 January . Jan. 31 . winter wint mNum["Feb"]="02" # .2 February .Feb. 28/29 mNum["Mar"]="03" # .3 March . . Mar. 31 . spring sprn mNum["Apr"]="04" # .4 April . . Apr. 30 mNum["May"]="05" # .5 May . . . May. 31 mNum["Jun"]="06" # .6 June . . .Jun. 30 . summer summ mNum["Jul"]="07" # .7 July . . .Jul. 31 mNum["Aug"]="08" # .8 August . .Aug. 31 mNum["Sep"]="09" # .9 September Sep. 30 . autumn autm mNum["Oct"]="10" # 10 October . Oct. 31 mNum["Nov"]="11" # 11 November .Nov. 30 mNum["Dec"]="12" # 12 December .Dec. 31 . winter wint errS="" print("= loaded; nHit:"nHit"."hitL" minT:"minT) # всё готово, начинаем сканирование статистик tIni=systime() # exit } { # // -=- основной блок скрипта begs if(FNR==1){ # секция завершения работ с одним файлом и подготовки к работе со следущим if(NR!=1)chkSteps() # чем закончилась обработка предыдущего файла? step=0 # 0-владелец, 1-дата обновления, 2-id раздела, 3-разбор строк таблиц статистики fPth=FILENAME fNam=split(fPth,arr0,"\\") # NEW/NEXT входной файл as-is (с полным путём) fNam=split(arr0[fNam],arr0,".") # файл: чистое nam.ext (like "0~0.stat.htm") fNam=arr0[1] # fNam чистое имя (like "0~0" in "0~0.stat.htm") id_P=substr(fNam,1,1)"/"substr(fNam,3) if(id_P in aHitP){ # этот раздел ЕСТЬ в рейтинге "по хитам" numP=aNumP[id_P] hitP=aHitP[id_P] namP=aNamP[id_P] }else{ numP=0 hitP=999 # выясняется в stat namP="\""id_P"\"" # - "" - - "" - } inTab=0 # сначала - мы НЕ "в таблице" numT=0 # счётчик таблиц в файле статистики numR=0 # счётчик строк в текущей таблице selN=0 # счётчик ячеекк в строке таблицы int8++ # if(int8%100==0) print(sprintf(": %4s.%-4s",int8/100,int7),strftime("%H:%M:%S",systime()-tIni,-1)) if(int8%100==0) print(sprintf(": %4s.%-4s",int8/100,int7)) # оживляж else if(int8%10)printf(".") # оживляж... else printf(":") # оживляж } gsub(/( )+|\xA0+|[\0-\31]+/," ",$0) # цепочки " " и прочих "пробелов" -> " " (пробел) if(step==0) { # ищем (для контроля) ФИО автора # <h3>Статистика раздела "<a href=./>Влад</a>":</h3> if (match($0,/<h3>Статистика раздела \"<a href=\.\/>(.*)<\/a>\":<\/h3>/,arr0)) { if(arr0[1]==""){ errS="] step."step" (NO nick in: " fNam " )" nextfile }else namP=pack(arr0[1]) step++ # проверка ОК } }else if(step==1){ # вычленеие даты обновления статистики if(match($0,\ /<li><i>Статистика рассчитывается .+\. \(.+ (...) +([0-9]+) (..:..:..) (20[0-9][0-9])\)<\/i>/\ ,arr0)){ if(length(arr0[2])==1) arr0[2]="0"arr0[2] # причешем первые дни месяца "1" -> "01" ticS=mktime(arr0[4]" "mNum[arr0[1]]" "arr0[2]" 12 00 00") # тики на 12 часов даты статистики datS=arr0[4]"."mNum[arr0[1]]"."arr0[2] # дата обновления статистики timS=arr0[3] # время обновления статистики if(mark<datS"/"timS)mark=datS"/"timS step++ # дату статистики оптичили } }else if(step==2){ # ищем authID (!должен быть и совпадать с префиксом имени файла) # [<a href=http://top.mail.ru/pages?id=77427&period=0&date=2018-10-02&filter_type=0 # &filter=n/nosow_w_w&pp=20&gender=0&agegroup=0>по дням</a>] if (match($0,/\[<a href=http.+&filter=([0-9a-z]\/[\-0-9a-z_]+)&pp=.+>по дням<\/a>]/,arr0)) { if(id_P!=arr0[1]){ # это ПОЛНЫЙ криминал! errS="] step."step" ("arr0[1]" != fNam: " fNam " )" nextfile } step++ # проверка ОК } }else if(step==3){ # таблицы статистики, просмотр строк, сборка данных в ячейках if($0=="<!--------- Подножие ------------------------------->"){ # разбор закончен step++ nextfile } if(inTab){ # Мы ВНУТРИ таблицы, собираем строки таблицы с хитами текстов buf0=buf0" "$0 # gain inpLines to buf0, then check contents while((match(buf0,/<tr ?[^>]*>/))||(int0=index(buf0,"</tr"))){ # seek <tr .. </tr for tabRow if(RSTART){ # new/next line begs numR++ # счётчик строк buf0=substr(buf0,RSTART+RLENGTH) # del всё до начала строки таблицы <tr>, в т.ч. и его } if(int0=index(buf0,"</tr")){ # this line ends getSels(substr(buf0,1,int0-1)) # tabl_row -> arrow:sell_values buf0=substr(buf0,int0+4) # убрали эту строку из буфера и окультуриваем... id_T=aSel[0] # имя+расшир файла с текстом (или "./" для раздела) namT=aSel[1] # пока фактическое (as-is) название текста в статистике if((numT==1)&&(numR==2)){ # хиты по разделу (спец.обслуживание) if(!numP)hitP=aSel[3] # хиты раздела за "12мес" ЕСЛИ нет в aHits aMig[++nMig]=datS"_"timS" "datJ sprintf("%7s%8s %s %s %s"\ ,numP,hitP,fNam,id_P,namP) # момент обновления if((hitT-minT>0)&&(rip1!=0)&&((endH-rip1>0)||rip1==1)){ ripP++ # число разделов-кандидатов на "штопку" id_T="~" # prt 8-раздел: 'хиты за 30 дней' namT="\"<!>\"" selsOutG() # гистограмма: хитов много + есть "прореха" } }else{ # обычная строка статистики текста int0=split(id_T,arr0,".") if( int0!=2){} # sErr="zOrg" нарушен формат имени файла: name.ext else if(arr0[2]!="shtml"){} # sErr="xExt" расширенеие не то-с else if(gensub(/[\-0-9a-z_]/,"","g",arr0[1])!=""){} # sErr="vNam" левизна в имени файла else if(namT==""){} # sErr="tHdr" "пустое" название текста else if(minT-hitT>0){} # sErr="hLow" хитов таки мало else { # 0-"всё ОК" поток строк с текстами и хитами для выбора top1000 namT=pack(namT) # запакованное (свёрнутое!) название текста if(match(namT,/^""$/)){ namT=hitT":noNamT" hitT=2 }else{ tNum++ # число принятых ГОДНЫХ текстов } aTxt[++nTxt]=sprintf("%7s%8s %6s",hitT,hitP,numP)" "id_P\ " "arr0[1]" "namP" "namT" "fNam" "datJ # строка для итогового списка текстов aStD[nTxt]=datJ" "sprintf("%7s",hitT)" "id_P" "arr0[1] # "datJ хиты id_P id_T" if(hitT-aDatM[dGap]>0){ # максимум - только у принятых! aDatM[dGap]=hitT # <- max хиты, v- чьи-с ;) aDatI[dGap]=sprintf("%7s %6s %6s",hitP,numP,hitT)" "id_P" "arr0[1] } } if(minT-hitY>0){ # хиты за "12мес", дальше - хитов ещё меньше step=4 nextfile } } } } if(int0=index(buf0,"</table")){ # this tabl ends buf0=substr(buf0,int0+4) # update buf0 inTab=0 } }else{ # ищем начало таблицы if(int0=index($0\ ,"<table border=1 cellspacing=0 cellpadding=0><tr><td><td colspan=2><b>Итого</b></td>")){ numT++ # new table numR=1 # певая строка каждой таблицы - календарь хитов статистики раздела buf0=substr($0,int0+80) if(numT==1){ # 1-st table 1-st row -> get col-dates & so-on match(buf0,/<tr[^>]*>(.+)<\/tr[^>]*>/,arr0) # собственно строка с календарём getSels(arr0[1]) # но самую первую такую - разберём-с tic0=ticS # и привяжем дату к нулевому (самому левому) дню посуточных данных while(strftime("%d",tic0)!=aSel[16])tic0=tic0-86400 # сдвинем стат.дату к нулевому дню datJ=strftime("%Y.%m.%d",tic0-86400) # полная дата первого дня в интервале 30 дней dGap=datS"-"datJ aDatN[dGap]++ # счётчики "datJ" дат в статистиках if( dEnd<datJ) dEnd=datJ # оперативная 'datJ' if((dPre<datJ)&&(datJ<dEnd))dPre=datJ # предыдущая 'datJ' } inTab=1 # мы ВНУТРИ таблицы buf0="" # буфер чист! } } } } # // -=- основной блок скрипта ends function getSels(rowLn){ # разделение строки таблицы статистики на массив значений hitT=0 # + сумма хитов "за 30 дней" ripN=0 # число пустых суток (там же) endH=0 # последний НЕ ноль "за 30 дней" rip1=0 # первый ноль (там же) selN=0 # sells count split("",aSel) aSel[0]="" while(match(rowLn,/<td[^>]*>/)){ # это объявление ячейки selN++ # 0.1-имя/ссылка; хиты: 2-всего, 3-12мес, 4..15-заМес, 16..77-заСутки rowLn=substr(rowLn,RSTART+RLENGTH) # выкусим объявление ячейки f3n2=index(rowLn,"</td") # это конец ячейки f3s2=substr(rowLn,1,f3n2-1) # это сама ячейка (с возможными внутренними тегами) if(selN==1){ # в ПЕРВОЙ ячейке - название текста и ссылка на него match(f3s2,/<a href=([^>]+)>(.*)<\/a>/,f3a1) # выцепим и разложим: aSel[1]=f3a1[2] # название текста aSel[0]=f3a1[1] # ссылка на текст: name.shtml }else aSel[selN]=rmTags(f3s2) # в ПРОЧИХ ячейках - только значение ячейки, очищенное от тегов rowLn=substr(rowLn,f3n2) # выкусим оптиченную ячейку if((selN-16>0)&&(47-selN>0)){ hitT=hitT+aSel[selN] # сразу подсчитаем сумму хитов "за 30 дней" if(aSel[selN]==0){ # и уточним важные подробности ripN++ # + число пустых суток (там же) if(rip1==0)rip1=selN-16 # первый ноль "за 30 дней" }else endH=selN-16 # последний НЕ ноль (там же) } } hitY=aSel[3] # хиты произведения за "12мес" if(selN==77)return # row HAVE had 77 sells nextfile # битая таблица == битый файл } function rmTags(f2s1){ # удаление ВСЕХ тегов в литерале while(match(f2s1,/<\/?[a-zA-Z][1-6a-zA-Z]?[a-zA-Z]*[ \/]?[^>]*>/)) f2s1=substr(f2s1,1,RSTART-1) substr(f2s1,RSTART+RLENGTH) return(f2s1) } function selsOutG() { # отладка: на StdOut гистограмма значений массива aSel +маркировка "прорехи" int0=0 # +с посуточной шкалой +справочные сведения касаемо hSum=0 for(int1=17;int1<47;int1++){ if(aSel[int1]-int0>0)int0=aSel[int1] # ищем максимальные хиты за сутки hSum+=aSel[int1] # +фактическию сумму хитов "за 30 дней" } int0=length(int0"") ++nGis split("",arr1) # готовим (собираем гистаграмму) for(int1=1;int1<31;int1++){ str0=sprintf("%"int0"s",aSel[int1+16]) for(int2=1;int2<=int0;int2++){ # в виде горизонтальных строк цифр str2=substr(str0,int2,1) if((int2==int0)&&(aSel[int1+16]==0))str2="_" # ЭТО суточная "прореха" (0 хитов) arr1[int2]=arr1[int2] str2 } } str0=strftime("%d",tic0-86400) " " # строим шкалу времени; привязанную к границам for(int2=5;int2<30;int2+=5)str0=str0 strftime("%d",tic0-86400*int2) " " str0=str0 strftime("%d.%m.%Y",tic0-86400*30)" hSum="hSum aGis[++nGis]=str0 # оформляем всё от... # |19 15 10 05 31 26 21.01.2020 # пример посуточной шкалы времени aGis[++nGis]="v...:....v....:....v....:....v" # 31302922396567855______0629939 # пример самой нижней строки гистограммы (с "прорехой") for(int2=1;int2<=int0;int2++)aGis[++nGis]=arr1[int2] aGis[++nGis]="|...:....|....:....|....:....|" aGis[++nGis]=id_P"/"id_T" "namT" " fNam # ... и до } function pack(f1s1) { # мешающие chars -> нейтральные + cut too long + закавычить результат f1n1=split(f1s1,f1a1) f1s1=f1a1[1] # обихаживание пробелов... " " -> "•" for(f1n2=2;f1n2<=f1n1;f1n2++)f1s1=f1s1"•"f1a1[f1n2] f1s2="" # двойные кавычки -> """ while(f1n1=index(f1s1,"\"")){f1s2=f1s2 substr(f1s1,1,f1n1-1)"""; f1s1=substr(f1s1,f1n1+1)} f1s1=f1s2 f1s1 f1s2="" # "%" -> "%" while(f1n1=index(f1s1,"%")){f1s2=f1s2 substr(f1s1,1,f1n1-1)"%"; f1s1=substr(f1s1,f1n1+1)} f1s1=f1s2 f1s1 if(length(f1s1)>999){ # обрезка слишком длинных литералов f1n1=index(substr(f1s1,1000),"•") if(!f1n1)f1n1=1000 else f1n1=f1n1+999 # v-вместо обрезанного - справка о факте ;) f1s1=substr(f1s1,1,f1n1-1)"•(+"(length(f1s1)-f1n1)" chars)" } return ("\""f1s1"\"") # результат "закавычивается!" } function chkSteps() { # проверка чем закончилась обработка очередного файла? if((step==4)&&(errS=="")){ # всё штатно ("ОК") return }else{ if(errS==""){ # что-то не так, но нужно уточнить... if(step==3){ if(inTab==1){ # уточним проблему... if(selN!=77){ # row HAVE had 77 sells errS="] step."step" (selN:"selN" Tab:"numT" Row:"numR"{not 77}): " fNam " )" }else if((numT==1)&&(numR==2)){ errS="] step."step" (bad 1-st table 2-nd row in: " fNam " )" }else{ errS="] step."step" (unClosed table in: " fNam " )" } }else{ errS="] step."step" (no or bad table in: " fNam " )" } }else if(step==2){ errS="] step."step" (no or bad author's ID in: " fNam " )" }else if(step==1){ errS="] step."step" (no or bad refresh date:{"$0"}: " fNam " )" }else if(step==0){ errS="] step."step" (no partition`s owner in: " fNam " )" } } aErr[++nErr]=errS aMig[++nMig]="0000.00.00_00:00:00 _bad_file_"sprintf("%7s%8s %s %s %s"\ ,numP,hitP,fNam,id_P,namP) # этот файл "на вынос" aDatN["0000.00.00-_bad_file_"]++ # 2021.03.05-14:21:54 2021.03.04 29076 514 a/ass "Асс" # aBad[nErr]=datS"-"timS" "datJ sprintf("%6s%8s %s %s"\ # ,numP,hitP,id_P,namP) # заполняем массив моментов обновления статистик errS="" # и очистим флаг-инфо } } function mkRpt1(ln2rpt) { # дабы нужное отправлять и в отчёт, и на экран, и... print(ln2rpt) >fLst # список текстов print(ln2rpt) >fMig # список разделов print(ln2rpt) >fLow # список выпавшего # print(ln2rpt) >fRpt print(ln2rpt) } function mkRpt2(ln2rpt) { # дабы правильно отправлять нужное куда след... print("; "ln2rpt) >fMig # print(ln2rpt) >fRpt print(ln2rpt) } END{ # отстрелялись; ну почти... if(errS!=""){ print("") print(errS) # есть проблем-с => подудим exit 1 # и на выход с вещами } chkSteps() # чем закончилась обработка последнего файла? if(errS!=""){ print("") print(errS) # есть проблем-с => подудим exit 1 # и на выход с вещами } if(int8%100)print("") print(" == " nMig,strftime("%H:%M:%S"),strftime("~%H:%M:%S~",systime()-tIni,-1)) # проблем нет asort(aMig) # подготовка списка дата/времы обновления day01 asort(aTxt) # подготовка (прямая сортировка) и выдача (в обратном порядке!) списка asort(aStD) split(aStD[nTxt],arr0) dStD=arr0[1] # опорная дата расчёта /dEnd/ hStD=hitL # def: нижняя граница хитов "по обновлению" == нижняя граница хитов по aHits for(int1=nTxt;int1>0;int1--){ split(aStD[int1],arr0) if((hStD-arr0[2]<0)&&(dStD!=arr0[1]))hStD=arr0[2]+1 # новая граница "по обновлению" } for(int1=nTxt;int1>0;int1--){ # вычленение и выдача в список split(aTxt[int1],arr0) if((hStD-arr0[1]>0)&&(hitL-arr0[1]<=0)){ nLow++ # выпавших их-ха не обновления значимых разделов print(aTxt[int1]) >fLow } # aTxt[++nTxt]=sprintf("%7s%8s %6s",hitT,hitP,numP)" "id_P" "arr0[1]" "namP" "namT" "fNam" "datJ # строка для итогового списка текстов # printf("%s %s %7s %s %s\n",hStD,(hStD-arr0[1]>0),arr0[1],hitL,(hitL-arr0[1]<=0)) > "x.x" } # print hitL".hitL",hStD".hStD" # if(hitL-hStD<0)hitL=hStD # print hitL".hitL",hStD".hStD" split("",aSel) # сборка итогового отчёта split(aMig[nMig],arr0) keep=" = " sEnd=substr(arr0[1],1,10) # дата самого последного обновления статистик dEnd=arr0[2] # последний datJ (верхняя граница расчёта) hEnd=aDatM[str0] # макс. хиты текста за datJ nEnd=1 # число статистик с datJ hPre=0 # макс. хиты текста ВНЕ datJ nPre=0 # число статистик ВНЕ datJ nSel=1 str0=sEnd"-"dEnd # самая свежая (последняя) пара дат datS-datJ aSel[nSel]=str0 sprintf("%7s %4.1f%",aDatN[str0],aDatN[str0]*100/nMig) keep aDatI[str0] frst=0 # первая строка итоговой сводки с "xDel/=Keep" == "=" for(int1=nMig-1;int1>0;int1--){ # сканируем aMig собирая отчёт split(aMig[int1],arr0) arr0[1]=substr(arr0[1],1,10) if(str0!=arr0[1]"-"arr0[2]){ # перешли границу суток в датах обновления if(!frst&&(arr0[2]!=dEnd))frst=nSel # у этой строки возможно будет смена "=" на "x" nSel++ str0=arr0[1]"-"arr0[2] # новая пара дат datS-datJ if(aDatI[str0]==""){ # если в ней нет значимых текстов, то... aDatI[str0]=" ~ ~ ~ ~ ~" # отметим факт keep=" x " # и назначение: "на удаление" }else if(arr0[2]!=dEnd)keep=" x " # и назначение: "на удаление" aSel[nSel]=str0 sprintf("%7s %4.1f%",aDatN[str0],aDatN[str0]*100/nMig) keep aDatI[str0] } if(arr0[2]==dEnd){ if(hEnd-aDatM[str0]<0)hEnd=aDatM[str0] # макс. хиты текста за datJ nEnd++ # число статистик с datJ }else{ if(aDatM[str0]&&(hPre-aDatM[str0]<0))hPre=aDatM[str0] # макс. хиты текста ВНЕ datJ nPre++ # число статистик ВНЕ datJ } } if(hStD-hPre>0){ # в Pre НЕТ хитового текста => рейтинг собирается! split(aSel[frst],arr0,"% = ") # у этой строки НУЖНО сменить "="... aSel[frst]=arr0[1]"% x "arr0[2] # ... на "x" if(datH==strftime("%y.%m.%d"))vOk="v" else vOk="~" preF=wDir dEnd "." vOk vOk="mod:"vOk }else{ # иначе - увы... preF=wDir dEnd ".!" # собирать НЕЛЬЗЯ! vOk="mod:!" } fLst=preF".lst.bStat" # итоговый список текстов-кандидатов siTopTexts fMig=preF".mig.bStat" # сортированные моменты обновления статистик fStD=preF".std.bStat" # сортированные моменты обновления статистик if(nErr)for(int1=1;int1<=nErr;int1++)print(aErr[int1]) >>fErr if(gisF){ # заказана гистограмма, выдадим, что нашлось if(nGis)for(int1=1;int1<=nGis;int1++)print(aGis[int1]) >fGis else print("") >fGis } for(int1=nTxt;int1>0;int1--)print(aTxt[int1]) >fLst # ОТОБРАННЫЕ тексты # . . . . . 9560 365732 6 k/kadawr n "Кадавр" "Псион" k~kadawr 2021.04.03 print("; hitT.1 hitP.2 numP.3 id_P.4 id_T.5 \"namP\".6 \"namT\".7 id_F.8 datJ.9") >fLst print("; hitT.1 hitP.2 numP.3 id_P.4 id_T.5 \"namP\".6 \"namT\".7 id_F.8 datJ.9") >fLow mkRpt2( "upDat_datS 1-st_day numS xDel/=Keep hitP numP hitT id_P id_T") for(int1=nSel;int1>0;int1--)mkRpt2(aSel[int1]) print("; datS_timS.1 datJ.2 numP.3 hitP.4 id_F.5 id_P.6 \"namP\".7") >fMig for(int1=1;int1<=nMig;int1++)print(aMig[int1]) >fMig # 2021.04.04_00:22:48 2021.04.03 186 15887 a~arh a/arh "Арх" # upDat_datS 1-st_day numS xDel/=Keep hitP numP hitT id_P id_T # 2021.04.17-2021.04.16 4 0.0% x ~ ~ ~ ~ ~ # 2021.04.18-2021.04.17 3 0.0% x ~ ~ ~ ~ ~ # 2021.04.21-2021.04.20 1985 6.6% x 200017 14 20113 z/zhan flibustain # 2021.04.22-2021.04.21 19691 65.7% = 791291 1 61567 m/metelxskij_n_a wtt-2 # 2021.04.23-2021.04.21 8266 27.6% = 241332 13 29405 r/raba_b_i molitva-113 print(infH) >fLst print(infH) >fMig print(infH) >fLow # print(infH) >fRpt # ;2B stat 2021.04.26:sEnd 1457:nPre 20102:hPre 1457:miss 300:minT 548:hitL 30075:nHit last~01:01:31~ mkRpt1(";2B stat"sprintf(" %s:sEnd %5s:nPre %6s:hPre %5s:miss"\ ,sEnd,nPre,hPre,nMig-nEnd)" "minT":minT "hStD":hitL "nHit":nHit last~"substr(mark,12)"~") # ;2C scan 2021.04.24:dEnd 28554:nEnd 60688:hEnd 30011:nMig 1592:tNum 10:nGis 29173:nLow mod:! OkV:95.1% str1=substr(sprintf("%1.1f",nEnd*100/nMig),1,4) mkRpt1(";2C scan"sprintf(" %s:dEnd %5s:nEnd %6s:hEnd %5s:nMig %s:tNum %s:nGis %s:nLow %s OkV:%s% "\ ,dEnd,nEnd,hEnd,nMig,tNum,ripP,nLow,vOk,str1)) # ;2D =Пн= 1116:tNum OkV:89.0% mod:v 2024.04.28:dEnd 0:sNul 2024.04.29:done 19:50 00:15:09~wrks 1.06~ratW 32:dnLd # 2020.02.20, nvv, первые прикидки "что и как НАДА делать-с" # 2020.03.28, nvv, рабочий макет (будем посмотреть...) # 2020.05.25, nvv, aHits - 120 pages-! => midS=8000 -> 9600; minS=9750 -> 11700 # 2020.06.25, nvv, minor updates # + это излишне: fDel=wDir"]bStat.del" - список списков оставляемых статистик # 2020.05.31, nvv, полнота нужной выборки вычисляются по % в наличных статистиках: # >97% - всё ОК (выборка достаточна для сборки рейтинга), на завтра - 1 последний список # >75% - 2-е сутки 3-х суточного такта, на завтра - 2 последних списка # <=75% - 1-е сутки, на завтра - 1 последний список # 2020.07.16, nvv, битые статистики теперь просто фиксируются в "]bStat.bad", # не прерывая весь процесс + уточнён алгоритм разграничения списков: xDel/=Keep # 2020.08.29, nvv, мелкая косметика # 2020.09.07, nvv, имя файла *.aHits (если пуста переменная fHist) ищется в общем логе "_siTop.#" # 2020.09.18, nvv, слегка перепахано для более тонкого разбора наличности # + итоговый отчёты см. переменную wDir # + итоговый fLst формируется сразу отсортированный и оформленный # + в конце строк с атрибутами отобранных текстов - datJ (1-й_полный_день в прошлое) # 2020.10.07, nvv, переделано (упорядочено) накопление, оценка и оформление итогов по датам # (для оценки пригодности к рассчёту, см. dEnd и dPre) # 2020.11.03, nvv, добавленена работа с хитами 12мес раздела # 2020.11.07, nvv, исправлена мелкая неточность вчисления "недостающего" в итоговом отчёте # 2021.01.09, nvv, исправлена сборка масива aMig (для fTim даты обновления и Ко) # + изменен учёт и оформление разделов с низкими хитами за "12мес." или за "30дн." fLow # 2021.01.29, nvv, minor turning # 2021.03.25, nvv, в итогах явно указывается % годных к расчёту статистик # 2021.04.09, nvv, серьёзно переделано (логика работы и унификация) # 2021.04.09, nvv, minor changes # 2021.05.02, nvv, косметика средней тяжести... ;) # 2021.06.18, nvv, иной формат *.mig.bStat # 2022.02.17, nvv, мелкое улучшение оживляжа + устранена мелкая неточность логики # 2022.04.13, nvv, для расчёта дата aHits /см. datH/ должна быть "сегодня" (== "v", иначе "~") # 2022.05.02, nvv, сводка по *.!.mig.bStat теперь в шапке этого списка # 2022.12.30, nvv, сменил разрешение экрана /меньше пикселей/, пришлось менять оживляж # 2023.03.09, nvv, was: set minT=300, now: 200 # 2023.06.22, nvv, нет в aHits(?), возьмём прямо из stat # 2024.05.04, nvv, теперь НЕ обновлённые статистики с хитовыми текстами поднимают нижнюю }
Имя файла скрипта: "bStat.cmd" V-текст скрипта-V- - - - - - - - - @if not defined pMod @echo off set nJob=bStat echo %date% %time:~0,8% %nJob% Begs :: основной и резервный URL Самиздата (желательно работать с резервом) if NOT defined siUrl if exist \siUrl.budclub set siUrl=budclub.ru if NOT defined siUrl set siUrl=samlib.ru rem 2024.09.01, nvv, восстановлена полная выдача в общий лог jRpt rem ! история изменений - в подвале set jDat=%date% :: примерно 1000 записей /ограничители для отладки ! НЕ нужны в штате/ rem set hitL=2200 :: примерно 200 записей rem set hitL=6400 :: примерно 3000 записей rem set hitL=1200 rem wDir - общее рабочее место set wDir=%~d0\Jobs\ rem zDir - место для сегодняшних итоговых списков set zDir=%~d0\Stor\wOld\%jDat%\ rem bStat.cmd - "обновлятель" статистик 30k разделов +список самых посещаемых за 30 дней произведений rem ! обязателен список U:\Jobs\20??.??.??.aHits rem = *.lst.bStat - итоговый "черновой" список топовых текстов {2021.04.20.v.lst.bStat} rem + *.mig.bStat - отсортированный по моментам список файлов статистик{2021.04.20.v.mig.bStat} rem ~ .upDatBad.bStat.# - список проблемных разделов {в этот раз} rem ~ .upDatGis.bStat.# - список разделов с прорехами в статистике rem ~ .upDatLow.bStat.# - список разделов, набравших h30k+ хитов, но меньше УТОЧНЁННОГО hitL rem после запуска и проверки комплектности: rem - если нет или пусто в #bStat или нет файла *.mig.bStat - тупо скачивается всё по aHits rem иначе смотрится на наличие сегодняшнего файла %jDat%.upd.2do.2do {"надо сделать"} rem есть - значит была авария и следует продолжит с места, где прервали rem нет - смотрится расклад в: fHIt и fMig rem NB. ДО начала скачивания на экран выдаётся оный расклад и запрашивается явное "ОК" {"Y"} rem OS windows - должны быть настроены системные переменные окружения: rem %time% - HH:MM:SS,tt HH<=9 -> "HH" == " H" лидирующий пробел для часа меньше 10 rem %date% - YYYY.mm.dd rem основные сеты и прочая подготовка инструментария... set errInf= rem dnLd - счётчик /формально/ успешно скачанного {НЕ 0b} set dnLd=0 rem ratW - темп скачивания {секунд на один файл в среднем} set ratW=0 rem cNum - счётчик-индикатор числа скачиваемых статистик set cNum=0 rem minT - минимальные допустимые хиты текста {меньше - брак/отсев/etc - для bStat.awk} set minT=200 rem jDir - место для оперативных файлов set jDir=%wDir%#%nJob%\ if NOT exist %jDir%*.* mkDir %jDir% if errorLevel 1 set errInf=fail mkDir %jDir% & goto errExit rem aChk - анализатор текущего расклада по спискам, выдаёт что следует: грузить/удалить/не_трогать set aChk=%~dpn00.awk rem aScn - сканер статистик, строит черновой список топовых текстов {и *.mig.%nJob% в частности} set aScn=%~dpn0.awk rem эти скрипты обязаны быть for %%A in (%aChk% %aScn%) do if NOT exist %%A set errInf=NO %%A found & goto errExit rem jRpt - общий отчёт с итоговыми сводками процессов set jRpt=%wDir%_siTop.# rem sNul счётчик "статистик недоступно" {скачано 0b} set sNul=0 rem wGetSiz - размер скачанного файла {default 1b минимум} set wGetSiz=1 rem wGetTot - размер скачанного файла {default 1b минимум} rem set wGetTot=0 rem bErr - оперативный {обнуляемый} файл для пометок CMD{скачивание} + AWK{сканирование} set bErr=%wDir%.upDatBad.%nJob%.# rem f2do - список "НАДО сделать сегодня" set f2do=%wDir%%jDat%.upd.2do.2do rem fPas - список "игнорировать" /пропустить/ set fPas=%wDir%%jDat%.upd.pas.2do rem fDon - список "УЖЕ сделано сегодня" set fDon=%wDir%%jDat%.upd.don.2do rem rDon - число уже сделанного set rDon=0 rem fSta - файлы статистики в #bStat set fSta=%jDir%?~*.stat.htm :: nSuf - файл статистики nvv /общая часть/ set nSuf=n~nosow_w_w.stat.htm :: nFil - полное имя обновляемого файла статистики nvv set nFil=%jDir%%nSuf% :: nDat - последняя наличная дата статистики nvv в формате "yyyy.Mns.d" /like: "2022.Jul.3"/ set nDat= :: nDir - склад для накопления nvv.stats /должен быть/ set nDir=%~d0\Stor\nvv\ if NOT exist %nDir%*.* mkDir %nDir% if errorLevel 1 set errInf=fail mkDir %nDir% & goto errExit :: выясним последнюю дату обновления статистики nvv на складе для for %%A in (%nDir%*%nSuf%) do set tmp0=%%A if defined tmp0 ( for /F "tokens=1-9,*" %%A in ( 'gawk.exe "{if(match($0,/<li><i>.+\. \(... (...) (..) ..:..:.. (20..)\)<\/i>/,a)){print(a[3],a[1],a[2]);exit}}" %tmp0%' ) do set nDat=%%A.%%B.%%C ) :: и обрадуем наблюдатеоя касаемо echo nDat:%nDat% if NOT exist %zDir%*.* mkDir %zDir% if errorLevel 1 set errInf=fail mkDir %zDir% & goto errExit :: fHit - ВХОДНОЙ список *.aHits {последний из и запомнить его имя} ОБЯЗАТЕЛЕН set fHit= for %%A in (%wDir%20??.??.??.aHits) do set fHit=%%A if NOT defined fHit set errInf=20??.??.??.aHits NOT found & goto errExit rem ;1A hits 6:xNam 453:xNum 103786:xPas 2024.05.10:hDat 446433:hMax 1043:hPag 1050:add2 30591:n30k 280:h30k 1081:dnLd 0.11~ratW 2024.05.10:done 01:15:04~wrks 10:58 for /F "tokens=1-2,*" %%A in ( 'gawk.exe "{if(match($0,/^;1A .+ ([0-9]+):n30k ([0-9]+):h30k /,a)){print(a[1],a[2]);exit}}" %fHit%' ) do ( set hitN=%%A set h30k=%%B ) if NOT defined hitL set hitL=%h30k% for /F "tokens=1-2,*" %%A in ( 'gawk.exe "{if(match($0,/^;1A .+ ([0-9]+):hMax .+ ([^ ]+):done /,a)){print(a[1],a[2]);exit}}" %fHit%' ) do ( set hMax=%%A set hitD=%%B ) rem э ключи fHit: hMax и hitD set tmp0=* if .%hitD% == .%jDat% set tmp0== echo %tmp0% fHit:%fHit% - - - - %hitD%:hitD %hitN%:hitN %hitL%:hitL rem fMig - отсортированный и размеченный список дат обновления статистик 2022.01.21.!.mig.bStat ЖЕЛАТЕЛЕН set fMig= for %%A in (%wDir%20??.??.??.?.mig.%nJob%) do ( set fMig=%%A set migD=%%~tA ) if defined migD set migD=%migD:~0,10% if .%migD% == .%jDat% ( echo = fMig:%fMig% - %sEnd%:sEnd %nPre%:nPre ) else ( set fMig= set migD= echo X fMig: -- NO or OLD ) :: смотрим дату файлов статистик по r~raba_b_i.stat.htm set rabD= for %%A in (%jDir%r~raba_b_i.stat.htm) do set rabD=%%~tA if defined rabD set rabD=%rabD:~0,10% if .%rabD% == .%jDat% ( echo = staF:%rabD% ) else ( set rabD= echo X staF: -- NO or OLD ) :: -1 rabD пусто /сегодняшних статистик нет/ & migD есть /сегодняшний/ - криминал! if defined migD if NOT defined rabD set errInf=err: NO 2day *.stat`s BUT is 2day fMig & goto errExit rem НЕ сегодняшние 2do точно НЕ нужны! разбипаемся касаемо сегодняшних set c2do=0 for %%A in (%wDir%*.2do) do call :chkDel2do %%A if defined errInf set errInf=%errInf% & goto errExit :: если НЕ падало уже начатое, то идём начинать... if %c2do% == 0 goto beg2day :: таки начинали, но списков 2do некомплект! НЕ хорошо-с... if NOT %c2do% == 3 set errInf=NOT 3 2day.*.2do files & goto errExit :: c2do == 3 /упало в процессе скачивания, надо бы продолжить.../ set m2do=3 for /F "tokens=1-9,*" %%A in ('gAwk.exe -f %aChk%') do ( set rDon=%%A set r2do=%%B ) set j2do=reSume set jInf=RESUME dnLding :: - выдать сводку "сделано/осталось" - req - ВОЗОБНОВИТЬ! echo [!] f2do{%s2do%}: %rDon%:done %r2do%:2do goto reqOK :beg2day rabD есть & migD пусто /упало при сборке списка/ - строим mig НЕ глядя! if NOT defined migD if defined rabD ( echo ! NO fMig, but upDated staF, HAVE to scan staF... call :reCreMig if defined errInf goto nExit goto ending ) :: ОК, НЕ законченного нема, а что исть? set m2do=1 for /F "tokens=1-9,*" %%A in ( 'gawk.exe -f %aChk%' ) do ( set nPas=%%A set nDel=%%B set nUpd=%%C set r2do=%%D ) if "%nPas%" == "]" ( set errInf=err in gAwk %m2do%:m2do %nDel%:nDel %nUpd%;nUpd %r2do%:r2do & goto errExit ) :: если СЕГОДНЯШНИЙ собран по СЕГОДНЯШНЕМУ fHit - делать нечего - озадачим... if NOT %r2do% == 0 goto next0 if defined pMod ( echo == all is done today already goto :eof ) echo NOTHING to do NOW: %nDel%:nDel %nUpd%;nUpd %r2do%:r2do echo ?WHAT do you want repeat: dnLd OR Scan set tmp0= echo ?ok to goOn [L/S] == y set /p tmp0=?[no]? if /i %tmp0%. == L. ( echo Ok, REPEAT files dnLoading for /F %%A in ('gawk.exe "BEGIN{print(systime());exit}"') do set wrks=%%A goto dlHist ) if /i %tmp0%. == S. ( echo Ok, REPEAT files Scanning call :reCreMig if defined errInf goto nExit goto ending ) set errInf=job canceled & goto errExit :next0 если нет файла fMig или он НЕ сегодняшний, нужно скачивать ВСЁ if %nPas% == -- ( set j2do=dlHist set jInf=DnLd ALL %r2do% goto reqOK ) :: со свежим aHits нужно лишь удалить ненужное и притащить отсутствующее set j2do=updMig set jInf=fresh: %nDel%:nDel %nUpd%;nUpd %r2do%:r2do :reqOK что можно и следует делать, определились, надо запросить "добро" на... echo [!] HAVE to %jInf% files set tmp0= echo ?ok to goOn [yes] == y if defined pMod goto noReq set /p tmp0=?[no]? if /i NOT %tmp0%. == y. ( set errInf=job canceled & goto errExit ) :noReq таки нада работать... wrks - общее время работы процесса /после "y" в ответ на запрос/ for /F %%A in ('gawk.exe "BEGIN{print(systime());exit}"') do set wrks=%%A goto %j2do% :updMig подготовка к выборочному по fMig скачиванию статистик set m2do=2 gawk.exe -f %aChk% if errorLevel 1 set errInf=err in gAwk with %m2do%:m2do & goto errExit rem список ошибок должно освобождать от старья echo. >nul 2>%bErr% goto reSume :dlHist подготовка к скачиванию всех годных статистик по списку в fHit set m2do=2 gawk.exe -f %aChk% if errorLevel 1 set errInf=err in gAwk with %m2do%:m2do & goto errExit :: проверяем: создаём/чистим рабочий каталог if NOT exist %jDir%*.* ( mkDir %jDir% if errorLevel 1 set errInf=fail mkDir %jDir% & goto errExit ) if exist %jDir%*.* ( :: !!! erase /Q/F %jDir%*.* if errorLevel 1 set errInf=fail erase %jDir%*.* & goto errExit ) rem список ошибок должно освобождать от старья echo. >nul 2>%bErr% :reSume (ре)старт скачивания, нужны: f2do и fDon скачивается разницы (есть в первом, но нет во втором) set m2do=4 :: мало ли что, без f2do ловить нечего! if NOT exist %f2do% set errInf=NO %f2do% no dnLd continue & goto errExit rem красивый оживляж уместен всегда! set begT=%time:~0,8% echo ~ curDLjob: %rDon%:nDon %r2do%:r2do %begT% :: а кратно ли 100 число в r2do? for /F %%A in ('gawk.exe "BEGIN{print(%r2do%%%100);exit}"') do set tmp0=%%A set /a jMax=%r2do%/100 :: если НЕ кратно, то добавим плюсик к скачиваемым сотням if NOT %tmp0% == 0 set jMax=%jMax%+ set jMax=%jMax% . set jMax=%jMax:~0,5% rem запустим "таймер" качалки for /F %%A in ('gawk.exe "BEGIN{print(systime());exit}"') do set r100=%%A set ratW=%r100% for /F "tokens=*" %%A in ('gAwk.exe -f %aChk%') do ( if errorLevel 1 set errInf=gawk err: %%A & goto nExit call :reqSfil %%A if defined errInf goto nExit ) rem остановим "таймер" качалки время работы в секундах for /F %%A in ('gawk.exe "BEGIN{print(systime()-%ratW%);exit}"') do set ratW=%%A rem среднее время скачивания файла в секундах if %dnLd% == 0 (set ratW=0) else ( for /F %%A in ('gawk.exe "BEGIN{print(sprintf(\"%%3.2f\",%ratW%/%dnLd%));exit}"') do set ratW=%%A ) echo. echo. == %cNum% %begT%-%time:~0,8% %ratW%~ratW rem если дошли досюда - скачивание ОК call :reCreMig if defined errInf goto nExit goto ending :ending выцепим главные итоги разбора статистик rem ;2B stat 2021.04.26:sEnd 1457:nPre 20102:hPre 1457:miss 300:minT 548:hitL 30075:nHit last~01:01:31~ for /F %%A in ('gawk.exe "{if(match($0,/ ([0-9]+):miss / ,a))print(a[1])}" %fMig%') do set miss=%%A rem ;2C scan 2021.04.24:dEnd 19719:nEnd 60688:hEnd 30012:nMig 1657:tNum 11:nGis 29154:nLow mod:! OkV:65.7% for /F %%A in ('gawk.exe "{if(match($0,/ ([0-9]+):tNum / ,a))print(a[1])}" %fMig%') do set tNum= %%A for /F %%A in ('gawk.exe "{if(match($0,/ ([\.0-9]+):dEnd /,a))print(a[1])}" %fMig%') do set dEnd=%%A for /F %%A in ('gawk.exe "{if(match($0,/ mod:(.) / ,a))print(a[1])}" %fMig%') do set mod=%%A for /F %%A in ('gawk.exe "{if(match($0,/ OkV:([0-9\.]+)%%/,a))print(a[1])}" %fMig%') do set OkV=%%A set tNum=%tNum:~-4% rem если грандов обнесли - готовый список использовать НЕЛЬЗЯ! if "%mod%" == "!" ( set jYes==NO set mark=~ ) else ( set jYes==OK set mark== ) rem преобразуем секунды в время работы {в обычном формате "чч:мм:сс"} for /F %%A in ('gawk.exe "BEGIN{print(strftime(\"%%H:%%M:%%S\",systime()-%wrks%+46800));exit}"') do set wrks=%%A rem оформим подвал списка... соственно сборка закончена; jLst - итоговый список топовых текстов gawk.exe "BEGIN{printf(\";2D %%s \",strftime(\"%mark%%%a%mark%\",systime()));exit}" >>%jLst% echo.^ %tNum%:tNum ^ OkV:%OkV%%% ^ mod:%mod% ^ %dEnd%:dEnd ^ %sNul%:sNul ^ %jDat%:done ^ %time:~0,5% ^ %wrks%~wrks ^ %ratW%~ratW ^ %dnLd%:dnLd >> %jLst% echo = itog ^ %tNum%:tNum ^ %sNul%:sNul ^ %ratW%~ratW ^ %jDat%:done ^ %wrks%~wrks ^ %time:~0,5% rem и в общий отчёт ентот итог занесть нада-с gawk.exe "{if(match($1,/^;2[BCD]$/))print($0)}" %jLst% >> %jRpt% rem и в fMig строку ;2D тож gawk.exe "{if(match($1,/^;2D$/))print($0)}" %jLst% >> %fMig% rem уложим свежак в склад на полочку-с... for %%A in (%wDir%*.%nJob%) do ( copy /b /y %%A %zDir% > nul if errorLevel 1 set errInf=fail copy %%A to %zDir% & goto nExit ) rem уложим туда же замеченные "дыры" и "недобрало", ЕСЛИ сборка ВОЗМОЖНА if "%mod%" == "v" ( copy /b /y %wDir%.upDatGis.bStat.# %zDir%%dEnd%.%mod%.gis.%nJob% > nul if errorLevel 1 set errInf=fail copy .upDatGis.bStat.# to %zDir% & goto nExit copy /b /y %wDir%.upDatLow.bStat.# %zDir%%dEnd%.%mod%.low.%nJob% > nul if errorLevel 1 set errInf=fail copy .upDatLow.bStat.# to %zDir% & goto nExit ) rem подудим где нада "готово-с!" set itog=%fMig% :nExit если было проблем-с - известим всяко (особливо при запуске "с выключение компа") if defined errInf echo !?. %errInf% & goto :eof rem как оказалось, нулевые файлы таки заводятся иногда, проверим и прибьём найденное for /F %%A in ( 'dir /a:-d /-c /o:s %fSta% ^| gawk "{if(NR>5)if($3>0){print NR-6;exit}}"' ) do set nulF=%%A if NOT %nulF% == 0 ( echo finds: %nulF% zero file{s} *.stat.htm, erasing... for /F %%A in ( 'dir /a:-d /-c /o:s %fSta% ^|gawk "{if(NR>5){if($3==0){print $4}else{exit}}}"' ) do ( erase %jDir%%%A if errorLevel 1 set errInf=fail erase %%A & goto :eof ) ) rem <li><i>Статистика рассчитывается раз в сутки. (Thu May 18 02:05:32 2023)</i> :: смотрим дату обновления свежескачанной статистики nvv for /F "tokens=1-9,*" %%A in ( 'gawk.exe "{if(match($0,/<li><i>.+\. \(... (...) (..) ..:..:.. (20..)\)<\/i>/,a)){print(a[3],a[1],a[2]);exit}}" %nFil%' ) do ( set tmp0=%%A.%%B.%%C set tmpA=%%A set tmpB=%%B set tmpC=%%C ) :: НЕ изменилась в сравнении с уже имещщейся - значит и суетиться касаемо не надо if %nDat%. == %tmp0%. goto nvvOk :: ! иная дата, перекодируем месяц, построив дату в стандартном формате "гггг.мм.дд" if %tmpB% == Jan set tmpB=01 if %tmpB% == Feb set tmpB=02 if %tmpB% == Mar set tmpB=03 if %tmpB% == Apr set tmpB=04 if %tmpB% == May set tmpB=05 if %tmpB% == Jun set tmpB=06 if %tmpB% == Jul set tmpB=07 if %tmpB% == Aug set tmpB=08 if %tmpB% == Sep set tmpB=09 if %tmpB% == Oct set tmpB=10 if %tmpB% == Nov set tmpB=11 if %tmpB% == Dec set tmpB=12 :: +добавляем /при нужде/ лидирующий ноль в день месяца if %tmpC:~1,1%. == . set tmpC=0%TmpC% :: и прикапываем... echo nDat: %nDat% - %tmp0% rem echo copy /b %nFil% %nDir%%tmpA%.%tmpB%.%tmpC%.%nSuf% copy /b %nFil% %nDir%%tmpA%.%tmpB%.%tmpC%.%nSuf% >nul rem echo run: D:\#ProgFile\Viewer\Viewer.exe %nDir%%tmpA%.%tmpB%.%tmpC%.%nSuf% echo ! new NVV.stat, use U:\zNvvStat.cmd :nvvOk rem set /a wGetTot=%wGetTot:~0,-3%.%wGetTot:~-3% + 500 echo %jDat% %time:~0,8% %~nx0 Ends (%dnLd%:dnLd %miss%:miss jYes=%jYes%) goto :eof :reqSfil 2do id_P - обслуживание раздела согласно операции 2do /+оживляж +пополнение fDon/ set /a cNum+=1 set id_P=%2 set wFil=%jDir%%id_P:~0,1%~%id_P:~2%.stat.htm set wUrl=%siUrl%/%id_P%/stat.shtml rem 1 - pas - "-" - пропустить /даже если нету-с/ set tmp0=- if %1 == 1 goto show rem 3 - del - "X" - удалить /если есть/ if %1 == 3 ( set tmp0=- if exist %wFil% ( set tmp0=x erase /F/Q %wFil% if errorLevel 1 set errInf=fail erase %wFil% & goto :eof ) goto show ) rem 2 - upd - "*" - если нет - скачать if exist %wFil% ( set tmp0=~ goto show ) set tmp0=. call wGetUrl2fil.cmd %wUrl% %wFil% if defined errInf goto :eof rem set /a wGetTot+=%wGetSiz% if %wGetSiz% == 0 ( set /a sNul+=1 echo x sNul %wUrl% >> %bErr% erase /F/Q %wFil% if errorLevel 1 set errInf=fail erase %wFil% & goto :eof ) :show echo %* >> %fDon% if "%cNum:~-1%" == "0" set tmp0=%cNum:~-2,1% gawk.exe "BEGIN{printf(\"%tmp0%\");exit}" if NOT "%cNum:~-2%" == "00" goto :eof set tmp0= %cNum% set tmp0=%tmp0:~-6,4%.%jMax% for /F "tokens=1-9,*" %%J in ( ' gawk.exe "BEGIN{s=systime();printf(\"%%s %%9.2f\",s,(s-%r100%)/100);exit}" ' ) do ( set r100=%%J set tmp0=%tmp0% %%K ) echo. %tmp0% f/s goto :eof :reCreMig разбор содержимого файлов статистики, сначала убираем точно устаревшее когда-то ранее for %%J in (%wDir%*.old) do ( erase /F/Q %%J if errorLevel 1 set errInf=fail erase %%J & goto :eof ) rem двигаем в .old то, что устареет сейчас for %%J in (%wDir%*.%nJob% %wDir%*.2do) do ( move /y %%J %%J.old if errorLevel 1 set errInf=fail move %%J 2old & goto :eof ) :noUpdNow собственно построение с нуля jLst и fMig echo ! minT.%minT% hitL.%hitL% wDir.%wDir% fHit.%fHit% gawk.exe -f %aScn% %jDir%*.stat.htm if errorLevel 1 set errInf=fail scaning *.stat.htm rem затем выявляем свежак jLst - итоговый список годных "начерно" текстов, набравших minT хитов за 30 дней set jLst= for %%J in (%wDir%20*.lst.%nJob%) do set jLst=%%J if NOT defined jLst set errInf=fail mk 20*.lst.%nJob% & goto :eof rem и свежак fMig - итоговый список годных "начерно" текстов, набравших minT хитов за 30 дней set fMig= for %%J in (%wDir%20*.mig.%nJob%) do set fMig=%%J if NOT defined fMig set errInf=fail make 20*.mig.%nJob% goto :eof :chkDel2do %%A НЕ сегодняшние 2do точно НЕ нужны! if /i %1 == %f2do% set /a c2do+=1 & goto :eof if /i %1 == %fDon% set /a c2do+=1 & goto :eof if /i %1 == %fPas% set /a c2do+=1 & goto :eof erase /F/Q %1 if errorLevel 1 set errInf=fail erase %1 goto :eof :errExit реакция на проблему: в пакете - выход if defined pMod goto :eof :: автономно - на экран + прекращение работы echo %errInf% exit rem 2019.07.15 creation from siTop-dStat.cmd {2019.07.11} rem ... rem 2020.01.06, nvv, {!}ЕСЛИ гранд СИ попал в отсеянные по ДАТЕ обновления - сборка рейтинга НЕВОЗМОЖНА! rem 2020.03.27, nvv, радикально переделано {ВСЕ проверки и ВСЕ итоги - в bStat1.awk} rem + более тонкая работа с наличностью {с уже имеющимися файлами статистик} rem 2020.04.25, nvv, some updates rem 2020.05.31, nvv, нижняя граница для разделов из списка *.aHits - hitP>hitL {==670}, а не конец списка rem 2020.06.05, nvv, hitL=665 rem 08 650 rem 10 645 rem 14 610 rem 2020.06.18, nvv, нижнюю границу {hitL=NNN} можно задать файлом-маркой "NNN.lowHits" rem 2020.08.21, nvv, статистики, обновлённые "СЕГОДНЯ" или с той же датой ВЕРХНЕЙ границы интервала rem НЕ удаляются! Т.е. киллер не трогает сегодняшний комплект для рассчёта rem 2020.09.18, nvv, слегка перепахано для более тонкого разбора наличности rem + итоговый jLst формируется сразу отсортированный и оформленный rem + в конце строк с атрибутами отобранных текстов - datJ {1-й_полный_день} rem 2020.09.30, nvv, исправлена неточность в работе со списком BadStats {если упомянут в ]bStat.rpt} rem 2020.10.12, nvv, мелкая косметика rem 2020.11.02, nvv, исправлена ошибка обработки списка LowStats rem 2020.11.13, nvv, будКлуб - глупость rem 2020.11.16, nvv, будКлуб - глупость? не факт... ;{ rem 2020.12.18, nvv, добавлена возможность принудительно задавать дату верхней границы интервала rem в 30 дней для обсчёта {занадобилось после аварий 2020.11.19 - "ледяной дождь" + паралич в СИ} rem 2020.12.28, nvv, \siUrl.budclub turn to budclub.ru rem 2021.01.29, nvv, если в корне нет NNN.lowHits, hitL == хиты "за 12мес" 30000-го раздела в *.aHits rem 2021.03.23, nvv, gawk для вычленения первых 30000+ записей aHits rem 2021.03.25, nvv, в итогах явно указывается % годных к расчёту статистик rem 2021.05.17, nvv, очередная оптимизация с унификацией... rem 2021.05.27, nvv, границы "от-доНЕвключая" запоминаются ДО обновления и юзаются ПОСЛЕ падения {если} rem 2021.06.19, nvv, иной формат {подчерк "_" вместо пробела " " в границах updB & updE} rem 2021.07.30, nvv, мелкая косметика rem 2021.11.16, nvv, мелкая косметика касаемо tNum {пробелы слева до 4-х знаков} rem 2022.01.19, nvv, начало оптимизации при рестарте {за день; ресканирование ВСЕХ статистик избыточно} rem 2022.02.06, nvv, радикально переделано, теперь готово работать сразу /без дум глубоких пред/ rem 2022.02.16, nvv, таки заработало(!) вменяемо сие радикально-с переделанное rem 2022.02.23, nvv, исправлена пара неточностей rem 2022.03.04, nvv, нулевые файлы статистик удаляются /если найдутся/ перед завершением работы rem 2022.03.23, nvv, теперь список статистик из aHIts /при скачивании ВСЕХ/ сортируется по алфавиту rem 2022.04.04, nvv, теперь таймеры показывают не текущее время, а прошедшее с запуска rem 2022.07.11, nvv, если делать нечего, то и нефик искать нулевые файлы статистики rem 2022.08.10, nvv, +updNum==updN - возможнось явно задать в .upDatSet.bStat.# кол-во обновляемых статистик rem 2022.09.03, nvv, minor improvements rem 2022.09.20, nvv, обихожено взаимодействие с bStat0.awk rem 2022.09.29, nvv, исправлены ошибки считывания r2do при перезапуске упавшего процесса rem 2022.10.15, nvv, minor improve rem 2023.01.03, nvv, сменил разрешение экрана /меньше пикселей/, пришлось менять оживляж rem + добавлено прикапывание файла статистики nvv rem 2023.01.15, nvv, minor cosmetics rem 2023.03.09, nvv, was: set minT=300, now: 200 rem 2023.03.23, nvv, добавлено прикапывание "дыр" *.v.gis.bStat в статистике в Stor rem 2023.04.16, nvv, сущая мелочь не нужная удалена rem 2023.05.06, nvv, папка nDir перемещена в Stor и лишилась префикса '#' rem 2023.05.21, nvv, исправлена ошибка в имени целефого файла в папке nDir + "DLобъём" rem 2023.06.28, nvv, +поддержка: add2 - список разделов-потеряшек для добавления в расчёт rem 2023.07.05, nvv, удалена поддержка: add2 потерянное вносится в список aHits rem 2023.07.28, nvv, сокращена выдача в общий лог jRpt rem 2023.12.18, nvv, мелкая правка в диалоге выхода с паузой "== EXIT" rem 2024.01.02, nvv, пауза после формирования списка 2do дабы убедиться при сомнениях rem 2024.02.20, nvv, исправлена работа с изменившимся aHits rem 2024.02.20, nvv, исправлена работа с изменившимся aHits rem 2024.06.01 16:47 серьёзно переделано под ежедневное пополнение статистик rem 2024.08.14 поддержка пакетного режима /без запросов по-мелочи и EXIT-ов/
Имя файла скрипта: "bStat0.awk" V-текст скрипта-V- - - - - - - - - BEGIN{ # bStat0.awk анализатор текущего расклада статистик по спискам и по наличности # test=1 # режим отладки - формируется выборка из *.mig.bStat удаляемого/обновляемого # режим/источники при составлении списка удалить/скачать # режимы (m2do): 1-сводка"dlAll" 2(1)-построчно.file 3-сводка"2doDif" 4(3)-построчно.StdOut # "1","2" - \Jobs\*.aHits - ОБЯЗАТЕЛЕН для этих режимов (без - бессмысленно) # "1","2" - \Jobs\*.mig.bStat - ОБЯЗАТЕЛЕН для ОБНОВЛЕНИЯ по свежему aHits # "3","4" - \Jobs\*.2do - списки .2do. .don. и .pas. за "СЕГОДНЯ" # [!] envVar m2do задаёт режим работы (1..4); нечётные: "справка", чётные: # "2" == "комплект файлов 2do"; "4" == не "оптиченное" на StdOut # 2024.05.28, nvv, исправоена ошибка в отработке уделения статистик, выпавших из aHits # ! прочая история в подвале # hitL=6400 jDat=strftime("%Y.%m.%d") # "сегодня" # jDat="2022.09.17" if(test){ m2do=1 # job: 1-сводка"dlAll" 2(1)-построчно.file 3-сводка"2doDif" 4(3)-построчно.StdOut jDir=".\\" # место рабочих файлов wDir="V:\\Jobs\\" # место общих файлов-списков fHit=wDir "2024.05.21.aHits" # ВХОДНОЙ список *.aHits fMig=wDir "2024.05.19.v.mig.bStat" # отсортированный список моментов обновления статистик }else{ m2do=getEnv("m2do") # 1-сводка"upgMig" 2-построчно.file 3-сводка"2doDif" 4-построчно.StdOut hitL=getEnv("hitL") # принудительное задание нижней границы по хитам jDir=getEnv("jDir") # место рабочих файлов wDir=getEnv("wDir") # место общих файлов-списков fHit=getEnv("fHit") # ВХОДНОЙ список *.aHits fMig=getEnv("fMig") # отсортированный список моментов обновления статистик } # print hitL"---"h30k"---"jDir"---"f2do if(wDir==""){ errS="] NO envVar: 'wDir'" exit } f2do=wDir jDat".upd.2do.2do" # то, что НУЖНО "удалить/обновить" fDon=wDir jDat".upd.don.2do" # то, что УЖЕ "удалено/обновлено" fPas=wDir jDat".upd.pas.2do" # то, что пропущено (для полноты картины-с) if((m2do==3)||(m2do==4)){ # секция "ПРОДОЛЖИМ?" nDon=0 # загрузка списка fDon - "уже сделано" (может быть пуст) - защита от падений while((getline jj<fDon)>0){ if(match(jj,/^([23]) ([^ ]+)/,aj)){ # "2 m/moskalenko" - обновить nDon++ # "3 s/s_w" . . . . - удалить aDon[aj[2]]=aj[1] # статус "КАК" /раздел/ был "оптИчен" } } close(fDon) n2do=0 # загрузка списка f2do - то, что НУЖНО "удалить/обновить" while((getline jj<f2do)>0){ if(match(jj,/^([23]) ([^ ]+)/,aj)){ if(!(aj[2] in aDon)){ a2do[++n2do]=aj[1]" "aj[2] # статус: "КАК птИчить" этог раздел } } } close(f2do) if(nDon+n2do==0){ errS="] Nothing2do: '*2do' - empty" }else{ if(m2do==3)print(nDon,n2do) # выдача итога на StdOut - СВОДКА: "сделано НЕсделано" else for(jj=1;jj<=n2do;jj++)print(a2do[jj]) # - ПЕРЕЧЕНЬ не оптиченных ID } exit } # секция "НАЧНЁМ": читаем aHits (+ mig.bStat) => 3 файла: "сделать"+"готово"(пуст)+"пропустить" nHit=0 # загрузка списка aHits. первичное заполнение массива id_P (дОлжных быть раздлов) while((getline jj<fHit)>0){ # чтение aHits # 362225 6 1133 3 k/kadawr "Кадавр" "no•comments" # ; hitP.1 numP.2 sizK.3 4.sizN 5.id_P 6."namP" 7."moto" split(jj,aj) if(match(aj[1],/^[0-9]+$/)){ if(aj[4])aHiH[aj[5]]=aj[1] # пустые разделы нам не интересны... }else{ # ;1A hits 6:xNam 453:xNum 103792:xPas 2024.05.12:hDat 447277:hMax 1043:hPag 1146:add2 30664:n30k 282:h30k 1085:dnLd 0.22~ratW 2024.05.12:done 01:13:24~wrks 11:04 if(match(jj,/;1A .+ ([^ ]+):hMax .+ ([0-9]+):n30k ([0-9]+):h30k .+ ([^ ]+):done/,aj)){ hMax=aj[1] # хиты топового раздела h30k=aj[3] # хиты 30k раздела n30k=aj[2] # разделов с хитани h30k+ hitD=aj[4] # дата в aHits } } } close(fHit) if(!length(aHiH)){ errS="] "fHit" NO recs" # а пусто! exit } if(hitL!="")h30k=hitL for(j0 in aHiH){ # вычленяем топовые разделы для работы (хитов НЕ меньше h30k) if(aHiH[j0]-h30k>=0){ # отбираем в рабочий массив... aHit[j0]=aHiH[j0] # разделы с достаточной посещаемостью (И не пустые) nHit++ # число таких, годных разделов } } # чтение списка fMig. формирование массива статусов наличных id_P migD="-" # fMig нет (или НЕ "сегодня") if(fMig!=""){ # вообще-то этот файл может отсутствовать, но если есть, то не может быть пуст while((getline jj<fMig)>0){ # чтение mig.bStat split(jj,aj) if(match(aj[1],/^;/)){ # различие записей в секциях: "справка" и "данные" (даты статистик) # ;2B stat 2022.02.10:sEnd 0:nPre 0:hPre 0:miss 300:minT 4530:hitL 500:nHit last~01:11:36~ if(match(jj,/^;1A .+ ([^ ]+):hMax .+ ([^ ]+):done/,ak)){ # данные "заюзанного" aHits hitM=ak[1]":"ak[2] # ключ ("hMax":"hitD"),aHits использованный в bStat } # ;2D ~Пт~ 624:tNum OkV:100.% mod:! 2024.05.23:dEnd 0:sNul 2024.05.24:done 13:51 00:00:15~wrks 0~ratW 0:dnLd if(match(jj,/^;2D .+ ([^ ]+):done /,ak)){ # данные "заюзанного" aHits migD=ak[1] # дата сборки bStat } }else{ # это /основная/ запись дат статистики раздела # 0000.00.00_00:00:00 _bad_file_ 0 0 w~wladimir_kasxjanow not_IN_aHits w/wladimir_kasxjanow # 0000.00.00_00:00:00 _bad_file_ 891 3967 g~goncharow_d_a "No.Wen" g/goncharow_d_a # 2022.09.14_00:39:10 2022.09.11 129 11429 s~sks s/sks "Скс" # 2022.09.17_00:52:48 2022.09.15 92 15152 n~nosow_w_w n/nosow_w_w "Влад" # 1 2 3 4 5 6 7 aMig[aj[6]]=aj[1] # "дата_время" обновления статистики этого id_P (2022.09.14_00:39:10) aNum[++nNum]=aj[6] # место id_P в *.mig.* } } close(fMig) } # варианты разбраковки/построения 2do списков if(migD!=jDat){ # 1 fMig - НЕ за "сегодня" (или нет) == качать ВСЁ по fHit if(m2do==1){ if(test)print("nPas nDel nUpd nTot") # выдача справки по "2do" (качаем ВСЁ!) print("--","--",nHit,nHit) }else{ # m2do==2 строим комплект файлов "2do" for(id_P in aHit)aUpd[++jj]=id_P jk=";9N "strftime("%H:%S")"~ "hMax":hMax "hitD":hitD 0:nDel "nHit":nUpd 0:nPas " asort(aUpd) for(jj=1;jj<=nHit;jj++)print(2,aUpd[jj]" ") >f2do # затем (туда же) - на обновление print(jk)>fDon # текущая метка для порядка print(jk)>fPas # во все print(jk)>f2do # три созданных списка } }else if(hMax":"hitD==hitM){ # 2 fMig - "сегодня" И по наличному fHit == НЕЧЕГО делать if(m2do==1){ if(test)print("nPas nDel nUpd nTot") # выдача справки по "2do" print(nHit,"--","--",0) }else{ print("") } }else{ # 3 fMig - "сегодня" И не по наличному fHit == нужно отрабатывать РАЗНИЦУ с fHit nPas=0 nDel=0 nUpd=0 for(id_P in aMig){ # проекция aMig на aHit if(id_P in aHit){ # есть в aHits aPas[++nPas]=id_P # 1 pas "оставить" }else{ aDel[++nDel]=id_P # 3 del "удалить" } } for(id_P in aHit){ # проекция aHit на aMig if(!(id_P in aMig)){ # нет в aMig? aUpd[++nUpd]=id_P # 2 скачать! } } if(m2do==1){ if(test)print("nPas nDel nUpd nTot") # выдача справки по "2do" print(nPas,nDel,nUpd,nDel+nUpd) }else{ # m2do==2 строим комплект файлов "2do" asort(aPas) asort(aDel) asort(aUpd) # ;9N 21:04~ 571717:hMax 2022.02.06:hitD --:nPre --:sEnd 0:nDel 493:nUpd 0:nPas jk=";9N "strftime("%H:%S")"~ "hMax":hMax "hitD":hitD "nDel":nDel "nUpd":nUpd "nPas":nPas " for(jj=1;jj<=nPas;jj++)print(1,aPas[jj]" ") >fPas # пропускаемое - в отдельный список for(jj=1;jj<=nDel;jj++)print(3,aDel[jj]" ") >f2do # обрабатываемое - в другой, на удаление for(jj=1;jj<=nUpd;jj++)print(2,aUpd[jj]" ") >f2do # затем (туда же) - на обновление print(jk)>fDon # текущая метка для порядка print(jk)>fPas # во все print(jk)>f2do # три созданных списка } } exit } function getEnv(env1) { # найти в массиве ENVIRON значение переменной с именем env1 for(env0 in ENVIRON){ # ! реГИстр букв в имени переменной МОЖЕТ быть лЮбОй if(tolower(env0)==tolower(env1)){ # имя переменной совпадает с указанным? return(ENVIRON[env0]) # вернём значение этой переменной } } return("") # ничего нет? знать не судьба... } END{ # отстрелялись; ну почти... if(errS!=""){ print("") print(errS) # есть проблем-с => подудим exit -1 # и на выход с вещами } # 2021.04.20, nvv, created # 2021.04.26, nvv, выходной список сортируется в порядке mig.bStat # 2021.05.02, nvv, мелкая косметика # 2021.05.29, nvv, полу-автоматический выбор границ удалить/обновить/скачать теперь здесь # 2021.06.18, nvv, иной формат *.mig.bStat # 2021.11.07, nvv, мелкая косметика # 2022.02.14, nvv, радикально переделано и наконец-то заработало как надо # 2022.02.23, nvv, исправлена пара неточностей # 2022.03.12, nvv, уточнена интерпретация явно заданых границ обновления # 2022.08.11, nvv, +updNum==updN - путь задать в .upDatSet.bStat.# кол-во обновляемых статистик # 2022.08.22, nvv, уточнена работа с явными границами в .upDatSet.bStat.# # а. updBeg~2022.08.20~ == с этого момента в дате обновления статистики НУЖНО скачать свежую копию # ! может быть пусто ~~ == "с начала списка" # б. updEnd~2022.08.20_01:18~ == с этого момента НЕ обновлять # ! может быть пусто ~~ == "до конца списка" # в. updNum~10~ == кол-во скачиваемых ТЫСЯЧ статистик с момента updBeg # ! или сначала, если updBeg не задано # + updEnd ИГНОРИРУЕТСЯ! # !!! параметр (updBeg/updEnd/updNum) должен быть терминирован пробелом и стоять первым в строке # + иначе он игнорируется (считается пустым) # + используется ПОСЛЕДНЕЕ непустое вхождение параметра, если таковых не одно # + если пусты все три == явных (заданных вручную) границ нет # 2022.09.22, nvv, исправлена работа с "ручными" границами в .upDatSet.bStat.# /более вменяемая/ # 2022.09.29, nvv, откат ненужного улучшения выдачи в m2do=3 # 2022.10.18, nvv, обустроен altStop - иное вычленение статистик "на upDat" /не по bStat.awk/ # 2023.01.14, nvv, altStop теперь не флаг, а число самых свежих НЕ обноляемых статистик # 2023.01.18, nvv, altStop теперь не нужен, изменился рисунок обновления статистик # 2023.04.20, nvv, более гибкий алгоритм поиска даты "до не включая" updEnd по вчерашнему раскладу # 2023.05.21-2023.07.02, nvv, +поддержка: add2 - список разделов-потеряшек для добавления в расчёт # 2023.07.05, nvv, удалена поддержка add2, потерянное вносится в список aHits # 2023.07.15, nvv, исправлена неточность в обработке списка aHits # 2023.10.15, nvv, иное разделение aMig на "обновить"/"пропустить" по самому старому "толстяку" # 2023.12.18, nvv, статистики со статусом "_bad_file_" НЕ пропускаются а считаются отсутствующими # 2024.04.01, nvv, изменился рисунок пополнения статистик - теперь ежедневно # ergo при ПЕРВОМ запуске ВСЁ, что есть в *.mig.bStat и aHits - на ОБНОВЛЕНИЕ # 2024.05.21, nvv, радикально переделано (упрощено) под ежедневное полное обновление статистик }
Имя файла скрипта: "cChkH.awk" V-текст скрипта-V- - - - - - - - - BEGIN{ # cChkH.awk - хиты текста по факту в интервале от "Размещен:" до верхней границы if(ARGV[1]=="")exit # защита от случайного пуска # 2020.06.10, nvv, creation, на основе siTop-bStat.awk от 2020.05.31 # 2020.06.16, nvv, it's working! =) # 2020.12.19, nvv, добавлена принудительная установка верхней даты (datJ) нашего интервала # 2021.05.02, nvv, мелкая косметика for ( str2 in ENVIRON ) { # ! регистр букв в имени переменной может быть любой str1 = tolower( str2 ) # Temp и temp - РАЗНЫЕ имена для gAwk... if ( str1 == "begd" ) begD=ENVIRON[str2] # дата "Размещен:" if ( str1 == "datj" ) datJ=ENVIRON[str2] # верхняя граница интервала: datJ if ( str1 == "id_t" ) t_id=ENVIRON[str2]".shtml" # имя файла с текстом, чьи хиты нужны } # begD="2020.11.23" # datJ="2020.12.08" # t_id="19.shtml" # массив имён месяцев для преобразования их в числа с лидирующим нулём 01..12 mNum["Jan"]="01" # .1 January . Jan. 31 . winter wint mNum["Feb"]="02" # .2 February .Feb. 28/29 mNum["Mar"]="03" # .3 March . . Mar. 31 . spring sprn mNum["Apr"]="04" # .4 April . . Apr. 30 mNum["May"]="05" # .5 May . . . May. 31 mNum["Jun"]="06" # .6 June . . .Jun. 30 . summer summ mNum["Jul"]="07" # .7 July . . .Jul. 31 mNum["Aug"]="08" # .8 August . .Aug. 31 mNum["Sep"]="09" # .9 September Sep. 30 . autumn autm mNum["Oct"]="10" # 10 October . Oct. 31 mNum["Nov"]="11" # 11 November .Nov. 30 mNum["Dec"]="12" # 12 December .Dec. 31 . winter wint hitT=0 # сумма хитов "за 30 дней" step=0 # 0-владелец, 1-дата обновления, 2-id раздела, 3-разбор строк таблиц статистики inTab=0 # сначала - мы НЕ "в таблице" numT=0 # счётчик таблиц в файле статистики numR=0 # счётчик строк в текущей таблице selN=0 # номер в строке обрабатываемой ячейки selE=0 # номер ячейки с датой "Размещён:" (последней НЕ 0!) # объявим массивыы для общего использования в подпрограммах split("",aSel) # в ячейках статистики: url,title,hits:all,12mon,mon0..monC-11,day0..day0-61 } { # // -=- основной блок скрипта begs if(step==0) { # ищем/проверяем ФИО автора # <h3>Статистика раздела "<a href=./>Влад</a>":</h3> if (match($0,/<h3>Статистика раздела \"<a href=\.\/>(.*)<\/a>\":<\/h3>/,aj)) { step++ # проверка ОК } }else if(step==1){ # вычленеие даты обновления статистики if(match($0,\ /<li><i>Статистика рассчитывается .+\. \(.+ (...) +([0-9]+) (..:..:..) (20[0-9][0-9])\)<\/i>/,aj)){ if(length(aj[2])==1) aj[2]="0"aj[2] # причешем первые дни месяца "1" -> "01" ticS=mktime(aj[4]" "mNum[aj[1]]" "aj[2]" 12 00 00") # тики на 12 часов даты статистики datS=aj[4]"."mNum[aj[1]]"."aj[2] step++ # дату статистики оптичили } }else if(step==2){ # ищем authID (!должен быть) #[<a href=http://top.mail.ru/pages?id=77427&period=0&date=2018-10-02&filter_type=0 #&filter=n/nosow_w_w&pp=20&gender=0&agegroup=0>по дням</a>] if (match($0,/\[<a href=http.+&filter=([0-9a-z]\/[\-0-9a-z_]+)&pp=.+>по дням<\/a>]/,aj)) { step++ # проверка ОК } }else if(step==3){ # таблицы статистики, просмотр строк, сборка данных в ячейках if($0=="<!--------- Подножие ------------------------------->"){ # разбор закончен step++ nextfile } if(inTab){ # Мы ВНУТРИ таблицы, собираем строки таблицы с хитами текстов buf0=buf0" "$0 # gain inpLines to buf0, then check contents while((match(buf0,/<tr ?[^>]*>/))||(int0=index(buf0,"</tr"))){ # seek <tr .. </tr for tabRow if(RSTART){ # new/next line begs numR++ buf0=substr(buf0,RSTART+RLENGTH) } if(int0=index(buf0,"</tr")){ # this line ends sel0=0 # хиты до накануне-v sel1=0 # хиты накануне даты "Размешен:" getSels(substr(buf0,1,int0-1)) # tabl_row -> arrow:sell_values buf0=substr(buf0,int0+4) # убрали эту строку из буфера и окультуриваем... id_T=aSel[0] # имя+расшир файла с текстом (или "./" для раздела) if((numT==1)&&(numR==2)){ # хиты по разделу (спец.обслуживание) }else{ # обычная строка статистики текста if(id_T==t_id){ if(!sel0)hitT=hitT+sel1 # если это глюк СИ (хиты накануне размещения), учтём их print(hitT) exit } } } } if(int0=index(buf0,"</table")){ # this tabl ends buf0=substr(buf0,int0+4) # update buf0 inTab=0 } }else{ # ищем начало таблицы if(int0=index($0\ ,"<table border=1 cellspacing=0 cellpadding=0><tr><td><td colspan=2><b>Итого</b></td>")){ numT++ # new table numR=1 # певая строка каждой таблицы - календарь хитов статистики раздела buf0=substr($0,int0+80) if(numT==1){ # 1-st table 1-st row -> get col-dates & so-on match(buf0,/<tr[^>]*>(.+)<\/tr[^>]*>/,aj) # собственно строка с календарём getSels(aj[1]) # но самую первую такую - разберём-с tic0=ticS # и привяжем дату к нулевому (самому левому) дню посуточных данных while(strftime("%d",tic0)!=aSel[16])tic0=tic0-86400 # сдвинем стат.дату к нулевому дню for(dev0=0;dev0<30;dev0++)if(strftime("%Y.%m.%d",tic0-86400*dev0)==datJ)break tic0=tic0-86400*(dev0-1) dev0=dev0+15 for(selE=1;selE<31;selE++)if(begD>=strftime("%Y.%m.%d",tic0-86400*selE))break } # ^- поиск номера яцейки с датой "Размещен:" inTab=1 # мы ВНУТРИ таблицы buf0="" # буфер чист! } } } } # // -=- основной блок скрипта ends function getSels(rowLn){ # разделение строки таблицы статистики на массив значений hitT=0 # сумма хитов "за 30 дней" selN=0 # sells count split("",aSel) aSel[0]="" while(match(rowLn,/<td[^>]*>/)){ # это объявление ячейки selN++ # 0.1-имя/ссылка; хиты: 2-всего, 3-12мес, 4..15-заМес, 16..77-за сутки rowLn=substr(rowLn,RSTART+RLENGTH) # выкусим объявление ячейки f3n2=index(rowLn,"</td") # это конец ячейки f3s2=substr(rowLn,1,f3n2-1) # это сама ячейка (с возможными внутренними тегами) if(selN==1){ # в ПЕРВОЙ ячейке - название текста и ссылка на него match(f3s2,/<a href=([^>]+)>(.*)<\/a>/,f3a1) # выцепим и разложим: aSel[1]=f3a1[2] # название текста aSel[0]=f3a1[1] # ссылка на текст: name.shtml }else aSel[selN]=rmTags(f3s2) # в ПРОЧИХ ячейках - только значение ячейки, очищенное от тегов rowLn=substr(rowLn,f3n2) # выкусим оптиченную ячейку if((selN-dev0>0)&&(selN-dev0-selE<=0)){ # 21 = dev0+5<=21 17..21 hitT=aSel[selN]+hitT # сразу подсчитаем сумму хитов "за 30 дней" }else if(selN-dev0-selE==1){ # ячейка сразу за границей sel1=aSel[selN] }else if(selN-dev0-selE>1){ # прочие ячейки за границей sel0=aSel[selN]+sel0 } } } function rmTags(f2s1){ # удаление ВСЕХ тегов в литерале while(match(f2s1,/<\/?[a-zA-Z][1-6a-zA-Z]?[a-zA-Z]*[ \/]?[^>]*>/)) f2s1=substr(f2s1,1,RSTART-1) substr(f2s1,RSTART+RLENGTH) return(f2s1) } END{ # отстрелялись; ну почти... if(ARGV[1]==""){ print("No file in") exit # защита от случайного пуска } }
Имя файла скрипта: "cChkH.cmd" V-текст скрипта-V- - - - - - - - - @if not defined nJob @echo off :: cChkH.cmd - просмотр списка *?.lst.bStat [?==v/~], скачивание ВСЕХ текстов из (кривое оставляется!) :: смотрится дата "Размещён", если она ПОСЛЕ верхней границы выцепляемого интервала - игнорировать! :: если ПОСЛЕ нижней границы - уточняются фактичкеи хиты в интервале :: по результатам собирается уточнённый ОТсортированный список *.cChkH (а`ля *.bStat) :: OS windows - должны быть настроены системные переменные окружения: :: %time% - HH:MM:SS,tt HH<=9 -> "HH" == " H" лидирующий пробел для часа меньше 10 :: %date% - YYYY.mm.dd :: 2022.03.31, nvv, годный mod теперь или "v" или "~" :: ! история изменений - в подвале echo %date% %time:~0,8% %~nx0 Begs :: siUrl - основной и резервный URL Самиздата (желательно работать с резервом) set siUrl=samlib.ru if exist \siUrl.budclub set siUrl=budclub.ru :: dnLd - счётчик /формально/ успешно скачанного (НЕ 0b) set dnLd=0 :: ratW - темп скачивания (секунд на один файл в среднем) set ratW=0 :: wrks - общее время работы процесса (пуск общего таймера) for /F %%A in ('gawk.exe "BEGIN{print(systime());exit}"') do set wrks=%%A :: основные сеты и прочая подготовка к работе... set errInf= set nJob=cChkH set jDat=%date% :: noReGet - запрет повторного скачивания пустых/битых текстов set noReGet=%1 :: minT - минимальные допустимые хиты текста (берётся из подвала .v.lst.bStat) set minT= :: hitL - хитов за "30дн." (у ТЕКСТА должно быть НЕ меньше), уточняется в *.bStat (по nHit) set hitL= :: aChk - скрипт поиска атрибутов текста СИ, может создать очищенную копию set aChk=%~dp0%nJob%.awk :: aTxt - скрипт поиска атрибутов текста СИ, может создать очищенную копию set aTxt=%~dp0dText.awk set jDat=%date% :: wDir - общее рабочее место set wDir=%~d0\Jobs :: zDir - общий подкаталог для посуточных подкаталогов с итоговыми списками set zDir=%~d0\Stor\wOld\%jDat% :: tDir - папка для текстов "наших" 30-дней (like: 2019.08.02.text) set tDir= :: jRpt - общий отчёт с итоговыми сводками процессов set jRpt=%wDir%\_siTop.# :: nulT текст - недоступен: 0b set nulT=0 :: badT текст - битый (нет любого): begD,endD,sizT,namA,namT set badT=0 :: badZ текст с ограниченным доступом set badZ=0 :: down - хиты изменены set down=0 :: datJ - верхняя граница интервала дат расчёта (дата в имени файла-списка yyyy.mm.dd.v.lst.bStat) set datJ= :: найти 20??.??.??.v.lst.bStat и запомнить его имя (т.е. дату в нём, например, 2019.07.14.v.lst.bStat) for %%A in (%wDir%\20??.??.??.?.lst.bStat) do set datJ=%%~nA if NOT defined datJ echo ? NO 20??.??.??.?.lst.bStat found & exit set tmp0=%datJ:~11,1% if NOT "%tmp0%" == "~" if NOT "%tmp0%" == "v" ( echo ? bad mod "%tmp0%" in %datJ% goto nExit ) :: sLst - входной список принятых "начерно" текстов (для скачивания и проверки, дат в первую очередь;) set sLst=%wDir%\%datJ%.bStat :: вырежем чистую дату datJ set datJ=%datJ:~0,10% :: dBeg - нижняя граница нашего интервала (datJ-29) set dBeg=mktime(\"%datJ:~0,4% %datJ:~5,2% %datJ:~8,2% 12 00 00\") for /F %%A in ('gawk.exe "BEGIN{print(strftime(\"%%Y.%%m.%%d\",%dBeg%-86400*29));exit}"') do set dBeg=%%A :: jDir - место для страниц сканируемых гостевых и рабочих файлов set jDir=%wDir%\#mRepl :: jLst - НЕ сортированный список для "siTopTexts" с проверенными хитами за 30дн. set jLst=%jDir%\]%nJob%.lst :: eLst - список ПРОБЛЕМ с текстами/гостевыми set eLst=%wDir%\]%nJob%.bad :: hold - опорная дата в имени склада с текстами set hold=%jDat% set tDir=%~d0\Stor\Text\%hold%.text :: если уже собирали именно этот день - запрос "повторить?" if NOT exist %wDir%\%datJ%.%nJob% goto goOn set tmp0= echo %datJ%.%nJob% found; tDir.*\%hold%.text\ reBuild? [yes] == y set /p tmp0=?[no]? if /i NOT %tmp0%. == y. echo job canceled {NO to reBuild} & exit :goOn if NOT exist %tDir%\ mkDir %tDir%\ if NOT exist %tDir%\ set errInf=fail mkDir %tDir%\ & goto nExit if NOT exist %jDir%\ mkDir %jDir%\ if NOT exist %jDir%\ set errInf=fail mkDir %jDir%\ & goto nExit if NOT exist %zDir%\*.* mkDir %zDir% if NOT exist %zDir%\ set errInf=fail mkDir %zDir%\ & goto nExit :: очистим будущие списки рейтинга и ошибок echo. >nul 2> %jLst% echo. >nul 2> %eLst% :: tmpF - времянка для скачиваемых текстов set tmpF=%tDir%\siTextDL.tmp if exist %tmpF% erase %tmpF% if errorLevel 1 set errInf=FAIL erase %tmpF%& goto nExit :: linN - счётчик текстов set linN=0 :: установим счётчик текстов на максимум... :: ;2C scan 2021.04.24:dEnd 19719:nEnd 60688:hEnd 30012:nMig 1657:tNum 11:nGis 29154:nLow mod:! OkV:65.7% for /F %%A in ('gawk.exe "{if(match($0,/ ([0-9]+):tNum /,a))print(a[1])}" %sLst%') do set linN=%%A :: ;2B stat 2021.04.26:sEnd 1457:nPre 20102:hPre 1457:miss 300:minT 548:hitL 30075:nHit 801964:hMax last~01:01:31~ for /F %%A in ('gawk.exe "{if(match($0,/ ([0-9]+):hitL /,a))print(a[1])}" %sLst%') do set hitL=%%A if NOT defined hitL set errInf=fail read 'hitL' (noOrBad in %sLst%) & goto nExit :: wGetSiz - объём файла, полученного с СИ (default 1b) set wGetSiz=1 echo req topTexts... linN:%linN% :: запустим "таймер" качалки for /F %%A in ('gawk.exe "BEGIN{print(systime());exit}"') do set ratW=%%A :: hitT hitP numP id_P id_T xDat "namA" "namT" - собственно сборка списка cChkH for /F "tokens=*" %%A in ( 'gawk.exe "{if(match($1,/^[0-9]+$/))print($0)}" %sLst%' ) do if NOT defined errInf call :reqSiText %%A if defined errInf goto nExit :: остановим "таймер" качалки время работы в секундах for /F %%A in ('gawk.exe "BEGIN{print(systime()-%ratW%);exit}"') do set ratW=%%A :: среднее время скачивания файла в секундах if %dnLd% == 0 (set ratW=0) else ( for /F %%A in ('gawk.exe "BEGIN{print(sprintf(\"%%3.2f\",%ratW%/%dnLd%));exit}"') do set ratW=%%A ) if exist %wDir%\*.%nJob% move /y %wDir%\*.%nJob% %jDir% >nul sort /rec 65535 /r %jLst% > %wDir%\%datJ%.%nJob% if errorLevel 1 set errInf=FAIL sort %jLst% & goto nExit :: теперь у нас свежий jLst set jLst=%wDir%\%datJ%.%nJob% :: выясним число текстов с хитами НЕ ниже hitL for /F %%A in ('gawk.exe "{if(%hitL%-$1>0){print(NR-1);exit}}" %jLst%') do set topN=%%A :: преобразуем секунды в время работы (в обычном формате "чч:мм:сс") for /F %%A in ('gawk.exe "BEGIN{print(strftime(\"%%H:%%M:%%S\",systime()-%wrks%+46800));exit}"') do set wrks=%%A :: оформим подвал списка... echo ; hitT oldH. hitP numP id_P id_T "namP" "namT" sFil >> %jLst% :: сначала сводки от aHits и bStat gawk.exe "{if(match($1,/^;[1-3].$/))print($0)}" %sLst% >> %jLst% :: затем собственная сводка rem ;3C chkH dInt:2021.03.23-2021.04.21 topN:767 down:14 nulT:0 badT:1 badZ:0 741:dnLd done:2021.04.24 gap3:16:11-16:16 set tmp0=;3C chkH ^ dInt~%dBeg%-%datJ%~ ^ %topN%:topN ^ %down%:down ^ %nulT%:nulT ^ %badT%:badT ^ %badZ%:badZ ^ %dnLd%:dnLd ^ %ratW%~ratW ^ %jDat%:done ^ %wrks%~wrks ^ %time:~0,5% echo %tmp0% >> %jLst% if NOT defined noReGet echo %tmp0% >> %jRpt% echo %tmp0% :: да и результат прикопать надлежитЪ copy /b/y %jLst% %zDir% > nul if errorlevel 1 set errInf=fail copy %jLst% to %zDir% :: подудим где нада "готово-с!" set itog=%jLst% :nExit if NOT defined tmpF goto nExit1 if exist %tmpF% erase %tmpF% :nExit1 if defined errInf echo ! %errInf% echo %date% %time:~0,8% %~nx0 Ends goto :eof :reqSiText работа с очередным тектстом set /a linN-=1 set linR= %linN% set linR=%linR:~-4% :: 1 2 3 4 5 6 7 8 9 :: hitT hitP numP id_P id_T "namP" "namT" sFil datJ :: 9241 365732 6 k/kadawr n Кадавр" "Псион" k~kadawr 2021.04.06 set hitT=%1 set hitP=%2 set numP=%3 set id_P=%4 set id_T=%5 set namP=%6 set namT=%7 set gFil=%8 set curT= %hitT% set curT=%curT:~-6% :: tFil - конечный файл для склада set tFil=%tDir%\%gFil%.%id_T%.text.html :: глянем, может этот текст уже у нас... set tmp0= for %%J in ( %tFil% ) do set tmp0=%%~zJ :: пусто == нужно тащить с СИ if NOT defined tmp0 goto getTxt :: есть, но нулевой - нужно горхнуть и тащить с СИ if %tmp0% == 0 ( if defined noReGet goto keepNul erase %tFil% goto getTxt ) :: есть и ненулевой, разберёмся... set fOut= for /F "tokens=*" %%J in ('gawk.exe -f %aTxt% %tFil%') do call :chkTxt %%J :: если OK - займёмся оформлением этого текста if NOT "%begD%" == "]" echo. %linR% = %curT%.Text: %gFil%.%id_T% & goto txtInOK :: если битый, то грохнуть и тащить заново if defined noReGet goto keepBad erase %tFil% :getTxt тащим топовый текст на склад-с set wUrl=%siUrl%/%id_P%/%id_T%.shtml if exist %tmpF% erase %tmpF% echo. %linR% ? %curT%.Text: %gFil%.%id_T% call wGetUrl2fil.cmd %wUrl% %tmpF% if defined errInf goto :eof if NOT %wGetSiz% == 0 goto mark0 :: если файл текста недоступен... set errT=] err:T nulT: %curT% move /y %tmpF% %tFil% if errorLevel 1 set errInf=FAIL move inpF 2 %tFil%& goto :eof :keepNul set /a nulT+=1 set typT=%hitT%. set hitT=1 set namA="x" set namT="x" goto fixErr :mark0 смотрим атрибуты (в т.ч. дату создания, точно название и автор[а/ов]) текста... set fOut=%tFil% for /F "tokens=*" %%J in ('gawk.exe -f %aTxt% %tmpF%') do call :chkTxt %%J set fOut= :: если свежий текст OK, надо дату вструмить if NOT "%begD%" == "]" touch.exe -t %endD:~0,4%%endD:~5,2%%endD:~8,2%0100 %tFil% & goto txtInOK :: если с текстом проблемы, ставим на нём крест move /y %tmpF% %tFil% if errorLevel 1 set errInf=FAIL move inpF 2 %tFil%& goto :eof :keepBad set /a badT+=1 set typT=%hitT%? set hitT=2 :fixErr с текстом всё плохо... rem set /a linN-=1 echo. -X- %errT% %wUrl% echo %errT% %gFil%.%id_T%.text.html %wUrl% >> %eLst% touch.exe -t 199001010100 %tFil% :: и что с того, что брак? Изъятия в перетряхиваемом списке - только вручную! call :formIt %hitT% %typT% %hitP% %numP% %id_P% %id_T% %namP% %namT% %gFil% goto :eof :txtInOK текст как-бы не битый, а доступ? if %sizT:~-2% == .0 ( set /a badZ+=1 set typT=%hitT%z set hitT=4 set errT=] err:Z unAv: %curT% goto fixErr ) :: доступ OK, а хиты текста? set typT=lowH if %hitL% GTR %hitT% goto BegDatOk :: а дата "Размещен:" - ОК? set typT=: if %begD% LEQ %dBeg% goto BegDatOk set typT=%hitT%! if %begD% GTR %datJ% set hitT=3& goto BegDatOk set typT=v :: дата после начала интервала => хиты текста как бы под подозрением... set filS=U:\Jobs\#bStat\%id_P:~0,1%~%id_P:~2%.stat.htm set tmp0= for /F %%J in ('gawk.exe -f %aChk% %filS%') do set tmp0=%%J if %hitT% == %tmp0% goto BegDatOk :: не совпало; наследство отдельно set typT=%hitT%] set hitT=%tmp0% set /a down+=1 :BegDatOk выгрузка собранных данных в накопительный список пефоманс call :formIt %hitT% %typT% %hitP% %numP% %id_P% %id_T% %namP% %namT% %gFil% goto :eof :: 9241 : 362225 6 k/kadawr n "Кадавр" "Псион" k~kadawr ::; hitT oldH. hitP numP id_P id_T "namP" "namT" sFil :: 1 2 3 4 5 6 7 8 9 :formIt %hitT% %typT% %hitP% %numP% %id_P% %id_T% %namP% %namT% %gFil% set typT= %typT% set typT=%typT:~-7% gawk.exe "BEGIN{printf(\"%%7s%%8s%%8s%%6s\",%1,\"%typT%\",%3,%4);exit}" >> %jLst% echo. %id_P% %id_T% %namA% %namT% %gFil% >> %jLst% goto :eof :chkTxt begD endD sizT namA namT votT jnrT fNam - вычленение данных по тексту :: . . . 1 .. 2 .. 3 .. 4 .. 5 .. 6 .. 7 .. 8 set begD=%1 set endD=%2 set namA=%4 set namT=%5 set sizT=%3 set votT=%6 set jnrT=%7 set errT=%* goto :eof :: 2018.08.10, nvv, creation :: ... :: 2020.03.14, nvv, мелкие изменения :: 2020.06.14, nvv, разделено и реорганизовано. здесь - первая часть, вторая (основная) в siTop-dText.cmd :: 2020.06.26, minor updates :: 2020.07.06, minor updates :: 2020.11.13, nvv, будКлуб - глупость :: 2020.12.19, nvv, ^- не факт... :: 2020.12.31, nvv, hitL check added (no datCheck for low text's hits) :: 2021.01.09, nvv, minor mistake corrected :: 2021.01.29, nvv, если доступ ограничен (sizT N.0) текст отбраковывается :: 2021.04.09, nvv, *.bStat turned to *.lst.bStat + minor updates :: 2021.04.19, nvv, minor updates :: 2021.04.26, nvv, updates унификация формата передаваемых итоговых значений :: 2021.05.11, nvv, очередная оптимизация с унификацией... :: 2021.11.16, nvv, добавлен запрос на пересборку итога, если он уже собирался (защита от случайного пуска)
Имя файла скрипта: "dText.awk" V-текст скрипта-V- - - - - - - - - BEGIN{ # siTop-dText.awk - (для siTop-mText.cmd) взять инфу из текста + очистить сам файл от мусора # fOut="nvv.shtml" # при запуске НЕ из CMD, для создания(!) очищенного текста раскомментировать fErr="F eInP:NO input file" if(ARGV[1]=="")exit # защита от случайного пуска # 2024.03.06 nvv, теперь 2 варианте оформления ФИО в шапке текста # ! прочая история в подвале # Скрипт выдаёт на StdOut 9 литералов: # :: begD endD sizT namA namT votT jnrT fNam # 1 begD(11) - дата размещения текста (2018.04.19) # 3 endD(11) - дата последнего изменения текста (2018.10.21, "!" == "битое") # 4 sizT(6) - размер текста kb (427) + суффикс ".1" (Ok) или ".0" (доступ ограничен) # 5 "namA" - ФИО ("Федорочев•Алексей" или "Калашников•Сергей•Александрович,•Андрей_М11") # 6 "namT" - заголовок текста ("Мажор") # 7 votT - оценки (7.07*811, может быть "0" без кавычек) # 8 "jnrT" - жанр(ы) (может быть пусто "0" без кавычек) # 9 fNam - чистое ИМЯ файла текста/гостевой (f-fedorochew_a.major) # ЕСЛИ это проблемный файл, выдача меняется (вместо begD - признак проблемы: "]"): # ] 190001010100 "err:E erId:description" gFil # fDat="190001010100" # 1900.01.01 01:00 (12:00 ВЛД) begD=0 # дата размещения текста endD=0 # дата последней редакции этого текста sizT=-1 # объём (в килобайтах) этого текста maxL=99 # максимальная допустимая длина ника или заголовка namA="-" # автор(ы) текста (as-is) namT="-" # заголовок текста (as-is) votT=0 # оценки текста (like 7.07*811) или диагноз jnrT=0 # жанр(ы) текста (упаковано, если есть) step=0 # шаг "разбора" страницы текста/гостевой "Самиздата" j1=split(ARGV[1],jArr,":") # drv+rest j1=split(jArr[j1],jArr,"\\") # path+name+ext j1=split(jArr[j1],jArr,".") # name+ext fNam=jArr[1] for(j2=2;j2<j1;j2++)fNam=fNam"."jArr[j2] # a-abwow_a_s.fp.text [.html] for ( j2 in ENVIRON ) { # ! регистр букв в имени переменной может быть любой j1 = tolower( j2 ) # Temp и temp - РАЗНЫЕ имена для gAwk... if ( j1 == "fout" ) fOut=ENVIRON[j2] # очищенный si-HTML текст if ( j1 == "hitt" ) hitT=ENVIRON[j2] # очищенный si-HTML текст } if(fOut!=""){ # PATH + id_F +.+ id_T +.+ text.html j1=split(fOut,aj,"\\") # like: V:\Stor\Text\2022.04.13.text\s~sej_p_s.ms.text.html j2=split(aj[j1],aj,".") fTxt=aj[1] # чистое имя БЕЗ расширения ".html" like: s~sej_p_s.ms.text for(j1=2;j1<j2;j1++)fTxt=fTxt"."aj[j1] }else fTxt=fNam if(hitT)hitT=sprintf("%7s",hitT) fErr="P eAvt:"hitT" NO owner FIO" # бывает-с, хотя и очень редко... flgA=0 flgO=1 split("",aOut) # массив под строки обихоженной страницы с текстом aNum=0 # счётчик строк в массиве aOut } function pack(j1,j0) { # заменить мешающие символы на нейтральные + закавычить результат j2="" # TAB -> "•" while(n1=index(j1,"\x09")) { j2 = j2 substr( j1, 1, n1-1 ) "•"; j1 = substr( j1, n1+1 ) } j1=j2 j1 j2="" # пробел -> "•" while(n1=index(j1," ")) { j2 = j2 substr( j1, 1, n1-1 ) "•"; j1 = substr( j1, n1+1 ) } j1=j2 j1 j2="" # неразрывный_пробел -> "•" while(n1=index(j1,"\xA0")) { j2 = j2 substr( j1, 1, n1-1 ) "•"; j1 = substr( j1, n1+1 ) } j1=j2 j1 j2="" # двойные кавычки -> "”" # while(n1=index(j1,"\"")) { j2 = j2 substr( j1, 1, n1-1 ) "”"; j1 = substr( j1, n1+1 ) } while(n1=index(j1,"\"")) { j2 = j2 substr( j1, 1, n1-1 ) """; j1 = substr( j1, n1+1 ) } j1=j2 j1 j2="" # "%" -> "%" while(n1=index(j1,"%")) { j2 = j2 substr( j1, 1, n1-1 ) "%"; j1 = substr( j1, n1+1 ) } j1=j2 j1 # j2="" # "••" -> "•" # while(n1=index(j1,"••")) { j2 = j2 substr( j1, 1, n1-1 ); j1 = substr( j1, n1+1 ) } # j1=j2 j1 n0=length(j1) if(j0&&(n0-maxL>0))j0=maxL else j0=n0 n1=split(j1,ak,"•") j1=ak[1] for(j2=2;j2<=n1;j2++){ if(j0<length(j1)+1+length(ak[j2])){ j1=j1"•(nvv:•+"n0-length(j1)"•знаков)" # •(nvv:•+1•знаков)" # 123456789.123456789.123456789. break } if(ak[j2]!="")j1=j1"•"ak[j2] } # if(substr(j1,1,1)=="•") j1 = substr( j1, 2 ) # del "•" at beg # n1=length(j1) # if(substr(j1,n1,1)=="•") j1 = substr( j1, 1, n1-1 ) # del "•" at end return ("\""j1"\"") } { # scan text head (шапка текста) outP($0) # 6 "namA" ФИО ("Федорочев Алексей" или "Калашников Сергей Александрович, Андрей_М11") # Буревой Андрей: <small><a href=/b/burewojandrej/>другие произведения.</a></small> # Ил Саган, Кейн Алекс: <small><a href=/s/sagan_i/>другие произведения.</a></small> # <div align=right><h3>Шерман Елена Михайловна : # <small><a href=/s/sherman_e_m/>другие произведения.</a></small></h3></div> # <div align=right><h3> # Boris : <small><a href=/b/boris/>другие произведения.</a></small> if (!step) { # нулевой шаг - автор if (match($0,/^<div align=right><h3>([^:]+)? ?:? ?/,aj)){ if(length(aj[1]))namA=pack(aj[1],1) flgA=1 } if(flgA){ if (match($0,/^([^:]+)? ?:? ?<small><a href=(.+)>другие произведения\.</,aj)){ if(length(aj[1]))namA=pack(aj[1],1) id_P=aj[2] fErr="H eHdr:"hitT" no title" step=1 next } } } # 7 "namT" заголовок текста ("Мажор") # <center><h2>Чего бы почитать?</h2> if (step==1) { # первый шаг - название текста if (match($0, /^<center><h2>(.+)<\/h2>$/, aj)) { namS=aj[1] namT=pack(aj[1],1) outP("</center>") outP("<hr>") flgO=0 fErr="I eInf:"hitT" bad date/size" step=2 next } } # 1 endD(11) дата последнего изменения текста (2018.10.21, "!" == "битое") # 2 begD(11) дата размещения текста (2018.04.19) # 3 sizT(6) размер текста kb (427) # <li>Размещен: 03/09/2018, изменен: 09/11/2018. 410k. <a href=stat.shtml#psv.shtml>Статистика.</a> # <li>Размещен: 15/08/2003, изменен: 17/02/2009. 246k. <a href="stat.shtml#xu43.shtml">Статистика.</a> if (step==2) { # второй шаг - основные атрибуты текста if(index($0,"<table width=90% border=0 cellpadding=0 cellspacing=0><tr>")){ flgO=1 outP($0) next } # if (match($0,/^<li>Размещен: ([0-3][0-9])\/([01][0-9])\/(20)?([0-9]{2})\, изменен: ([0-3][0-9])\/([01][0-9])\/(20)?([0-9]{2})\. ([0-9]+)k\. <a href=.+>Статистика\.<\/a>$/,aj)){ # begD="20"aj[4]"."aj[2]"."aj[1] # endD="20"aj[8]"."aj[6]"."aj[5] if (match($0,/^<li>Размещен: ([0-3][0-9])\/([01][0-9])\/(..)?([0-9]{2})\, изменен: ([0-3][0-9])\/([01][0-9])\/(..)?([0-9]{2})\. ([0-9]+)k\. <a href=.+>Статистика\.<\/a>$/,aj)){ if(aj[3]=="")aj[3]="20" begD=aj[3] aj[4]"."aj[2]"."aj[1] if(aj[7]=="")aj[7]="20" endD=aj[7] aj[8]"."aj[6]"."aj[5] # fDat=strftime("%Y%m%d%H%M",mktime(aj[6]" "aj[5]" "aj[4]" 01 00 00")) # YYYYMMDDhhmm (12:00 VLD) sizT=aj[9] fErr="J eJnr:"hitT" bad janr info" step=3 next } } # 9 "jnrT" - жанр(ы) (может быть пусто "-") # <li><a href="http://budclub.ru/type/index_type_18-1.shtml">Справочник</a>: <a href="http://budclub.ru/janr/index_janr_20-1.shtml">Естествознание</a> # <li><a href=/type/index_type_16-1.shtml>Глава</a>: <a href="/janr/index_janr_25-1.shtml">Приключения</a>, <a href="/janr/index_janr_1-1.shtml">Фантастика</a> if (step==3) { # третий шаг - дополнительные атрибуты текста, жанр(ы) if (match($0, /<li>(<a href=[^>]*\/type\/index_type_.+<\/a>: .*)$/, aj)){ if(aj[1]=="")jnrT=0 else jnrT=pack(aj[1]) fErr="V eVot:"hitT" someThing wrongWith votes" step=4 next } else if (namT=="\"Информация•о•владельце•раздела\"") { # тут жанров нет в прнципе! jnrT=0 fErr="V eVot:"hitT" someThing wrongWith votes" step=4 next } } # <form action="http://budclub.ru/cgi-bin/votecounter" method=POST> # <form action="/cgi-bin/votecounter" method=POST> # <input type=hidden name=FILE value=fant016 > # <input type=hidden name=DIR value=a/abbakumow_i_n > # <!-- 1 if (step==4) { # четвёртый шаг - оценки... if(match($0,/<form action="[^"]*\/cgi-bin\/votecounter\" method=POST>/)){ step=5 chkLn=NR+2 # 3 обязательные строки в начале блока голосования next } } # 8 votT - оценки (7.07*811, может быть "0") # Оценка: <b>6.71*23</b> # Оценка: <b>5.78*1204</b> # Оценка: <b><a href=/cgi-bin/vote_show?DIR=b/burewojandrej&FILE=knigi>*</a></b> # Оценка: <b><a href=/cgi-bin/vote_show?DIR=s/sagan_i&FILE=psv>7.16*117</a></b> if (step==5) { # пятый шаг - дополнительные атрибуты текста if((NR-chkLn)>0){ if(index($0,"<!--")){ # оценки отключены; в тексте больше нечего делать step=6 fErr="T eTxt:"hitT" someThing wrongWith text1" next } if(match($0,/Оценка: <b><a href=\/cgi-bin\/vote_show\?DIR=.+>(.*\*.*)<\/a><\/b>$/,aj)){ votT=aj[1] if(votT=="*") votT=0 else votT=pack(votT) step=6 fErr="T eTxt:"hitT" someThing wrongWith text2" next } if (match($0, /Оценка: <b>(.*\*.*)<\/b>$/, aj)) { votT=aj[1] if(votT=="*") votT=0 else votT=pack(votT) step=6 fErr="T eTxt:"hitT" someThing wrongWith text3" next } } } if (step==6) { # шестой шаг if(match($0,/<!--[^>]*Собственно произведение[^>]*-->/))chkLn=NR+4 # nvv 2021.05.14 changed # if($0=="<!----------- Собственно произведение --------------->")chkLn=NR+4 if(NR==chkLn){ if(index($0,"<h3>Извините, доступ к этому произведению ограничен.</h3>"))sizT=sizT".0" else sizT=sizT".1" # для обычных текстов, ".0" для -^- хитромудрых # print(sprintf("%11s%11s%8.1f %s %s %s %s",begD,endD,sizT,namA,namT,votT,jnrT),fTxt,fNam) print(sprintf("%11s%11s%8.1f %s %s %s %s",begD,endD,sizT,namA,namT,votT,jnrT),"",fTxt) step=NR next } } if ((step-6)>0) { # завершающмй шаг if(match($0,/<!--[^>]*Блок описания произведения \(слева внизу\)[^>]*-->/)){ # nvv 2021.05.14 # if($0=="<!---- Блок описания произведения (слева внизу) ----------------------->") flgO=1 # if(substr($0,RSTART,5)=="<!---")nNew=0 # else nNew=1 # print nNew,id_P,namP,namT >> "u:\\z.z" # outP($0) # outP("<hr size=2 noshade>") outP("</body>") outP("</html>") fErr="" exit } } } function outP(j1){ # п/п ПЕРЕсоздания чистой копии входного файла if((fOut=="")||(!flgO)) return aOut[++aNum]=j1 } END{ if(fErr!=""){ print("] err:"fErr,fTxt,ARGV[1]) # у нас проблема... exit -1 } for(j1=1;j1<=aNum;j1++)print(aOut[j1])>fOut # 2018.02.25, nvv, creation (siReplsChk.awk) # ... # 2019.01.04, nvv, update # 2019.04.04, nvv, sizB added (== ".0" if "доступ ... ограничен", else == ".1") # 2019.07.04, nvv, работаеи ТОЛЬКО с текстами # 2019.08.05, nvv, update # 2019.12.06, nvv, current unification # 2020.06.13, nvv, обрабатываемая страница буфферизируется; выдача - только если всё ОК # 2021.05.15, nvv, иначе (с доп.пробелами) оформлены некоторые HTML-комментарии у части текстов # пришлось менять метод распознания: независящий от использованного варианта оформления оных # 2021.09.29, nvv, символ 0x1A (Ctrl+Z) - для gAwk == "конец файла" (даже если это не так) # 2022.03.09, nvv, уточнён алгоритм вычленения данных в служебке (при разной подработке текста) # 2022.04.13 nvv, теперь (fOut) в выдаче указывается конечное ИМЯ файла ПОСЛЕ преобразования # 2022.06.29 nvv, введено ограничение maxL длины ника и заголовка текста (защита от идиотов) # 2022.08.16 nvv, исправлена неточность в имени файла с текстом /fTxt/ в выдаче скрипта }
Имя файла скрипта: "dText.cmd" V-текст скрипта-V- - - - - - - - - @if not defined nJob @echo off :: dText.cmd - сборка и оснащение 30d списка 1k топовых текстов доп.данными о них и их гостевых :: основной и резервный URL Самиздата (желательно работать с резервом) :: %time% - HH:MM:SS,tt HH<=9 -> "HH" == " H" лидирующий пробел для часа меньше 10 :: %date% - YYYY.mm.dd :: 2021.11.16, nvv, добавлен запрос на пересборку итога, если он уже собирался (защита от случайного пуска) :: ! история изменений - в подвале echo %date% %time:~0,8% %~nx0 Begs :: siUrl - основной и резервный URL Самиздата (желательно работать с резервом) set siUrl=samlib.ru if exist \siUrl.budclub set siUrl=budclub.ru :: dnLd - счётчик /формально/ успешно скачанного (НЕ 0b) set dnLd=0 :: ratW - темп скачивания (секунд на один файл в среднем) set ratW=0 :: wrks - общее время работы процесса (пуск общего таймера) for /F %%A in ('gawk.exe "BEGIN{print(systime());exit}"') do set wrks=%%A :: основные сеты и прочая подготовка к работе... set errInf= set nJob=dText set mark=;m set awkV=%~dp0%nJob%V.awk set awkR=%~dp0%nJob%R.awk set awkT=%~dp0%nJob%.awk set jDat=%date% :: wDir - общее рабочее место set wDir=%~d0\Jobs :: sDir - общее складское хранилище set sDir=%~d0\Stor set jRpt=%wDir%\_siTop.# :: dirT - склад для топовых текстов (лидеры рейтингов) set dirT=%sDir%\Text :: tHit - сумма всех хитов призёров, попавших в тор1000 set tHit=0 :: счётчики проблем... set errInf= :: nulG гостевая - недоступна: 0b set nulG=0 :: badG гостевая - битая (нет любого на проверяемых страницах): endD,sizT set badG=0 :: rNot гостевая - пуста (нет любого): Dat,rNum set rNot=0 :: zipR гостевая - архив(ы) set zipR=0 :: datJ - верхняя граница интервала дат расчёта (дата в имени файла-списка yyyy.mm.dd.v.lst.bStat) set datJ= :: найти 20??.??.??.v.lst.bStat и запомнить его имя (т.е. дату в нём, например, 2019.07.14.v.lst.bStat) for %%A in (%wDir%\20??.??.??.?.lst.bStat) do set datJ=%%~nA if NOT defined datJ echo ? NO 20??.??.??.?.lst.bStat found & exit set tmp0=%datJ:~11,1% if NOT "%tmp0%" == "~" if NOT "%tmp0%" == "v" ( echo BAD mod "%tmp0%" in %datJ% exit ) set datJ=%datJ:~0,10% set cLst=%wDir%\%datJ%.cChkH :: найти последний 20??.??.??.cChkH и запомнить его имя (т.е. дату в нём, например, 2019.07.14.cChkH) if NOT exist %cLst% echo NO %cLst% found, exit & exit :: если уже собирали именно этот день - запрос "повторить?" if NOT exist %wDir%\%datJ%.%nJob% goto goOn set tmp0= echo %datJ%.%nJob% found; reBuild it? [yes] == y set /p tmp0=?[no]? if /i NOT %tmp0%. == y. echo job canceled {NO to reBuild} & exit :goOn jDir - место для страниц сканируемых гостевых и рабочих файлов set jDir=%wDir%\#mRepl if NOT exist %jDir%\ mkDir %jDir%\ if NOT exist %jDir%\ set errInf=fail mkDir %jDir%\ & goto nExit :: если итоговый список уже принят "к публикации" (суффикс "#"), трогать низя if exist %wDir%\%datJ%.#.%nJob% set errInf=found %wDir%\%datJ%.#.%nJob% (published?!) & goto nExit :: если есть пока непринятый итоговый список, он берётся как опорный для пересборки if exist %wDir%\%datJ%.%nJob% move /y %wDir%\%datJ%.%nJob% %jDir% :: lstJ - список для "siTopTexts" - популярные тексты за 30 дней (со всеми атрибутами) set lstJ=%jDir%\%datJ%.%nJob% :: eLst - несортированный список ПРОБЛЕМ с текстами/гостевыми set eLst=%wDir%\]%nJob%.bad :: hold - опорная дата привязки реплик set hold= :: если перезапуск (есть lstJ) - считать дату привязки, иначе - проверить почистить jDir if exist %lstJ% ( for /F %%J in ('gawk.exe "{if(match($1,/^%mark%$/)){print($3);exit}}" %lstJ%') do set hold=%%J ) else ( if exist %jDir%\*.* erase /F/Q %jDir%\*.* if errorlevel 1 set errInf=fail erase %jDir%\*.* & goto nExit set hold=%jDat% ) :: собирать список должно СЕГОДНЯ! Завтра (если не успели) - всё с начала if NOT %hold%. == %jDat%. ( set hold=%jDat% if exist %jDir%\*.* erase /F/Q %jDir%\*.* if errorlevel 1 set errInf=fail erase %jDir%\*.* & goto nExit ) :: очистим будущие списки рейтинга и ошибок echo %mark% hold %hold% > %lstJ% 2> %eLst% :: tDir - папка для топовых текстов "наших" 30-дней (like: 2019.08.02.text) set tDir=%dirT%\%hold%.text :: должОн бысть (после cChkH.cmd) if NOT exist %tDir%\ set errInf=%tDir% not found & goto nExit :: tmpF - времянка для скачиваемых текстов set tmpF=%tDir%\siTextDL.tmp if exist %tmpF% erase %tmpF% if errorLevel 1 set errInf=FAIL erase %tmpF%& goto nExit :: ok1k - устанавливается, когда оптичены все принятые топовые тексты (+оценки +гостевые к ним) set ok1k= :: linN - счётчик текстов set linN=0 :: wGetSiz - объём файла, полученного с СИ (default 1b) set wGetSiz=1 echo req topTexts... :: запустим "таймер" качалки for /F %%A in ('gawk.exe "BEGIN{print(systime());exit}"') do set ratW=%%A :: hitT hitP numP id_P id_T xDat "namA" "namT" for /F "tokens=*" %%A in (%cLst%) do if NOT defined errInf if NOT defined ok1k call :reqSiText %%A if defined errInf goto nExit :: остановим "таймер" качалки время работы в секундах for /F %%A in ('gawk.exe "BEGIN{print(systime()-%ratW%);exit}"') do set ratW=%%A :: среднее время скачивания файла в секундах if %dnLd% == 0 (set ratW=0) else ( for /F %%A in ('gawk.exe "BEGIN{print(sprintf(\"%%3.2f\",%ratW%/%dnLd%));exit}"') do set ratW=%%A ) :: jLst - конечный список-итог set jLst=%wDir%\%datJ%.%nJob% copy /b/y %lstJ% %jLst% > nul if errorlevel 1 set errInf=fail copy %lstJ% to %wDir% :: преобразуем секунды в время работы (в обычном формате "чч:мм:сс") for /F %%A in ('gawk.exe "BEGIN{print(strftime(\"%%H:%%M:%%S\",systime()-%wrks%+46800));exit}"') do set wrks=%%A :: оформим подвал списка... :: . 3333 159 49066 1821.0 -993 993 2014.07.10 2017.11.30 2018.01.26 "Скс." "Режим•бога" s/sks 111 "6.05*126" 0 "Скс" 10_3834 s-sks.111 rem echo ; hitT.1 numP.2 hitP.3 sizT.4 aNum.5 rNum.6 begD.7 endD.8 aDat.9 ^ rem "namA".10 "namT".11 id_P.12 id_T.13 "votT".14 "jnrT".15 gFil.16 >> %jLst% set tmp0=; hitT.1 numP.2 hitP.3 sizT.4 aNum.5 rNum.6 begD.7 endD.8 aDat.9 set tmp0=%tmp0% "namA".10 "namT".11 id_P.12 id_T.13 "votT".14 "jnrT".15 gFil.16 echo %tmp0% >> %jLst% :: затем сводки от aHits и cChkH gawk.exe "{if(match($1,/^;[1-3].$/))print($0)}" %cLst% >> %jLst% :: ;4T text nulG:0 badG:0 rNot:85 zipR:253 1456:dnLd done:2019.11.28 17:17-17:31 <- штат :: затем собственная сводка set tmp0=;4T text ^ %nulG%:nulG ^ %badG%:badG ^ %rNot%:rNot ^ %zipR%:zipR ^ %tHit%:tHit ^ %dnLd%:dnLd ^ %ratW%~ratW ^ %jDat%:done ^ %wrks%~wrks ^ %time:~0,5% echo %tmp0% >> %jLst% echo %tmp0% >> %jRpt% echo %tmp0% :: подудим где нада "готово-с!" set itog=%jLst% :nExit if exist %tDir%\siTextDL.tmp erase %tDir%\siTextDL.tmp if defined errInf echo !!! %errInf% echo %date% %time:~0,8% %~nx0 Ends goto :eof :reqSiText работа с очередным тектстом и его гостевой if defined ok1k goto :eof set hitT=%1 set oldH=%2 :: всё годно было ДО lowH дальше не интересно if %oldH%. == lowH. (set ok1k=yes & goto :eof) set /a linN+=1 set linR= %linN% set linR=%linR:~-4% :: 1 2 3 4 5 6 7 8 9 :: hitT oldH hitP numP id_P id_T "namP" "namT" sFil :: 9241 : 362225 6 k/kadawr n "Кадавр" "Псион" k~kadawr set hitP=%3 set numP=%4 set id_P=%5 set id_T=%6 set namP=%7 set namT=%8 set gFil=%id_P:~0,1%~%id_P:~2%.%id_T% set curT= %hitT% set curT=%curT:~-6% :: tFil - конечный файл для склада (дОлжен быть!) set tFil=%tDir%\%gFil%.text.html if NOT exist %tFil% set errInf=no %tFil% found & goto :eof set tmp0= for %%J in ( %tFil% ) do set tmp0=%%~zJ :: есть, но нулевой - нужно горхнуть и тащить с СИ if %tmp0% == 0 set errInf=zeroSize %tFil% found & goto :eof :: есть и ненулевой, разберёмся... set fOut= for /F "tokens=*" %%J in ('gawk.exe -f %awkT% %tFil%') do call :chkTxt %%J :: если OK - займёмся оформлением этого текста if "%begD%" == "]" set errInf=bad %tFil% found & goto :eof echo. %linR% = %curT%.Text: %gFil% :: txtInOK теперь оценки, если есть-с... ;) budclub.ru/cgi-bin/vote_show?DIR=n/nosow_w_w&FILE=si_tq1k-curr if exist %tDir%\siTextDL.tmp erase %tDir%\siTextDL.tmp if %votT% == 0 goto votesOK set wUrl="%siUrl%/cgi-bin/vote_show?DIR=%id_P%&FILE=%id_T%" set tmpF=%jDir%\%gFil%.vote.htm if exist %tmpF% ( echo. =Votes goto voteIs ) echo. ? Votes call wGetUrl2fil.cmd %wUrl% %tmpF% if defined errInf goto :eof :: если файл оценок недоступен => текст удалить set errT=] err:V badV %curT% %gFil%.text if %wGetSiz% == 0 set /a nulT+=1 & goto killZero :voteIs проверяем полученное set chkN=0 for /F "tokens=1-4*" %%J in ('gawk.exe -f %awkV% %tmpF%') do ( set balN=%%J& ^ set balM=%%K& ^ set balS=%%L& ^ set balD=%%M) :: если с оценками проблема => текст удалить if "%balN%" == "]]" set /a nulT+=1 & goto killZero set votT="%balM%»%balS%*%balN%" :votesOK теперь гостевая этого текста; страница самых последних реплик rem !!! 2019.11.25, nvv NO guestBooks == NO scanning them atALL rem if defined noRepl goto noRepl rem !!! set wUrl=%siUrl%/comment/%id_P%/%id_T% set tmpF=%jDir%\%gFil%.z00.z1.repl.htm if exist %tmpF% ( echo. =Repls goto replIs ) echo. ? Repls call wGetUrl2fil.cmd %wUrl% %tmpF% if defined errInf goto :eof :: если файл гостевой недоступен... set errT=] err:N nulG %curT% %gFil%.z00.z1.repl if %wGetSiz% == 0 set /a nulG+=1 & goto killZero :replIs проверяем полученное set chkN=0 for /F "tokens=*" %%J in ('gawk.exe -f %awkR% %tmpF%') do call :chkRpl %%J :: если с гостевой текста проблемы, ставим на тексте крест if "%dat0%" == "]" set /a badG+=1 & goto fixErr :: если гостевая пуста, так и запишем... if %dat0% == 0 goto noRepl set aDat=%dat0% set arcN=%num0% set rNum=%num1% set pagN=%num2% :: если ОДНА реплика, без архивов; всё ясно БЕЗ второго запроса if "%arcN%%rNum%" == "01" ( set aNum=%rNum% goto fixNews ) :: архива нет, реплик: 2..1012 == НЕ одна реплика, нужен запрос самой первой в текущих if %arcN% == 0 goto reqCur :: == архив(!) запрос архива set tmp0=0%pagN% set tmp2=00%arcN% set wUrl="%siUrl%/comment/%id_P%/%id_T%.%arcN%?ORDER=reverse&PAGE=%pagN%" set tmpF=%jDir%\%gFil%.%tmp2:~-3%.%tmp0:~-2%.repl.htm if exist %tmpF% ( echo. =Arch goto replA ) echo. ? Arch call wGetUrl2fil.cmd %wUrl% %tmpF% if defined errInf goto :eof :: если файл гостевой недоступен... set errT=] err:N nulG %curT% %gFil%.%tmp2:~-3%.%tmp0:~-2%.repl if %wGetSiz% == 0 set /a nulG+=1 & goto killZero :replA ищем в последнем архиве реплику с тем же номером (или радом;) set chkN=%rNum% for /F "tokens=*" %%J in ('gawk.exe -f %awkR% %tmpF%') do call :chkRpl %%J :: если с гостевой текста проблемы, ставим на тексте крест if "%dat0%" == "]" set /a badG+=1 & goto fixErr :: если гостевая пуста, так и запишем... if %dat0% == 0 goto noRepl :: - архив(ы) сосчитаем set /a zipR+=1 :: pref "-" == number is IN archive set aNum=-%num1% set aDat=%dat0% goto fixNews :reqCur дата первой реплики в текущих set wUrl="%siUrl%/comment/%id_P%/%id_T%?ORDER=reverse&PAGE=1" set tmpF=%jDir%\%gFil%.z00.01.repl.htm if exist %tmpF% ( echo. =Curr#1 goto repl1 ) echo. ? Curr#1 call wGetUrl2fil.cmd %wUrl% %tmpF% if defined errInf goto :eof set errT=] err:N nulG %curT% %gFil%.z00.01.repl :: если файл гостевой недоступен... if %wGetSiz% == 0 set /a nulG+=1 & goto killZero :repl1 set chkN=1 for /F "tokens=*" %%J in ('gawk.exe -f %awkR% %tmpF%') do call :chkRpl %%J :: если с гостевой текста проблемы, ставим на тексте крест if "%dat0%" == "]" set /a badG+=1 & goto fixErr :: если гостевая пуста, так и запишем... if %dat0% == 0 goto noRepl set aDat=%dat0% set aNum=%num1% goto fixNews :noRepl гостевая пуста, отклик по нулям set /a rNot+=1 set aDat= 0 set aNum=0 set rNum=0 :fixNews выгрузка собранных данных в накопительный список set /a tHit+=%hitT% call :formIt %hitT% %numP% %hitP% %sizT% %aNum% %rNum% goto :eof :formIt %hitT% %numP% %hitP% %sizT% %aNum% %rNum% gawk.exe "BEGIN{printf(\"%%7s%%6s%%8s%%8.1f%%6s%%5s\",%1,%2,%3,%4,%5,%6);exit}" >> %lstJ% echo. %begD% %endD% %aDat% %namA% %namT% %id_P% %id_T% %votT% %jnrT% %oldH% %gFil% >> %lstJ% goto :eof :chkTxt begD endD sizT namA namT votT jnrT fNam - вычленение данных по тексту/гостевой :: . . . 1 .. 2 .. 3 .. 4 .. 5 .. 6 .. 7 .. 8 set begD=%1 set endD=%2 set namA=%4 set namT=%5 set sizT=%3 set votT=%6 set jnrT=%7 set errT=%* goto :eof :chkVot %%J balN balM balS set balN=%1 set balM=%2 set balS=%4 goto :eof :chkRpl 1 2 .. 3 .. 4 .. 5 - вычленение данных по тексту/гостевой :: . aDat arcN aNum pagN fNam :: . dat0 num0 num1 num2 set dat0=%1 set num0=%2 set num1=%3 set num2=%4 set errT=%* goto :eof :killZero if exist %tmpF% erase %tmpF% :fixErr с текстом или его гостевой всё плохо, пропускаем (игнорируем этот текст) set /a linN-=1 echo. -X- %errT% echo %errT% %wUrl% >> %eLst% goto :eof :: 2018.08.10, nvv, creation :: ... :: 2020.01.08, nvv, добавлен счётчик tHit - подсчёт суммы хитов всех призёров :: 2020.03.14, nvv, мелкие изменения :: 2020.06.14, nvv, работа не с *.bStat а с *.cChkH <- список с нормализованными хитами за 302 дней :: 2020.08.08, nvv, подправлен оживляж (нагляднее-с;) :: 2020.11.16, nvv, будКлуб - глупость? не факт... ;( :: 2020.12.31, nvv, hitL check added (no votes & repls for low text's hits) :: 2021.04.09, nvv, minor updates :: 2021.04.19, nvv, minor updates :: 2021.05.11, nvv, очередная оптимизация с унификацией...
Имя файла скрипта: "dTextR.awk" V-текст скрипта-V- - - - - - - - - BEGIN{ # siTop-dTextR.awk - (для рейтингов T1000) взять инфу со страниц гостевой текста fErr="] eInP:NO input file" if(ARGV[1]=="")exit # защита от случайного пуска # 2018.02.25, nvv, creation (siReplsChk.awk) # ... # 2019.01.04, nvv, update # 2019.04.04, nvv, sizB added (== ".0" if "доступ ... ограничен", else == ".1") # 2019.07.28, nvv, переименовано + убрана работа с текстами, - только гостевые + реорганизовано # 2019.12.06, nvv, current unification # Скрипт выдаёт на StdOut 5 литералов: #:: aDat,arcN,rNum,pagN,gFil #1 aDat - дата нужной/последней реплики в интервале, в гостевой (2018.07.20) #2 arcN - кол-во архивов (0..999) #3 rNum - номер нужной/последней реплики в интервале, в гостевой (0..1012, может быть пусто "-") #4 pagN - номер нужной/последней страницы гостевой (1..26) #5 gFil - чистое ИМЯ файла текста/гостевой (f-fedorochew_a.major) arcN=0 # кол-во архивов (значения по умолчанию) pagN=1 # кол-во страниц, pageN==1 is default, ever if none rNum=0 # номер найденной реплики aDat=0 # дата этой найденной реплики step=0 # шаг "разбора" страницы текста/гостевой "Самиздата" modSI=1 # ОБРАТНАЯ сортировка реплик на странице гостевой (штатная в СИ) chkN="" # 0==последняя реплика; >0==номер искомой реплики; ""(пусто) - атрибуты текста gFil="" # имя файла, БЕЗ пути и расширения for ( tmp0 in ENVIRON ) { # ! регистр букв в имени переменной может быть любой tmp1 = tolower( tmp0 ) # Temp и temp - РАЗНЫЕ имена для gAwk... if ( tmp1 == "chkn" ) chkN=ENVIRON[tmp0] # номер первой реплики в последней 1000-е if ( tmp1 == "gfil" ) gFil=ENVIRON[tmp0] #чистое ИМЯ файла текста/гостевой (f-fedorochew_a.major) if ( tmp1 == "hitt" ) hitT=ENVIRON[tmp0] # очищенный si-HTML текст } if(hitT)hitT=sprintf("%7s",hitT) fErr="P eAvt:"hitT" NO owner FIO" # бывает-с, хотя и очень редко... if(gFil==""){ # при автономной работе приходится вычленять нужное jr=split(ARGV[1],jArr,":") # drv jr=split(jArr[jr],jArr,"\\") # path tmp1=split(jArr[jr],jArr,".") # name+ext gFil=jArr[1] for(jr=2;jr<tmp1;jr++)gFil=gFil"."jArr[jr] # a-abwow_a_s.fp.z00.01.repl.htm } } function getDat(tmp2) { # выдернуть дату реплики #"<small>91.</small> <b>Алена Николаева</b> <small><i>2018/07/03 12:23 </i> ") { if (match(tmp2, /([0-9]{4})\/([0-9]{2})\/([0-9]{2}) ([0-9]{2}:[0-9]{2}) *<\/i>/,aj)) { return aj[1]"."aj[2]"."aj[3]; # aj[4] игнорируем, только дата, время не нужно } else {return "~???~"}; } function pack(j1) { # заменить мешающие символы на нейтральные + закавычить результат j2="" # TAB -> "•" while(n=index(j1,"\x09")) { j2 = j2 substr( j1, 1, n-1 ) "•"; j1 = substr( j1, n+1 ) } j1=j2 j1 j2="" # пробел -> "•" while(n=index(j1," ")) { j2 = j2 substr( j1, 1, n-1 ) "•"; j1 = substr( j1, n+1 ) } j1=j2 j1 j2="" # неразрывный_пробел -> "•" while(n=index(j1,"\xA0")) { j2 = j2 substr( j1, 1, n-1 ) "•"; j1 = substr( j1, n+1 ) } j1=j2 j1 j2="" # двойные кавычки -> "”" # while(n=index(j1,"\"")) { j2 = j2 substr( j1, 1, n-1 ) "”"; j1 = substr( j1, n+1 ) } while(n=index(j1,"\"")) { j2 = j2 substr( j1, 1, n-1 ) """; j1 = substr( j1, n+1 ) } j1=j2 j1 j2="" # "••" -> "•" while(j0=index(j1,"%")) { j2 = j2 substr( j1, 1, j0-1 ) "%"; j1 = substr( j1, j0+1 ) } j1=j2 j1 j2="" # "••" -> "•" while(n=index(j1,"••")) { j2 = j2 substr( j1, 1, n-1 ); j1 = substr( j1, n+1 ) } j1=j2 j1 if(substr(j1,1,1)=="•") j1 = substr( j1, 2 ) # del "•" at beg n=length(j1) if(substr(j1,n,1)=="•") j1 = substr( j1, 1, n-1 ) # del "•" at end return ("\""j1"\"") } { # <h3>Влад if (!step) { # нулевой шаг - автор if (match($0, /<h3>(.*)$/, aj)) { if(aj[1]=="") exit # == "битая" гостевая (нет ника автора) fErr="H eHdr:"hitT" no title" step=1 next } } # <center><h2>Комментарии: <a href= #<h2>Комментарии: <a href="/k/koshienko_a_g/kniga3.shtml">6 Косплей Сергея Юркина (книга четвёртая)</a><br><small> ()</small></h2> #<center><h2>Комментарии: <a href="/f/fedorochew_a/2018.shtml">Лось</a><br><small> #(Оценка:<b><a href=/cgi-bin/vote_show?DIR=f/fedorochew_a&FILE=2018>8.26*694</a></b>,)</small></h2> # <center><h2>Комментарии: <a href="/p/polishuk_w/zenitchic.shtml">Зенитчик</a> #<br><small> (Оценка:<b><a href=/cgi-bin/vote_show?DIR=p/polishuk_w&FILE=zenitchic #>5.98*169</a></b>,)</small></h2> # {if(match($0,/:<b><a href=\/cgi-bin\/vote_show\?DIR=.+>(.+)<\/a>/,a)) print a[1];exit} if (step==1) { if (tmp0=index($0,"<h2>Комментарии: <a href=")) { $0=substr($0,tmp0+30) match($0, />(.*)<\/a><br>/, aj) # выдернуть название текста, к которому гостевая namT=pack(aj[1]) if ((aj[1]=="")||(aj[1]=="Управление")) exit #== "битая" гостевая (нет или "левое" название) fErr="I eInf:"hitT" bad dates/size" step=2 next } } #<li>Обновлено: 21/05/2018. 1123k. <a #<li>Размещен: 30/04/2019, изменен: 29/06/2019. 231k. <a if (step==2) { if (match($0,/^<li>Размещен: [0-9]{2}\/[0-9]{2}\/(..)?[0-9]{2}\, изменен: [0-9]{2}\/[0-9]{2}\/(..)?[0-9]{2}\. [0-9]+k\. <a/,aj)){ fErr="J eJnr:"hitT" bad janr info" step=3 next } } #<li><a href=/type/index_type_15-1.shtml>Новелла</a>: <a href="/janr/index_janr_5-1.shtml">Проза</a>, <a href="/janr/index_janr_1-1.shtml">Фантастика</a>, <a href="/janr/index_janr_35-1.shtml">Фанфик</a> #<li><a href=/type/index_type_5-1.shtml>Статья</a>: <a href="/janr/index_janr_15-1.shtml">Философия</a>, <a href="/janr/index_janr_10-1.shtml">Переводы</a> #<li><a href=/type/index_type_4-1.shtml>Очерк</a>: if (step==3) { if(match($0, /<li><a href=\/type\/index_type_.+<\/a>: /, aj)){ fErr="" step=4 next } if (namT=="\"Информация•о•владельце•раздела\"") { # тут жанров нет в прнципе! fErr="" step=4 next } } #6 arcN["namA"] кол-во архивов (0..999) #7 pagN["namT"] номер нужной/последней страницы гостевой (1..26) #<center><small> Отсортировано по:[убыванию][<a href=/comment/k/koshienko_a_g/kniga3?ORDER=reverse>возрастанию</a>]</small></center><center><b>Страниц (8):</b> <b>1</b> <a href=/comment/k/koshienko_a_g/kniga3?PAGE=2>2</a> <a href=/comment/k/koshienko_a_g # … <b>Страниц (2) … # … <b>Архивы (46) … if ((step-3)>0) { # навигация есть ТОЛЬКО если ВОЗМОЖНА пересортировка (даже невидимого-с;) if ( index( $0, "> Отсортировано по:[" )) { # в СИ (по умолчанию) сортировка по убыванию, if ( match($0,/<b>Страниц \(([0-9]{1,2})\)/, aj ) ) { pagN=aj[1] if ( match($0,/<b>Архивы \(([0-9]+)\)/, aj ) ) { arcN=aj[1] } } if ((pagN-26)>0) pagN=26 modSI=index($0," по:[убыванию") # признак сортировки: 0==прямая, >0==обратная (по умолчанию) } #1 aDat(11) дата нужной/последней реплики в интервале, в гостевой (2018.07.20) #4 rNum(5) - номер нужной/последней реплики в интервале, в гостевой (0..1012, может быть пусто "-") #"<small>91.</small> <b>Алена Николаева</b> <small><i>2018/07/03 12:23 </i> ") { if ( match($0,/<small>([0-9]+)\.<\/small>/, aj ) ) { step++ rNum=aj[1] # номер очередной реплики ("91") aDat=getDat($0) # дата очередной реплики ("2018,07,03) if(modSI) exit else { if (!chkN) exit else if ((rNum-chkN)>=0) exit # первая в границах } } } } END{ if(fErr!="") print("] err:"fErr,fNam) # у нас проблема print(sprintf("%11s%5s%5s%3s",aDat,arcN,rNum,pagN),gFil) }
Имя файла скрипта: "dTextV.awk" V-текст скрипта-V- - - - - - - - - BEGIN{ # siTop-dTextV.awk - (для рейтингов T1000) взять инфу со страницы оценок текста fErr="]] NO or bad file" if(ARGV[1]=="")exit # защита от случайного пуска # 2019.12.08, nvv, creation gFil="" # имя файла, БЕЗ пути и расширения for ( tmp0 in ENVIRON ) { # ! регистр букв в имени переменной может быть любой tmp1 = tolower( tmp0 ) # Temp и temp - РАЗНЫЕ имена для gAwk... if ( tmp1 == "gfil" ) gFil=ENVIRON[tmp0] #чистое ИМЯ файла текста/гостевой (f-fedorochew_a.major) } if(gFil==""){ # при автономной работе приходится вычленять нужное jr=split(ARGV[1],jArr,":") # drv jr=split(jArr[jr],jArr,"\\") # path tmp1=split(jArr[jr],jArr,".") # name+ext tmp1-- gFil=jArr[1] for(jr=2;jr<tmp1;jr++)gFil=gFil"."jArr[jr] # a-abwow_a_s.fp.z00.01.repl.htm } } # budclub.ru/cgi-bin/vote_show?DIR=n/nosow_w_w&FILE=si_tq1k-curr # budclub.ru/cgi-bin/vote_show?DIR=m/metelxskij_n_a&FILE=wtt-1 #голосования.<br><table align=right cellspacing=0 cellpadding=10 border=0 bgcolor=#e0e0e0> #<tr><td valign=top><b>ВСЕГО: 8.00 * 3</b> #</br><b>8</b>: 2 (отличная книга) #<br><b>6</b>: 1 (нормально) #<br></td> #<tr><td colspan=2 bgcolor=#e5e5e5>Сред. <b>7.33</b> Дисп. <b>0.89</b> #<br><br> #Всего оценок: 1585376</a><br><a href=/rating/top40/>Рейтинг: Сорок лучших</a><br><a href=/rating/top100/>Рейтинг: Топ-500</a><br><a href=/rating/expert/>Рейтинг: Избранное</a></td></tr></td></table><pre><small> <a href=http://samlib.ru/cgi-bin/vote_show? #голосования.<br><table align=right cellspacing=0 cellpadding=10 border=0 bgcolor=#e0e0e0> #<tr><td valign=top><b>ВСЕГО: * 2</b> #</br><b>8</b>: 1 (отличная книга) #<br><b>7</b>: 1 (хорошая книга) #<br></td><tr><td colspan=2 bgcolor=#e5e5e5>Сред. <b>7.50</b> Дисп. <b>0.25</b>. Cnt <b>2</b> #<br><br>Всего оценок: 1584436</a><br><a href=/rating/top40/>Рейтинг: Сорок лучших</a><br><a href=/rating/top100/>Рейтинг: Топ-500</a><br><a href=/rating/expert/>Рейтинг: Избранное</a></td></tr></td></table><pre><small> <a href=http://samlib.ru/cgi-bin/vote_show?ITEM=seVBNdpdUckiE&DIR=n/nilin_a&FILE=plenniki1>66.102.x.xx</a> 8 2019/10/28 10:07:31 Mozilla/5.0 { # вычленение итогов по оценкам: СИ_баллы; кол-во; среднее; дисперсия if(match($0,/=top><b>\ ВСЕГО: ([0-9]+)?\.?([0-9]+)? \* ([0-9]+)<\/b>.+>\ Сред. <b>([0-9]+)\.([0-9]+)<\/b> \ Дисп. <b>([0-9]+)\.([0-9]+)\ .+<br><br>/,aj)){ if(!aj[1])aj[1]=0 # оценок меньше 3-х, балловСИ просто нет if(!aj[2])aj[2]=0 # значит ставим 0.0 вместо fErr="" # N . <-средн.--> <-СИ балл--> <-дисп.--> print sprintf("%4s %2s.%-2s %2s.%-2s %2s.%-2s",aj[3],aj[4],aj[5],aj[1],aj[2],aj[6],aj[7]), gFil exit } } END{ if(fErr!=""){ print fErr,fNam # у нас проблема... exit 1 } }
Имя файла скрипта: "fHtml.awk" V-текст скрипта-V- - - - - - - - - BEGIN{ # fHtml.awk - оформление в HTML рейтинга "siTopTexts" if(ARGV[1]=="")exit # защита от случайного пуска # 2024.08.27, nvv, отключена отметка "Upd" для: "Исходные тексты скриптов" # + """ -> "·" # ! прочая история - в подвале rTyp="<b>siTopTexts</b>" # siTopTexts ancW="t" # общий признак типа рейтинга в якорях, комментах и т.п. ancS=":" # частный признак якоря места (в формате: "ггммвв:NNN" nAnc="nvv" # спец.якорь для первой МОЕЙ вещи ;) flag=0 # флаг для чередующейся раскраски строк таблиц tGap=100 # строк в одной таблице tMax=0 # строк в списке всего maxH=0 # максимальные хиты текста (1-й в рейтингше) totH=0 # сумма хитов всех текстов nAv1=0 # новый автор oldT=0 # размещено более года назад curT=0 # размещено в границах обсчитываемого интервала ficT=0 # фикция (за верхней границы интервала) nTx1=0 # вверх nTx2=0 # новинки nTx3=0 # вниз nSz1=0 # объём+ nSz2=0 # объём- nUs1=0 # успех+ nUs2=0 # успех- rNew=0 # число гостевых со свежими репликами tNot=0 # число мошенников с ограниченным доступом mNot="<b>~ ? ~</b>" updH=0 # поправленные хиты за "30 дн." dOld="" hDat=-1 # donH=-1 hPag=-1 nHit=-1 hitL=-1 hMax=-1 nulG=-1 badG=-1 rNot=-1 zipR=-1 # "/" == общий префикс урла СИ: samlib.ru nUrl="n/nosow_w_w" # nvv-с... # jDat=strftime("%y%m%d%H%M%S",systime()) # дата для якорей таблиц for ( jj in ENVIRON ) { # ! регистр букв в имени переменной может быть любой j1=tolower(jj) if ( j1 == "fold" ) fOld=ENVIRON[jj] # ИМЯ опорного файла (like 2018.11.29.mText) if ( j1 == "hdir" ) hDir=ENVIRON[jj]"\\" # место для файлов *.HTML } if(fOld==""){ fOld="U:\\Stor\\Text\\zOld.dTexts\\2023.10.24.dText" fOld="U:\\Jobs\\2023.10.24.dText" hDir=".\\" } nMth[ 1]="января" nMth[ 2]="февраля" nMth[ 3]="марта" nMth[ 4]="апреля" nMth[ 5]="мая" nMth[ 6]="июня" nMth[ 7]="июля" nMth[ 8]="августа" nMth[ 9]="сентября" nMth[10]="октября" nMth[11]="ноября" nMth[12]="декабря" color[0]="\"#FFFFE0\"" # (четная строка таблицы) светло-жёлтый line color 0 color[1]="\"#F5F5DC\"" # (НЕчетная строка таблицы) грязно-жёлтый line color 1 color[2]="\"#C0C0C0\"" # gray серый (всё плохо) color[3]="\"#FFF4E0\"" # светло-розовый (ниже, меньше, плохо, нет) color[4]="\"#F0FFE0\"" # светло-зелёный (выше, больше, хорошо) color[5]="\"#FFFFB0\"" # светло-жёлтый - новое color[6]="\"#FFFF70\"" # yellow желтый (нечётные ячейки в шапках таблиц) color[7]="\"#F8F8F8\"" # светло-серый - наш рейтинг color[8]="\"#0000FF\"" # синий (птичка nvv) color[9]="\"#000000\"" # чёрный (вратый объём) color[10]="\"#E8F8B8\"" # зелёный - ячейки с текстом нашего рейтинга color[11]="\"#E0F8FF\"" # светло-сиреневый - размещено "давно" больше года назад color[12]="\"#FFD700\"" # оранжевый "потеряшки" /скрытые разделы/ aad2 jr=split(ARGV[1],aq,"\\") # U:\Jobs\#qMonths\ +2020.06.03.vText dEnd=substr(aq[jr],1,10) fOut=hDir aq[jr] ".html" # U:\Stor\Html\ +2020.06.08.dText +.html fPre=hDir aq[jr] ".z.html" # U:\Stor\Html\ +2020.06.08.dText +.z.html rYea=substr(aq[jr],1,4) # год рейтинга !привязан к верхней дате выборки rMth=substr(aq[jr],6,2) # месяц его же rDay=substr(aq[jr],9,2) # день его же dBeg=strftime("%Y.%m.%d",mktime(rYea" "rMth" "rDay" 12 00 00")-86400*29) # дата 1-го дня выборки yBeg=substr(dBeg,1,4) # год этого 1-го дня интервала нашей выборки oldD=rYea-1"."rMth"."rDay # "год назад" - привязка к КОНЦУ нашей выборки tOld="года" qGap="30дн." info="<!-- (L) nvv; type: '30days' done: }"strftime("%Y.%m.%d %H:%M")"{ -->" # mark HTML inf2="<!-- (L) nvv; type: '30days' \"prev siTopTexts\" "strftime("%Y.%m.%d %H:%M")" -->" print "--- " strftime("%H:%M:%S") " Begs..." # начали работу (оживляж;) # † массив строк шапки общий # # информационная вставка --> • ¦ » • ¦ » if(strftime("%j")-355>0)jj="С наступающим" else if(strftime("%j")-11<0)jj="С" else jj="" if(jj!=""){ aHnY[++nHnY]="<table align=center border=0 cellspacing=0 cellpadding=2>" aHnY[++nHnY]="<tr align=center bgcolor=navy><td><font size=+2 color=aqua>" aHnY[++nHnY]="<b> ❄ "jj" новым годом! <font color=white>❄" aHnY[++nHnY]="<font size=+2 color=lime>Happy New Year! ❄ </b></td>" aHnY[++nHnY]="</tr></table>" aHnY[++nHnY]="<hr>" } # aHdr[++nHdr]="<table align=center border=1 cellspacing=0 cellpadding=2>" # aHdr[++nHdr]="<tr align=center bgcolor=LightYellow><td><font size=+1><b> NB." # aHdr[++nHdr]="В <a href=/comment/"nUrl"/si_top500look-curr>гостевой</a>" # aHdr[++nHdr]="(реплика #58.) - <font color=brown>ОПРОС..." # <font color=brown> # aHdr[++nHdr]="</font>Мне интересно ваше мнение. :-! </b></td>" # aHdr[++nHdr]="</tr></table>" # aHdr[++nHdr]="<hr>" # # <!-- информационная вставка (справка в шапке) aHdr[++nHdr]="См. <i>также</i>:" aHdr[++nHdr]="<br>?" aHdr[++nHdr]="<a href=/"nUrl"/si_pop-brief.shtml>Как узнать<b>" aHdr[++nHdr]="популярность произведения</b> в \"Самиздате\"</a>" aHdr[++nHdr]="(\"<b>где/что смотреть</b>\" - основное, вкратце)." # † массив строк шапки ТОЛЬКО у последнего рейтинга aHdr[++nHdr]="<br>+" aHdr[++nHdr]="<a href=/"nUrl"/si_top6author-curr.shtml>" aHdr[++nHdr]="Рейтинг <b>siTopAuthors</b> \"Авторы\"</a>" aHdr[++nHdr]="(\"Самиздат\" <b>намедни</b>, приложение к "rTyp")." aHd1[++nHd1]="<br>#" # aHd1[++nHd1]="<font color=\"#DC143C\">Upd</font>" # 2024.07.27 11:43 aHd1[++nHd1]="<a href=/"nUrl"/sitopscriptslist.shtml>" aHd1[++nHd1]="Исходные <b>тексты скриптов</b> задач \"<b>siTop…</b>\"</a>" # aHd1[++nHd1]="<br>=" # aHd1[++nHd1]="<a href=/"nUrl"/si_top100repls-current.shtml>" # aHd1[++nHd1]="Сборка "rTyp"</a> (среда," # aHd1[++nHd1]="<i>скрипты</i>, обстоятельства и рекомендации)." aHd1[++nHd1]="<br>*" # aHd1[++nHd1]="<font color=\"#DC143C\">Upd</font>" # 2024.02.07 11:51 aHd1[++nHd1]="<a href=/"nUrl"/si_top-old_ones.shtml>История-<b>Р</b>," aHd1[++nHd1]="\"<i>прикопанное</i>\" <b>прошлое</b></a>" aHd1[++nHd1]="(ссылки на подборки старых рейтингов по полугодиям)." aHd1[++nHd1]="<br>±" # <font color=red size=-2>New</font>" aHd1[++nHd1]="<a href=/n/nosow_w_w/si_votes-brief.shtml><b>Оценка произведений</b>" aHd1[++nHd1]="в \"Самиздате\"</a> (<b>что, где, как</b> и почему…)." aHd1[++nHd1]="<br>√" aHd1[++nHd1]="<a href=/n/nosow_w_w/si-ini_reg.shtml><b>Регистрация</b> в \"Самиздате\" для получения" aHd1[++nHd1]="статуса «<b>пользователь</b>»</a> (оформление своего аккаунта)." aHd1[++nHd1]="<hr>" aHd1[++nHd1]="<b>NB.</b> <i>Названия</i> произведений и <i>псевдонимы</i>" aHd1[++nHd1]="авторов (как и прочие <i>сведения</i> в таблицах) приведены" aHd1[++nHd1]="<i>\"<a title=\"как есть\"" aHd1[++nHd1]="href=\"https://ru.wikipedia.org/wiki/%D0%9A%D0%B0%D0%BA_%D0%B5%D1%81%D1%82%D1%8C\"><u>as" aHd1[++nHd1]="is</u></a>\", по состоянию на момент</i> сбора" aHd1[++nHd1]="данных. <i>Текущее</i> состояние можно узнать, пройдя" aHd1[++nHd1]="<i>по ссылкам</i> (в ячейках таблиц)." aHd1[++nHd1]="<br><b>(!)</b> <i><u>Если</u></i> на месте некоторых букв" aHd1[++nHd1]="(символов) в <i>названии</i> произведения или в <i>псевдониме</i>" aHd1[++nHd1]="автора вы видите \"<i><u>пустоту</u></i>\", то <i><u>у" aHd1[++nHd1]="вас</u></i>, скорей всего, <i><u>отсутствует</u></i>" aHd1[++nHd1]="шрифт с такими символами (иероглифы, руны, etc.)." aHd1[++nHd1]="<br><b>(#)</b>" aHd1[++nHd1]="<i>Скрытые</i> авторы <u><i>отсутствуют</i></u>" # <font color=\"#A52A2A\"></font> aHd1[++nHd1]="в \"<a href=/rating/hits/>Рейтинге по количеству посетителей</a>\"." aHd1[++nHd1]="<br><b>(~)</b>" aHd1[++nHd1]="<i>Новые</i> авторы/произведения отсутствовали в <i><u>предыдущем</u></i> рейтинге." aHd1[++nHd1]="<br><b>(+)</b>" # aHd1[++nHd1]="<font color=\"#DC143C\">NEW</font>" # 2023.10.28 crimson aHd1[++nHd1]="<i>Новые</i> отклики\" появились в гостевой" # <font color=\"#884700\">\"</font> aHd1[++nHd1]="<u><i>после</i></u> сборки предыдущего рейтинга." } function dat_str(d0,d2) { # "2020.05.23" -> "23 мая" (d2==nul) or "23 мая 2020 г." (d2!=nul) d1=split(d0,ad,".") if(!d2)return("<b>"ad[3]+0" "nMth[ad[2]+0]"</b>") else return("<b>"ad[3]+0" "nMth[ad[2]+0]"</b> "ad[1]" г.") } function mkPage() { # сборка всей страницы рейтинга/приложения (тип, строк, куда-с) # † массив строк шапки краткой справки последнего рейтинга aTb1[++nTb1]="<hr>" aTb1[++nTb1]="" aTb1[++nTb1]="<table align=center border=1 cellspacing=0 cellpadding=2>" aTb1[++nTb1]="<tr align=center>" aTb1[++nTb1]="<td bgcolor="color[1]" colspan=\"14\">Краткая сводка + цвет некоторых" aTb1[++nTb1]="ячеек таблиц (<i>предыдущий рейтинг -" aTb1[++nTb1]="<a href=/"nUrl"/si_top500look-prev.shtml><b>"dOld"</b></a></i>)</td></tr>" # † массив строк шапки краткой справки ПРЕДпоследнего рейтинга aTb2[++nTb2]="<hr>" aTb2[++nTb2]="" aTb2[++nTb2]="<table align=center border=1 cellspacing=0 cellpadding=2>" aTb2[++nTb2]="<tr align=center>" aTb2[++nTb2]="<td bgcolor=\"#F5F5DC\" colspan=\"14\">Краткая сводка + цвет некоторых" aTb2[++nTb2]="ячеек таблиц (<i>предыдущий рейтинг - "dOld"</i>, последующий" aTb2[++nTb2]="- <a href=/"nUrl"/si_top500look-curr.shtml><b>здесь</b></a>)</td></tr>" # † массив строк тела краткой справки общий aTbl[++nTbl]="<tr align=center><td bgcolor="color[0]" colspan=\"1\"><b>N</b>," aTbl[++nTbl]="сдвиг места</td></td>" aTbl[++nTbl]="<td rowspan=\"4\"></td>" aTbl[++nTbl]="<td bgcolor="color[0]"><b>Произведения</b></td>" aTbl[++nTbl]="<td rowspan=\"4\"></td>" aTbl[++nTbl]="<td bgcolor="color[0]"><b>Авторы</b></td>" aTbl[++nTbl]="<td rowspan=\"4\"></td>" aTbl[++nTbl]="<td bgcolor="color[0]"><b>Размещено</b></td>" aTbl[++nTbl]="<td rowspan=\"4\"></td>" aTbl[++nTbl]="<td bgcolor="color[0]"><b>Объём</b> стал</td>" aTbl[++nTbl]="<td rowspan=\"4\"></td>" aTbl[++nTbl]="<td bgcolor="color[0]"><b>Оценки</b></td>" aTbl[++nTbl]="<td rowspan=\"4\"></td>" aTbl[++nTbl]="<td bgcolor="color[0]"><b>Отклики</b></td>" aTbl[++nTbl]="</tr><tr align=center>" aTbl[++nTbl]="<td bgcolor="color[4]">вверх.<b>" nTx1"</b></td>" aTbl[++nTbl]="<td bgcolor="color[5]"rowspan=\"2\">новые.<b>"newN"</b></td>" # aTbl[++nTbl]="<td bgcolor="color[5]">новые.<b>"newN"</b></td>" # aTbl[++nTbl]="<td bgcolor="color[5]"rowspan=\"2\">новые.<b>"nAv1"</b></td>" aTbl[++nTbl]="<td bgcolor="color[5]">новые.<b>"nAv1"</b></td>" aTbl[++nTbl]="<td bgcolor="color[4]">"qGap"<b>"curT"</b></td>" aTbl[++nTbl]="<td bgcolor="color[4]">больше.<b>"nSz1"</b></td>" aTbl[++nTbl]="<td bgcolor="color[4]">хорошие.<b>"nUs1"</b></td>" aTbl[++nTbl]="<td bgcolor="color[5]">новые.<b>"rNew"</b></td>" aTbl[++nTbl]="</tr><tr align=center>" aTbl[++nTbl]="<td bgcolor="color[3]">вниз.<b>" nTx3"</b></td>" # aTbl[++nTbl]="<td bgcolor="color[12]">скрытые.<b>"newN"</b></td>" aTbl[++nTbl]="<td bgcolor="color[12]">скрытые.<b>"length(a90)"</b></td>" aTbl[++nTbl]="<td bgcolor="color[11]">давно.<b>"oldT"</b></td>" aTbl[++nTbl]="<td bgcolor="color[3]">меньше.<b>"nSz2"</b></td>" aTbl[++nTbl]="<td bgcolor="color[3]">плохие.<b>"nUs2"</b></td>" aTbl[++nTbl]="<td bgcolor="color[3]">нет.<b>"rNot"</b></td>" if(tNot){ aTbl[++nTbl]="</tr><tr align=center>" aTbl[++nTbl]="<td></td><td></td><td></td><td></td>" aTbl[++nTbl]="<td title=\"Доступ ограничен\" bgcolor="color[9]\ "><font color="color[6]">"mNot" "tNot"</font></td>" } aTbl[++nTbl]="</tr></table>" aTbl[++nTbl]="<table align=center border=0 cellspacing=0 cellpadding=2><tr>" aTbl[++nTbl]="<td>(</td>" aTbl[++nTbl]="<td bgcolor="color[11]"><b><i>давно</i></b> –" aTbl[++nTbl]="больше <b>"tOld"</b> назад</td>" aTbl[++nTbl]="<td>)</td>" aTbl[++nTbl]="</tr></table>" # aTbl[++nTbl]="<table align=center border=0 cellspacing=0 cellpadding=2><tr>" # aTbl[++nTbl]="<td bgcolor="color[4]"><b>NB.</b> Хиты" # aTbl[++nTbl]="произведений, опубликованных <b>после</b>" # aTbl[++nTbl]=dat_str(dBeg)", учтены <u>по факту</u>" # aTbl[++nTbl]="(„<b>¦</b>“ - с даты размещения)" # aTbl[++nTbl]="</tr></table>" aTbl[++nTbl]="<hr>" aTbl[++nTbl]="" aTbl[++nTbl]="<font size=\"-2\" face=monospace color="color[8]">" aTbl[++nTbl]=" /\\ /\\ <br>" aTbl[++nTbl]=" ·--·--·--· <br>" aTbl[++nTbl]=" \\/ <br>" aTbl[++nTbl]=" /\\ <br>" aTbl[++nTbl]=" ·--· <br></font>" # † титулы (названия) и рейтинга и его копии "Предыдущий" Ttl1="<center><font size=\"+2\">Рейтинг "rTyp"-"ancD"</font>" Ttl2="<center><font size=\"+2\">Предпоследний рейтинг "rTyp"-"ancD"</font>" # † массив строк тела рейтинга (всё оставшееся кроме последней строки) aOut[++nOut]="<br>\"Самиздат\", самые популярные произведения" aOut[++nOut]="<table align=center border=0 cellspacing=0 cellpadding=2>" aOut[++nOut]="<tr bgcolor="color[4]">" j0="с "dat_str(dBeg) if(yBeg!=rYea)j0=j0" "yBeg" г." j0=j0" по "dat_str(dEnd,1)" " aOut[++nOut]="<td> за 30 дней: "j0"</td>" # if(dOff!="0.0")aOut[++nOut]="<td bgcolor="color[3]">(<i><u>нет данных</u> за: "dOff"</i>)</td>" aOut[++nOut]="</tr></table></center></blockquote>" bLin=mkCap() # шапка - первая (нулевая-с) строка таблиц lMax=tMax # всего строк в таблице for ( tIni=1; tIni<=lMax; tIni=tIni+tGap ) { aOut[++nOut]="<blockquote>" # начало очередной таблицы aOut[++nOut]="<table align=center border=1 cellspacing=0 cellpadding=2>" # навигация в aOut[++nOut]="<caption><a id=\""ancD ancW tIni"\"></a>"mkGoTo(tIni)"</caption>" # заголовке aOut[++nOut]=bLin # шапка таблицы tEnd=tIni+tGap for (tBeg=tIni;tBeg<tEnd;tBeg++) { if(tBeg<=lMax) aOut[++nOut]=mkTabLn(tBeg,ordr[tBeg]) # строка данных в таблице } if ((tBeg-tMax)>=0) aOut[++nOut]=bLin aOut[++nOut]="</table>" # таблица готова aOut[++nOut]="</blockquote>" # закрытие блока } aOut[++nOut]="<blockquote>" # подвал страницы aOut[++nOut]="<center>" mkGoTo(0) "</center>" # заголовке aOut[++nOut]="<ul>" aOut[++nOut]="<table border=0 cellspacing=0 cellpadding=2><tr>" # навигация в aOut[++nOut]="<td><b>Попутные сведения</b> (к "rTyp"-"ancD")" aOut[++nOut]="<td></tr></table>" aOut[++nOut]="<li>Справочник ИСС-СИ" aOut[++nOut]="\"<a href=/rating/hits/index.shtml><i><b>Рейтинг по количеству" aOut[++nOut]="посетителей</b></i></a>\" за <b>"hDat"</b>." aOut[++nOut]="<br>(от "dat_str(donH)", всего страниц: "hPag")" aOut[++nOut]="<br>Интервал хитов (<u>за 12мес</u>) у отобранных разделов:" aOut[++nOut]="<ul>" aOut[++nOut]="<li><i>Лидер</i> (1-е место): <b>"hMax"</b>." aOut[++nOut]="<li><i>Замыкающий</i> ("nHit"-е): <b>"hitL"</b>." aOut[++nOut]="</ul>" aOut[++nOut]="<li><i>Прочие</i> данные - по состоянию на "dat_str(hold)"." if(updH)aOut[++nOut]="<li>Произведения с хитами <i>по факту</i> „<b>¦</b>“: <b>"updH"</b>." j0=0 for(j1 in a90)j0=j0+a90[j1] if(j0)aOut[++nOut]="<li>Произведения из „<i>скрытых</i>“ разделов: <b>"j0"</b>." aOut[++nOut]="<li>Среди гостевых (у <b>"tMax"</b> произведений списка):" aOut[++nOut]="<ul>" if(nulG)aOut[++nOut]="<li><i>недоступные</i>: <b>"nulG"</b>;" if(badG)aOut[++nOut]="<li><i>повреждёные</i>: <b>"badG"</b>;" if(rNot)aOut[++nOut]="<li><i>пустые</i> (кулуары•\"<i>антимат</i>\"•без реплик): <b>"rNot"</b>;" if(zipR)aOut[++nOut]="<li><i>с архивами</i>: <b>"zipR"</b>." aOut[++nOut]="</ul>" if(tNot){ aOut[++nOut]="<br><table border=0 cellspacing=0 cellpadding=2><tr bgcolor="color[9]">" aOut[++nOut]="<td><font color="color[6]"> Произведения с <b>ограниченным</b>" aOut[++nOut]="("mNot") <i>доступом</i>: <b>"tNot"</b>. </td>" aOut[++nOut]="</tr></table>" } aOut[++nOut]="</ul>" aOut[++nOut]="<table align=center border=0 cellspacing=0 cellpadding=2>" # навигация в aOut[++nOut]="<tr><td>(copyleft "rYea"</td>" aOut[++nOut]="<td bgcolor="color[6]"><b>/\\/.\\/.\\/.</b></td><td>)</td></tr></table>" } function mkCap() { # сборка шапки соответствующего типа таблиц (птичка или ссылка в ячейке) tmp0= "<tr align=center bgcolor="color[flag]">" # шапки начало; v-место:хиты tmp0=tmp0 "<td title=\"Место:сдвиг в списке, Хиты:за "qGap"\" bgcolor="color[6]"><b>N</b>: Хиты</td>" tmp0=tmp0 "<td><b>Произведение</b></a></td>" # Произведение tmp0=tmp0 "<td bgcolor="color[6]"><a title=\"Раздел за 12мес: хиты, место\"><b>Автор(ы)</b></a></td>" # Автор tmp0=tmp0 "<td><a title=\"Дата создания текста + дата его последнего изменения\"" # Создан +v tmp0=tmp0 "><small>Размещено *<b>Изменено</b></small></a></td>" # ^+ Создан tmp0=tmp0 "<td bgcolor="color[6]"><a title=\"Текст в килобайтах\"" # Объём +v tmp0=tmp0 "><small><b>Объём</b></small></a></td>" # ^+ Объём tmp0=tmp0 "<td><a title=\"Текста\"><small><b>Форма</b>: Жанр(ы)</small></a></td>" # Форма: Жанр(ы) tmp0=tmp0 "<td bgcolor="color[6]"><a title=\"Уровень=(Оценки-5.5)*ln(голоса)\"" # Оценки +v tmp0=tmp0 "><small><b>Оценка</b></small></a></td>" # ^+ Оценки tmp0=tmp0 "<td><a title=\"Реплик в сутки\"" # Отклик +v tmp0=tmp0 "><small><b>Отклик</b></small></a></td>" # ^+ Отклик return( tmp0 "</tr>" ) # шапка готова } function mkTabLn(nLn,tLn) { # таблица: сборка строки номер nLn (строка siTopTexts за номером tLn) flag=!flag # чередующаяся раскраска строк hLin="<tr align=center bgcolor="color[flag]">" # собираем очередную строку... hLin=hLin"<td "a00[tLn]" title=\""a02[tLn]"\"><a id=\""ancD ancS nLn"\"></a><b>"nLn"</b>: " # <- место:хиты -v if(a23[tLn]!="")hLin=hLin"<a title=\"Хиты по факту.\"" else hLin=hLin"<a title=\"Хиты за "qGap"\"" hLin=hLin "href=/"a10[tLn]"/stat.shtml#"a20[tLn]".shtml>"a22[tLn] a23[tLn]"</a></td>" # <-место:хиты-^ hLin=hLin "<td align=left" # <- text -v if(a10[tLn]==nUrl) hLin=hLin " bgcolor=" color[10] # nvv line ;) else if(a00[tLn]==" bgcolor="color[5])hLin=hLin " bgcolor="color[5] # new text hLin=hLin "><a href=/" a10[tLn] "/" a20[tLn] ".shtml id=\"" ancA[tLn] ancS a20[tLn] # <- text -^ hLin=hLin "\">" a21[tLn] "</a></td><td align=left" # ^- text -> <- автор-v if(a10[tLn]==nUrl) hLin=hLin " bgcolor=" color[10] # nvv line ;) else{ if(a12[tLn]) hLin=hLin a77[tLn] # у автора/раздела ЕСТЬ место в рейтинге "по хитам" 2023.06.24 else hLin=hLin " bgcolor=" color[12] } hLin=hLin "><a href=/"a10[tLn]"/ id=\"" ancA[tLn] "\" title=\"Хиты:"a13[tLn] if(a12[tLn]) hLin=hLin ", место:"a12[tLn]a78[tLn]"\">" a11[tLn] "</a></td>" # <- автор -^ else hLin=hLin ", скрытый\">" a11[tLn] "</a></td>" # <- автор -^ hLin=hLin "<td "a34[tLn]"><small>"a30[tLn]" *<b>"a31[tLn]"</b></small></td>" # изменено/размещено (текст) if(a33[tLn]) hLin=hLin "<td align=right"a81[tLn]">" a82[tLn] a32[tLn] "k"a83[tLn]"</td>" # <- объём else hLin=hLin "<td align=right title=\"Доступ ограничен\" bgcolor="color[9]"><font color="\ color[6]">"a32[tLn] "</font></td>" # <- объём, "доступ ограничен" -^ hLin=hLin "<td><small>" a40[tLn] "</small></td>" # жанр(ы) if(a50[tLn]==0)hLin=hLin "<td><small>--</small></td>" # оценки+успех +v else{ hLin=hLin "<td"a52[tLn]"><a title=\"Среднее » баллыСИ *шт. ==Уровень: "a51[tLn] hLin=hLin "\" href=/cgi-bin/vote_show?DIR="a10[tLn]"&FILE="a20[tLn]">" hLin=hLin "<small>"a50[tLn]"</small></a></td>" # ^+ оценки+успех } if(a62[tLn]==-1)hLin=hLin"<td bgcolor="color[2]"><small>-X-</small></td>" # <- недоступно-с else if(a62[tLn]==0){ # <- гостевая пуста hLin=hLin "<td bgcolor="color[3]" title=\"Пусто или кулуары\"><small>" hLin=hLin "<a href=/comment/"a10[tLn]"/"a20[tLn]">:)(:</a></small></td>" }else{ hLin=hLin "<td" if(a65[tLn])hLin=hLin " bgcolor="color[5] hLin=hLin "><small><a href=/comment/"a10[tLn]"/"a20[tLn] # отклик -v hLin=hLin " title=\"Реплик в сутки (шт./дни): "a63[tLn] # v- отклик -^ if(a65[tLn])hLin=hLin "++" hLin=hLin "\">"a64[tLn]"</a></small></td>" # ^- отклик } return (hLin "</tr>") # строку собрали, вываливаем! } function mkGoTo(lCur) { # сборка строки навигации для титула таблиц lBeg=1 # начало очередного интервала lEnd=lBeg+tGap-1 # и его конец if ((lEnd-lMax)>0) lEnd=lMax # но не выше общего конца sNav="<center>Интервал <b>N</b>: <b>" # начало строки навигации for(j0=1;j0<=lMax;j0++) { if (j0==lBeg) { # компоновка очередного элемента навигации if ((lBeg-1)>0) sNav=sNav " | " # первый разделитель опускаем if (lBeg==lCur) sNav=sNav "<big>" lBeg "-" lEnd "</big>" # это у своей таблицы, v-иначе else { sNav=sNav "<a title=\"Перейти к интервалу: " lBeg "-" lEnd "\" href=\"#" sNav=sNav ancD ancW j0"\">" lBeg "-" lEnd "</a>" # оформление как ссылка на ЯКОРЬ } lBeg=lEnd+1 # сдвинем границы на шаг tGap lEnd=lEnd+tGap if ((lEnd-lMax)>0) lEnd=lMax } } sNav=sNav"</b></center>" # завершение строки return(sNav) } # hitT numP hitP sizT aNum rNum begD endD aDat "namA" "namT" id_P id_T votT jnrT down gFil # $1 $2 $3 $4 $5 $6 $7 $8 $9 $10 $11 $12 $13 $14 $15 $16 $17 # 24659 12 332071 275.1 -478 478 2018.07.01 2018.11.11 2018.07.18 "Федорочев•Алексей" "Лось" f/fedorochew_a 2018 "6.89*760" 0 v f-fedorochew_a.2018 # 1966 116 59167 1821.1 -199 199 2014.07.10 2017.11.30 2018.02.23 "Скс." "Режим•бога" s/sks 111 0 0 : s-sks.111 { # загрузка исходного списка (с разборкой и оформлением значений, отображаемых в ячейках) if(match($1,/^[0-9]+$/)){ # признак - "строка основных данных" tMax++ jj=NR-1 # 1-st line - hold date a00[jj]=0 # пока неизвестная позиция текста в предыдущем bStat.20??.??.# a01[jj]=jj # позиция текста в siTopTexts a02[$12"/"$13]=jj # обратная ссылка на позицию по урлу текста a10[jj]=$12 # автор, id_P - урл раздела (мой - n/nosow_w_w;) a11[jj]=unpack($10) # автор, namA - ФИО a12[jj]=$2 # автор, numP - позиция раздела в рейтинге посещаемости "по зитам" 2023.06.24 if(!a12[jj])a90[$12]++ # СКРЫТЫЙ раздел, учтём произведение из 2023.06.23 a13[jj]=$3 # автор, hitP - хиты раздела (в рейтинге посещаемости) a20[jj]=$13 # текст, id_T - имя файла (без расширения .shtml) ancA[jj]=substr($12,1,1)"~"substr($12,3) # формат: "aChr~aNik" a21[jj]=unpack($11) # текст, namT - заголовок a22[jj]=$1 # текст, hitT - хиты текста (в статистике раздела) if(match($16,/^[0-9]+\]$/)){ a23[jj]="<b>¦</b>" # 16317. updH++ }else a23[jj]="" a30[jj]=rusDat($7) # текст, begD - дата размещения в разделе a31[jj]=rusDat($8) # текст, endD - дата последнего изменения split($4,aq,".") a32[jj]=aq[1] # текст, sizT - объём в килобайтах a33[jj]=aq[2] # текст, sizB - "1"==объёмOk, "0"=="доступ ... ограничен" if(!aq[2]){ tNot++ # учтём и сосчитаем мошенника... :( a32[jj]=mNot # и покажем фигу, ВМЕСТО "размера" } a34[jj]=$7 # текст, создан в формате гггг.мм.дд a40[jj]=unquot(unpack($15)) # текст, jnrT - жанр(ы) (может отсутствовать) a50[jj]=unpack($14) # текст, votT - оценки (могут отсутствовать) a60[jj]=$5 # гостевая, aNum номер первой реплики интервала (с минусом == в архиве) a61[jj]=$6 # гостевая, rNum номер последней реплики интервала (текущая) a62[jj]=$9 # гостевая, aDat дата первой реплики интервала if(jj==1)maxH=$1 # максимальные хиты текста (1-й в рейтингше) totH=totH+$1 # сумма хитов всех текстов }else{ if($1 $2==";m""hold") { # сводки сведения + проблемы, замеченные при сборе данных # ;m hold 2019.07.29 hold=$3 # дата сборки "yyyy.MM.dd" ancD=substr(hold,3,2) substr(hold,6,2) substr(hold,9,2) # дата сборки "yyMMdd" }else{ # ;1A hits 2:xNam 445:xNum 101285:xPas 2021.04.22:hDat 1018:hPag 806772:hMax 1018:DnLd 2021.04.27:done 25:mins gapT~14:53-15:18~ # ;2B stat 2021.04.27:sEnd 23:nPre 0:hPre 23:miss 300:minT 552:hitL 30072:nHit 806772:hMax last~00:26:00~ # ;2C scan 2021.04.24:dEnd 29987:nEnd 60688:hEnd 30010:nMig 1593:tNum 10:nGis 29174:nLow mod:v OkV:99.9% # ;4T text 0:nulG 0:badG 78:rNot 197:zipR 1479659:tHit 0:dnLd 2021.04.27:done 2:mins 16:07-16:09:gapT if(match($0,/^;1A .+ 20..\.(.+)\.(.+):hDat /,aj))hDat=aj[2]"/"aj[1] # дата aHits по СИ-шному if(match($0,/^;1A .+ ([\.0-9]+):done /,aj)) donH=aj[1] # дата "скачан" (aHits) if(match($0,/^;1A .+ ([0-9]+):hPag /,aj)) hPag=aj[1] # страниц aHits if(match($0,/^;1A .+ ([0-9]+):hMax /,aj)) hMax=aj[1] # хиты раздела-лидера aHits if(match($0,/^;2B .+ ([0-9]+):nHit /,aj)) nHit=aj[1] # точное число топовых разделов if(match($0,/^;2B .+ ([0-9]+):hitL /,aj)) hitL=aj[1] # хиты замыкающего за "12мес" if(match($0,/^;4T .+ ([0-9]+):nulG /,aj)) nulG=aj[1] # гостевая недоступна if(match($0,/^;4T .+ ([0-9]+):badG /,aj)) badG=aj[1] # гостевая повреждена if(match($0,/^;4T .+ ([0-9]+):rNot /,aj)) rNot=aj[1] # гостевая пуста if(match($0,/^;4T .+ ([0-9]+):zipR /,aj)) zipR=aj[1] # гостевая с арховом } } } function rusDat(jj) { # 2019.19.25 -> 25.19.2019 split(jj,aq,".") return(aq[3]"."aq[2]"."aq[1]) } function cutR(jj) { # из литерала типа "rNot=80" split(jj,aq,":") # выделяет правую часть return(aq[2]) # типа "80" } function unpack(j1) { # восстановление литерала, свёрнутого при сборе сведений с СИ if (substr(j1,1,1)=="\"") j1=substr(j1,2,length(j1)-2) # откусим обрамляющие двойные кавычки j2="" # "•" -> пробел while(n=index(j1,"•")) { j2 = j2 substr( j1, 1, n-1 ) " "; j1 = substr( j1, n+1 ) } j1=j2 j1 j2="" # "”" -> двойные кавычки while(n=index(j1,"”")) { j2 = j2 substr( j1, 1, n-1 ) """; j1 = substr( j1, n+1 ) } j1=j2 j1 return( j1 ) } function unquot(j1) { # восстановление литерала "жанр(ы), свёрнутого при сборе сведений с СИ j2="" # '"' -> '"' while(n=index(j1,""")) { j2 = j2 substr( j1, 1, n-1 ) "\""; j1 = substr( j1, n+6 ) } j1=j2 j1 return( j1 ) } END{ # данные загружены и разобраны, оформляем рейтинг и приложения... if(ARGV[1]==""){ print "NO input file!" # защита от случайного пуска exit -1 } if(hold=="") { print "NO date to bind guesbooks (no ';m' in 1-st line)" exit -1 } if(hDat==-1)aVar["hDat"]=1 # дата aHits по СИ-шному if(donH==-1)aVar["donH"]=1 # дата "скачан" (aHits) if(hPag==-1)aVar["hPag"]=1 # страниц aHits if(nHit==-1)aVar["nHit"]=1 # точное число топовых разделов if(hitL==-1)aVar["hitL"]=1 # хиты замыкающего за "12мес" if(hMax==-1)aVar["hMax"]=1 # хиты раздела-лидера aHits if(nulG==-1)aVar["nulG"]=1 # гостевая недоступна if(badG==-1)aVar["badG"]=1 # гостевая повреждена if(rNot==-1)aVar["rNot"]=1 # гостевая пуста if(zipR==-1)aVar["zipR"]=1 # гостевая с арховом if(j0=length(aVar)){ tmp0="? no var(s):" for(j1 in aVar)tmp0=tmp0" "j1 print(tmp0" in "FILENAME) exit -1 } endS=mktime(substr(hold,1,4)" "substr(hold,6,2)" "substr(hold,9,2)" 00 00 00") # seconds "до" # подвязка позиций прошлого рейтинга, для отметок "сдвиг" (места) # hitT numP hitP sizT aNum rNum begD endD aDat "namA" "namT" id_P id_T votT jnrT gFil # $1 $2 $3 $4 $5 $6 $7 $8 $9 $10 $11 $12 $13 $14 $15 $16 # 6093 156 27017 1821.1 -291 291 2014.07.10 2017.11.30 2018.03.24 "Скс." "Режим•бога" s/sks 111 0 0 s~sks.111 tmp0=0 while ((getline line < fOld) > 0) { # fOld: like 2018.11.29.mText split(line,aj) # ;m hold 2019.12.02 первая строка if(!tmp0)dOld= substr(aj[3],3,2) substr(aj[3],6,2) substr(aj[3],9,2) #"191202" (ID старого рейтинга) else if(match(aj[1],/^[0-9]+$/)){ # это именно строка с хитами текста &Co a76[aj[12]]++ # старые авторы j0=aj[12]"/"aj[13] # полный ID старого текста a80[j0]=aj[4] # размер старого текста a84[j0]=aj[6] # реплик в гостевой старого текста # split(aj[4],aq,".") # объём 50.1 =ok, 50.0 =fake # if(aq[2]) a80[j0]=aq[1] # реальный объём старого текста # else a80[j0]=0 # вратый-с if(!a00[a02[j0]])a00[a02[j0]]=tmp0 # если этот текст неоптичен запомним, текст был здесь: } tmp0++ # старая позиция текста в старом списке } close(fOld) # всё/не_всё, - старый список тогось # while(hitL-a22[tMax]>0)tMax-- # реальное число строк (текстов) с хитами НЕ менее hitL print("tMax:"tMax) # siTopTexts - оформление заготовок строк (для основного рейтинга) split("", ordr) # очистим массив newN=0 for (jj=1;jj<=tMax;jj++){ # порядок строк (основной цикл построчной подготовки) ordr[jj]=jj # - как в источнике if(!a00[jj]){ # признак "новый текст в рейтинге" newN++ # и сосчитаем } if(!(a10[jj] in a76)){ # новый автор a77[jj]=" bgcolor="color[5] # новый автор a78[jj]=" (Новый)" if(!(a10[jj] in a79)){ # новый автор, первое вхождение a79[a10[jj]]++ # запомним этого нового автора nAv1++ # и сосчитаем его же-с } } # NN - место_в_рейтинге if(dEnd<a34[jj]){ a00[jj]=" bgcolor="color[2] # место - "фикция" (до нашего интервала) a02[jj]="Фикция" }else{ if(a00[jj]){ # место в старом рейтинге нашлось? j0=a00[jj]-a01[jj] if(!j0){ # нулевой сдвиг a00[jj]="" # default color - основной цвет строки a02[jj]="Сдвиг:0==" }else if(j0>0){ # "сдвиг" вверх "N-^" a00[jj]=" bgcolor="color[4] # "сдвиг" вверх "N-^" a02[jj]="Сдвиг:"j0"-^" nTx1++ # вверх }else{ # "сдвиг" вниз "M-v" j0=0-j0 a00[jj]=" bgcolor="color[3] # "сдвиг" вниз "M-v" a02[jj]="Сдвиг:"j0"-v" nTx3++ # вниз } }else{ # новое "NEW" - светло-желтый a02[jj]="Новое" # подсказка в этой ячейке a00[jj]=" bgcolor="color[5] # новое "NEW" nTx2++ # новинки } } # изменение размера текста if(a33[jj]){ # текст, sizB - "1"==объёмOk, "0"=="доступ ... ограничен" j0=a10[jj]"/"a20[jj] # id_P/id_T if(split(a80[j0],aq,".")==2){ # в старом рейтинге текст есть if(!aq[2])a80[j0]=0 # "0"=="доступ ... ограничен" (враньё-с) else a80[j0]=aq[1] # "1"==объёмOk j0=a32[jj]-a80[j0] if(!j0) a83[jj]="</a>" if(j0>0){ a81[jj]=" bgcolor="color[4] # стало больше a82[jj]="<a title=\"+"j0"k\">" # стало больше nSz1++ } if(j0<0){ # j0=-j0 a81[jj]=" bgcolor="color[3] # стало меньше a82[jj]="<a title=\""j0"k\">" # стало меньше nSz2++ } } } # Жанр(ы) split(a40[jj],aq,":") # разделим форму и жано(ы) if(aq[2]=="") aq[2]="--" # два дефиса подряд смотрятся красивше (jnrT;) a40[jj]="<b>"aq[1]"</b>: "aq[2] # Оценки текста (7.25*15) пляски с бубном... if(a50[jj]!=0){ split(a50[jj],aj,"*") j1=split(aj[1],az,"»") # az[1] - среднее, az[2] - SI баллы a50[jj]=az[1]"»<b>"az[2]"</b> *"aj[2] if(j1==1)j1=aj[1] else j1=az[1] a51[jj]=sprintf("%3.2f",(j1-5.5)*log(aj[2])) # уровень оценок if((a51[jj]+0)==0){ a51[jj]=0 # ни рыба, ни мясо a52[jj]="" }else if(a51[jj]<0){ a52[jj]=" bgcolor="color[3] # плохие nUs2++ # успех- }else{ a52[jj]=" bgcolor="color[4] # хорошие nUs1++ # успех+ } } # Отклик в гостевых if(substr(a62[jj],5,1)=="."){ # aDat (like 2018.07.18) гостевая НЕ пуста, считаем отклик j0=mktime(substr(a62[jj],1,4)" "substr(a62[jj],6,2)" "substr(a62[jj],9,2)" 00 00 00") # seconds "от" j0=(endS-j0+86400)/86400 # days - интервал в днях j1=a60[jj] if(j1<0)j1=a61[jj]+j1+1000 # nums - реплик в интервале else j1=a61[jj]-j1+1 a64[jj]=sprintf("%4.2f",j1/j0) # reac - реплик в сутки (для сортировки) a63[jj]=j1"/"j0 # сборка для вывода (Реплик в сутки (шт./дни)) if(a60[jj]>0)a64[jj]=a64[jj]"•" # архивов нет a65[jj]=0 # по умолчанию гостевая без цвета j0=a10[jj]"/"a20[jj] # id_P/id_T if(j0 in a84){ # этот текст был в старом рейтинге a65[jj]=(a84[j0]!=a61[jj]) # изменилось ли число реплик? if(a65[jj])rNew++ } } # выявим "свежак", влетевший в рейтинг менее чем за 30 дней a30 и "старьё" if(dEnd<a34[jj]){ # до нашего интервала a34[jj]=" bgcolor="color[3] # фикция т.е. ПОСЛЕ нашего интервала ficT++ # счётчик "фикция" }else if(dBeg<=a34[jj]){ # в нашем интервале до верхней границы a34[jj]=" bgcolor="color[4] curT++ }else if(oldD>a34[jj]){ # в нашем интервале до верхней границы a34[jj]=" bgcolor="color[11] oldT++ # счётчик "давно" }else a34[jj]="" } # собственно сборка файла с таблицами... if(500-tMax>=0)tGap=50 if(250-tMax>=0)tGap=25 mkPage() print("<blockquote>") >fOut print(info) >fOut # служебная отметка (для порядку) if(nHnY)for(jj=1;jj<=nHnY;jj++)print(aHnY[jj]) >fOut for(jj=1;jj<=nHdr;jj++)print(aHdr[jj]) >fOut for(jj=1;jj<=nHd1;jj++)print(aHd1[jj]) >fOut for(jj=1;jj<=nTb1;jj++)print(aTb1[jj]) >fOut for(jj=1;jj<=nTbl;jj++)print(aTbl[jj]) >fOut print(Ttl1) >fOut for(jj=1;jj<=nOut;jj++)print(aOut[jj]) >fOut print(info) >fOut # служебная отметка (для порядку) printf("</blockquote>") >fOut print("<blockquote>") >fPre print(inf2) >fPre if(nHnY)for(jj=1;jj<=nHnY;jj++)print(aHnY[jj]) >fPre for(jj=1;jj<=nHdr;jj++)print(aHdr[jj]) >fPre for(jj=1;jj<=nHd2;jj++)print(aHd2[jj]) >fPre for(jj=1;jj<=nTb2;jj++)print(aTb2[jj]) >fPre for(jj=1;jj<=nTbl;jj++)print(aTbl[jj]) >fPre print(Ttl2) >fPre for(jj=1;jj<=nOut;jj++)print(aOut[jj]) >fPre print(inf2) >fPre printf("</blockquote>") >fPre print "--- " strftime("%H:%M:%S") " Ends..." # закончили работу (оживляж;) # 2018.09.30, nvv creation # ... # 2020.05.09, nvv, +дополнения, + мелкая косметика # 2020.05.21, nvv, раскраска по "Размещено" - "намедни", "недавно" и "давно" # 2020.06.12, nvv, исправление замеченных неточностей + updates: # 2020.06.27, nvv, anchors "place" added (теперь можно сослаться извне на любое место рейтинга) # 2020.07.09, nvv, minor updates # = причёсана работа с датами границ потребных интервалов # = ведена поддержка "фикций" (хиты ДО размещения текста) # = немного обихожены даты и уточнено разграничение: "давно", "недавно", "фикция" # = немного изменена палитра раскраски ячеек # 2020.08.21, nvv, подготовка к отказу от козырного числа 1000 в названии рейтинга # вместо "siTop1000texts" стало "siTopTexts" # 2020.09.23, nvv, поддержка (ссылки на) предыдущего рейтинга # 2020.09.28, nvv, число текстов в списке определяется по границе выборки bStat: # ;2D =Вс= hitL:20223.630 <- т.е. 20223 разделов с хитами "12мес" НЕ ниже 630 # ergo -> в списке тексты с хитами "30дн." НЕ меньше 630. # 2020.10.14, nvv, к жанрам текста добавлена форма (роман/повесть/справочник/etc.) # + исправлена мелкая ошибка в алгоритме + добавлен спец.якорь "nvvA" ;) # 2020.10.31, nvv, мелкая косметика # 2020.11.05, nvv, добавлены якоря ancA на авторов # и на сами произведения в формате: "aChr~aNik:id_T" ("ancT") # 2020.11.09, nvv, добавлено отображение tNot числа текстов "для френдов" # (т.е. НЕ доступных "mNot" читателям) в списке # 2020.11.18, nvv, мелкая косметика # 2020.12.31, nvv, новогоднее поздравление... ;) # 2021.01.02, nvv, мелочёвка # 2021.01.09, nvv, мелочёвка # 2021.02.12, nvv, мелочёвка # 2021.03.20, nvv, мелочёвка # 2021.04.24, nvv, переделки задачи bStat влекут переделки сопряжения # 2021.05.10, nvv, теперь скрипт создаёт сразу и рейтинг (HTML) и копию в варианте "Предыдущий" # 2021.05.23, nvv, исправлена устаревшая ссылка на "Историю-Р" # 2021.06.09, nvv, мелкая косметика # 2021.09.03, nvv, мелкая неточность (строка "по факту" ненужна, если таковых нет) # 2021.11.22, nvv, разбиение на таблицы, макс число строк в одной (tGap) - зависит от общего оных числа # 2021.12.26, nvv, автоматическая вставка поздравления с новым годом # 2022.01.13, nvv, исправлена неточность в выявлении новогоднего периода # 2022.10.19, nvv, в шапку добавлена ссылка на текст: "Регистрация в СИ"" # 2022.12.01, nvv, текст: "Регистрация в СИ" перестал быть New # 2023.06.24, nvv, добавлена поддержка aad2 произведений из скрытых разделов # 2023.07.29, nvv, мелкая косметика # 2023.11.01, nvv, "(+)"==отмечаются цветом гостевые с изменившимся числом реплик "свежее" # 2023.11.30, nvv, снято извещение о: отмечаются цветом гостевые с изменившимся числом реплик # 2024.02.07, nvv, добавлена отметка "Upd" для обновлённой истории в шапке рейтинга # 2024.03.04, nvv, удалена отметка "Upd" для обновлённой истории в шапке рейтинга # 2024.03.09, nvv, изменился рисунок работы СИ - изменено оформление NB. в шапке # 2024.02.07, nvv, добавлена отметка "Upd" для: "Исходные тексты скриптов" # 2024.08.19, nvv, """ -> "·" }
Имя файла скрипта: "fHtml.cmd" V-текст скрипта-V- - - - - - - - - @if not defined nJob @echo off echo %date% %time:~0,8% %~nx0 Begs :: fHtml.cmd - оформление в HTML списка топовых текстов последних 30 дней :: + 20??.??.??.dText (like 2018.12.30.dText) - оформляемый последний список :: + 20??.??.??.dText (like 2018.11.29.dText) - опорный ПРЕД последний список :: проверить-найти: :: - свежий *.dText, например: 2021.04.27.dText :: - старый *.dText, например: 2021.04.24.dText :: - свежий *.dText, например: 2021.04.27.dText.html :: - старый *.dText, например: 2021.04.24.z.dText.html :: 2018.11.26, nvv, creation :: ... :: 2019.03.06, nvv, оформляемый месяц можно задать ЯВНО (вместо дефолтного) :: 2019.07.31, nvv, мелкая косметика... :: 2019.11.29, nvv, переменная nJob блокирует пилотную команду @echo off :: 2019.12.06, nvv, current unification :: 2020.03.21, nvv, some updates :: 2021.05.29, nvv, очередная оптимизация с унификацией... :: 2021.06.13, nvv, confirmation to move PREV data off :: 2023.06.24, nvv, hidden authors debugging see: rem goto mkHtm set nJob=fHtml if NOT defined jDat set jDat=%date% set ok2upDt=%1 set aHtm=%~dp0%nJob%.awk :: wDir - общее рабочее место set wDir=%~d0\Jobs :: sDir - общее складское хранилище set sDir=%~d0\Stor :: dDir - склад для уже ненужных списков 20??.??.??.dText set dDir=%sDir%\Text\zOld.dTexts if NOT exist %dDir% set errInf=NO %dDir% found & goto nExit :: hDir - склад под выходные файлы с таблицами *.html set hDir=%sDir%\Html set pDir=%hDir%\dTexts if NOT exist %hDir%\ mkDir %hDir% if errorLevel 1 set errInf=fail mkDir %hDir% & goto nExit :: fOld - прошлый опорный список для "siTopTexts" set fOld= :: fCur - свежий список для "siTopTexts" - 1k популярных текстов (со всеми атрибутами) set fCur= for %%A in (%wDir%\20??.??.??.dText) do call :findCurOld %%A if NOT defined fOld set errInf=!? NO old 20*.dText found & goto nExit if defined errInf goto nExit set fHtm=%hDir%\%dCur%.dText.html echo prev:%fOld% echo curr:%fCur% echo fHtm:%fHtm% if NOT exist %fHtm% goto mkHtm :: итоговый файл есть. если нужно прибрать - идём прибирать, иначе выясняем... if defined ok2upDt goto upDt :: запрос (конечный HTML уже есть!) set tmp0= rem goto mkHtm echo fHtm found; reBuild it? [yes] == y set /p tmp0=?[no]? if /i NOT %tmp0%. == y. ( echo job canceled {NO to reBuild} exit ) :mkHtm собственно оформлялка ("от и до";) gawk.exe -f %aHtm% %fCur% if errorLevel 1 set errInf=!!! X someThing's wrong with %~n0.awk & goto nExit :: блокируется оптичивание преобразованного в HTML goto nExit :upDt запрос (точно ненада?) set tmp0= echo confirm PREV data OFF? [yes] == y set /p tmp0=?[no]? if /i NOT %tmp0%. == y. ( echo job canceled {NO to reBuild} exit ) :: уберём уже ненужный старый список рейтинга на склад Text\zOld.dTexts if exist %fOld% ( echo move %fOld% to %dDir% move /Y %fOld% %dDir% if errorLevel 1 set errInf=!! fail to move old *.dText to %dDir% & goto nExit ) :: уберём опубликованное (в HTML) set tmp0=%hDir%\%dCur%.dText.html if exist %tmp0% ( echo move %tmp0% to %pDir% move /Y %tmp0% %pDir% if errorLevel 1 set errInf=!! fail to move %tmp0% to %pDir% & goto nExit ) :: убьём опубликованное "предыдущее" (в HTML) set tmp0=%hDir%\%dOld%.dText.z.html if exist %tmp0% ( echo erase %tmp0% erase %tmp0% if errorLevel 1 set errInf=!! fail to erase %tmp0% & goto nExit ) :nExit if defined errInf ( echo ! %errInf% set errInf= ) echo %date% %time:~0,8% Job:%nJob% Ends goto :eof :findCurOld :: dOld dCur - даты в именах файлов опорного и текущего списков if defined fOld if defined fCur set errInf=too many *.dText files in %wDir% & goto :eof set fOld=%fCur% set dOld=%dCur% set fCur=%1 set dCur=%~n1 goto :eof
Имя файла скрипта: "gAuth.cmd" V-текст скрипта-V- - - - - - - - - @if not defined pMod @echo off set nJob=gAuth echo %date% %time:~0,8% %nJob% Begs :: gAuth.cmd - построение диф-списка (изменение хитов "12мес") за цикл обновления статистик :: в _siTop.# ищутся два последних aHits, выявляются даты их расчётов (и интервал в днях;) :: вычисляется среднесуточная посещаемость разделов (за последний интервал, по умочанию - 3 дня) :: последовательность сборки рейтинга siTopAuthors "Авторы": :: 2024.08.13, nvv, вместо вопроса или работа, или выход по "уже есть" :: ! прочая история в подвале :: порядок запросов при сборке списка годного: :: 1 ищется годная пара aHits для расчёта :: 2 по этой паре строим список авторов с успехом не меньше 10-и и скачиваем их статистики :: 3 по этим статистикам выявляются самые популярные тексты с успехом не менее 20-и :: 4 у таких авторов проверяютмя их титулы и сами тексты-кандидаты в рейтинг :: 5 годные собираются в свежий список gAuth :: основные сеты и прочая подготовка к работе... set jDat=%date% set nJob=gAuth :: siUrl - URL Самиздата (будКлуб - глупость -- НЕ факт-с;) if NOT defined siUrl if exist \siUrl.budclub set siUrl=budclub.ru if NOT defined siUrl set siUrl=samlib.ru :: dLjb - общий счётчик /формально/ успешно скачанного (НЕ 0b) set dLjb=0 :: ratW - темп скачивания (секунд на один файл в среднем) rem set ratW=0 :: minL - минимальная удача раздела (число посетителей в сутки)*10 - граница отбора для последующей обработки set minL=100 set errInf= :: awkH - скрипт сравнения двух последних списков fHits set awkH=%~p0%nJob%H.awk :: awkI - скрипт разбора титула раздела (объём, обновлялось и проч.) set awkI=%~p0%nJob%I.awk :: awkS - скрипт поиска текста-лидера в статистике раздела set awkS=%~p0%nJob%S.awk :: awk_ - скрипт поиска текста-лидера в статистике раздела set awk_=%~p0%nJob%_.awk :: awkT - скрипт разбора и обустройства текста СИ set awkT=%~p0dText.awk :: - проверить комплектность AWK for %%A in ( %awkH% %awkI% %awkS% %awkT% %awk_% ) do if NOT exist %%A ( set errInf=NO %%A & goto errExit ) :: wGetSiz - размер скачанного файла (default 1b минимум) set wGetSiz=1 :: wDir - общее рабочее место set wDir=\Jobs :: sDir - общее складское хранилище set sDir=\Stor :: jDir - место для оперативных файлов set jDir=%wDir%\#%nJob% if NOT exist %jDir%\ mkDir %jDir% if errorLevel 1 ( set errInf=fail mkDir %jDir% & goto errExit ) :: jBad - список проблемных файлов процесса set jBad=%jDir%\]%nJob%.bad :: jRpt - общий сводный отчёт с итоговыми сводками процессов set jRpt=%wDir%\_siTop.# :: xDir - складское хранилище справочников рассчётов и окрестностей... set xDir=%sDir%\wOld :: zDir - общий подкаталог для посуточных подкаталогов с итоговыми списками set zDir=%xDir%\%jDat% if NOT exist %zDir%\ mkDir %zDir% if errorLevel 1 ( set errInf=fail mkDir %zDir% & goto errExit ) :: datJ - верхняя дата обсчитываемого интервала /с 2024.02.23 это "ВЧЕРА"/ вычислим... for /F %%A in ( ' gawk.exe "BEGIN{print(strftime(\"%%Y.%%m.%%d\",systime()-86400));exit}" ' ) do set datJ=%%A :: gTop - итоговый список; если нет - начнём /спросив/ или продолжим работу /если что-то уже есть/ set gTop= for %%A in (%wDir%\%datJ%.*.gAuth) do set gTop=%%A :: если свежего gAuth нет, можно сразу начинать, иначе запрос на повторение всего с нуля if NOT defined gTop goto chkCur echo == all is done today already goto :eof :chkCur 0-й шаг: надо к последнему aHits выбрать опорный для вычисления прироста хитов в интервале :: - 1-й шаг: ищется сортированый по посещаемости список разделов /есть == есть интервал, нет - смотрим расклад/ set /a step+=1 set itog=%jDir%\%datJ%.??.gAuthH call :lookFor %itog% if NOT defined found goto chk1st for %%A in (%found%) do set gapD=%%~xA set gapD=%gapD:~1% goto gAuthH_done :chk1st echo ? check dates and so on... set modG=0 rem for /F "tokens=*" %%A in (' gAwk.exe -f %awkH% ') do echo %%A rem echo gDif.%gDif% gapD.%gapD% itog.%itog% found.%found% for /F "tokens=*" %%A in (' gAwk.exe -f %awkH% ') do call :echoH %%A set itog=%gDif% set j2do=gAuthH :mkReq п/п: ЗАПРОС на действие /%j2do%/ + ВЫЗОВ оного + ПРОВЕРКА итога /%itog%/ + ПЕРЕХОД дальше + ОЖИВЛЯЖ echo. -%step%- HAVE to make: %j2do% set tmp0= echo ?ok to goOn [yes] == y :: !!! goto reqOk rem if NOT %step% == 1 if NOT defined errInf goto reqOk rem if %step% == 5 if NOT defined errInf goto reqOk set /p tmp0=?[no]? :: "y/Y" - "да" - идём делать упомянутое, иначе - досвидания if /i NOT "%tmp0%" == "y" set errInf=job canceled & goto errExit :reqOk call :make_%j2do% if defined errInf echo %errInf% & goto :eof if NOT exist %itog% set errInf=! fail make %itog% & goto errExit :: !!! if NOT defined errF if %step% GTR 4 start D:\MEW11\Mew32.exe %itog% goto %j2do%_done :gAuthH_done gapD - текущий интервал "намедни", ergo можно указать имена всеъ потребных списков set /a step+=1 rem set gapD=%found:~11% set gDif=%jDir%\%datJ%.%gapD%.gAuthH set gSta=%jDir%\%datJ%.%gapD%.gAuthS set gInd=%jDir%\%datJ%.%gapD%.gAuthI set gTxt=%jDir%\%datJ%.%gapD%.gAuthT set gTop=%wDir%\%datJ%.%gapD%.gAuth set gNum= for /F "tokens=1,*" %%A in ( ' gawk.exe "END{match($0,/^;5G .+ ([0-9]+):gNum /,a);print(a[1])}" %gDif% ' ) do set gNum=%%A if NOT defined gNum set errInf=! NO gNum in %gDif% & goto errExit :: - 2-й шаг: сборка статистик разделов 100+ составление списка текстов 200+ set itog=%gSta% call :lookFor %itog% if defined found goto gAuthS_done set j2do=gAuthS goto mkReq :gAuthS_done - 3-й шаг: сборка титулов подходячих разделов составление списка недастающих атрибутов разделов set /a step+=1 set nTxL= for /F "tokens=1,*" %%A in ( ' gawk.exe "END{match($0,/^;5H .+ ([0-9]+):nTxL /,a);print(a[1])}" %gSta% ' ) do set nTxL=%%A if NOT defined nTxL set errInf=! NO nTxL in %gSta% & goto errExit set itog=%gInd% call :lookFor %itog% if defined found goto gAuthI_done set j2do=gAuthI goto mkReq :gAuthI_done - 4-й шаг: сборка текстов 200+ составление списка раздел-текст set /a step+=1 set nTit= for /F "tokens=1,*" %%A in ( ' gawk.exe "END{match($0,/^;5I .+ ([0-9]+):nTit /,a);print(a[1])}" %gInd% ' ) do set nTit=%%A if NOT defined nTit set errInf=! NO nTit in %gSta% & goto errExit set itog=%gTxt% call :lookFor %gTxt% if defined found goto gAuthT_done set j2do=gAuthT goto mkReq :gAuthT_done все рабочие списки есть, смотрим/собираем итоговый... set /a step+=1 set itog=%gTop% call :lookFor %gTop% :: ЕСЛИ всё УЖЕ сделано - досвидание if defined found set errInf=== OK, all is done, ITOG: %gTop% & goto errExit set j2do=gAuth goto mkReq :gAuth_done goto :eof :: потребные для работы п/п :lookFor %1 == %itog% - смотрим - есть ли такой файл \с маской\ set found= for %%J in ( %itog% ) do if exist %%J (set found=%%~nJ&set tmp0=%%J) if defined found ( echo = ok: %tmp0% ) else ( echo x NO: %itog% ) goto :eof :make_gAuthH сборка списка *.gAuthH /самые посещаемые разделы по разнице хитов 100+ в aHits/ echo ? make *gAuthH list... :: чистим рабочий каталог от уже устаревших файлов if exist %jDir%\*.* erase /Q/F %jDir%\*.* if errorLevel 1 echo ! fail erase %jDir%\*.* & goto :eof set modG=1 gAwk.exe -f %awkH% goto :eof :make_gAuthS сборка списка *.gAuthS /докомплектация и обработка статистик 100-200+/ echo checkGet %gNum% stats :: взведём таймер со компанией call :setTimer %gNum% :: сборка комплекта нужных статистик for /F %%J in ( ' gawk.exe "{if(match($0,/^ *([0-9]+):.+:([^ !:]+):/,a)&&(100-a[1]<=0)){print(a[2])}else{exit}}" %gDif% ' ) do ( call :chkGet %%J /stat.shtml stat %jDir% if defined errInf goto :eof ) rem остановим "таймер" качалки время работы в секундах for /F %%J in ('gawk.exe "BEGIN{print(strftime(\"%%M:%%S\",systime()-%ratW%,-1));exit}"') do set ratW=%%J echo. echo. == %gNum% %ratW% ? make *gAuthS list... :: построение списка *gAuthS gAwk.exe -f %awkS% %jDir%\*.stat.htm goto :eof :make_gAuthI сборка списка *.gAuthI /комплектация и обработка Титулов разделов 200+/ echo checkGet %nTxL% Titles :: взведём таймер со компанией call :setTimer %nTxL% :: сборка комплекта нужных титулов for /F "tokens=*" %%J in ( ' gawk.exe "{if(match($0,/:!:([^ !:]+):!:./,a))print(a[1])}" %gSta% ' ) do ( call :chkGet %%J / titl %jDir% if defined errInf goto :eof ) rem остановим "таймер" качалки время работы в секундах for /F %%J in ('gawk.exe "BEGIN{print(strftime(\"%%M:%%S\",systime()-%ratW%,-1));exit}"') do set ratW=%%J echo. echo. == %nTxL% %ratW% ? make *gAuthI list... :: построение списка *gAuthI gAwk.exe -f %awkI% %jDir%\*.titl.htm goto :eof :make_gAuthT сборка списка *.gAuthT //докомплектация текстов 200+/ echo checkGet %nTit% Texts :: вычленим актуальный путь в складу текстов "к расчёту" (like: U:\Stor\Text\2020.11.18.text\) rem ;2D =Ср= 998:tNum OkV:99.8% mod:v 2022.04.09:dEnd 0:sNul 2022.04.13:done 11:14 00:16:09~wrks 0~ratW 0:dnLd set tDir=%sDir%\Text\%jDat%.text if NOT exist %tDir% mkDir %tDir% if errorLevel 1 ( set errInf=fail mkDir %tDir% & goto errExit ) :: tmpF времянка для текстов set tmpF=%jDir%\tmp.text.html :: tmpL пустая времянка для списка set tmpL=%jDir%\tmp.text.lst echo. >nul 2> %tmpL% :: взведём таймер со компанией call :setTimer %nTit% :: сборка комплекта нужных титулов for /F "tokens=1,2*" %%J in ( ' gawk.exe "{if(match($0,/:!:([^ !:]+):!:([^ !:]+) ./,a))print(a[1],a[2])}" %gInd% ' ) do ( call :chkGet %%J /%%K.shtml text %tDir% %%K if defined errInf goto :eof ) rem остановим "таймер" качалки время работы в секундах for /F %%J in ('gawk.exe "BEGIN{print(strftime(\"%%M:%%S\",systime()-%ratW%,-1));exit}"') do set ratW=%%J echo. echo. == %nTit% %ratW% ? make *gAuthT list... for /F "tokens=1,2*" %%J in ( ' gawk.exe "{if(match($1,/^20[\.0-9]{8}/)){n++}else{if($1==\"]\")e++}}END{print(n,0+e)}" %tmpL% ' ) do ( set nTxt=%%J set nErr=%%K ) echo ; begD endD sizT.Ok "namA" "namT" "votT" "jnrT" fNam fTmp >> %tmpL% gawk.exe "{if(match($1,/^;[0-9][^ ]/,a))print($0)}" %gInd% >> %tmpL% echo ;5T txtL %datJ%:datJ %gapD%:gapD %nTxt%:nTxt %nErr%:nErr %jDat%:done at~%time:~0,5% >> %tmpL% move /y %tmpL% %gTxt% if errorLevel 1 set errInf=! fail move %tmpL% %gTxt% & goto gAuth_err echo. == %nTxt%:nTxt %nErr%:nTxt goto :eof :make_gAuth сборка списка *.gAuth /итоговый: "всё в одном"/ for /F "tokens=*" %%A in ( ' gawk.exe -f %awk_% ' ) do call :mkRpt %%A if NOT defined errInf echo == OK all is done, itog: %gTop% goto :eof :mkRpt if %1 == ] set errInf=fail %awk_% & goto :eof echo ;5Q gapQ %* %jDat%:done echo ;5Q gapQ %* %jDat%:done >> %gTop% echo ;5Q gapQ %* %jDat%:done >> %jRpt% copy /b /y %gTop% %zDir% >nul if errorLevel 1 set errInf=fail copy %gTop% 2 %xDir% goto :eof :setTimer cNum set cNum=%1 set /a jMax=%cNum%/100 if NOT %cNum:~-2% == 00 set jMax=%jMax%+ set jMax=%jMax% . set jMax=%jMax:~0,4% set cNum=0 for /F %%J in ('gawk.exe "BEGIN{print(systime());exit}"') do set ratW=%%J :: dnLd - счётчик /формально/ успешно скачанного (НЕ 0b) set dnLd=0 goto :eof rem id_P.1 2 3 4 rem call :chkGet %%A /stat.shtml stat %jDir% rem call :chkGet %%A /%%B.shtml text %tDir% %%B :chkGet id_W wSuf set /a cNum+=1 set id_P=%1 :: если ненужен - просто "/" без кавычек /скачивание титулов разделов/ set wSuf=%2 set fSuf=%3 set outD=%4 set outT=%5 set id_F=%id_P:~0,1%~%id_P:~2% if defined outT set id_F=%id_F%.%outT% :: имя локального файла из authID (d/dront -> d~dront) set fSuf=%id_F%.%fSuf%.htm if defined outT set fSuf=%fSuf%l set wFil=%outD%\%fSuf% set /a count+=1 :: возможно уже есть? set mark=. set mrk1=: if exist %wFil% goto show :: нет, нужно скачивать... set mark=~ set mrk1=! set wUrl=%siUrl%/%id_P%%wSuf% set gFil=%wFil% if NOT defined outT goto chk_Get set gFil=%tmpF% if exist %tmpF% erase %tmpF% if errorLevel 1 set errInf=fail erase %tmpF% & goto :eof :chk_Get call wGetUrl2fil.cmd %wUrl% %gFil% if %wGetErr% == 0 goto show :: проблема? if %wGetErr% == 1 ( if exist %gFil% erase %gFil% echo ] nulFil %wUrl% >> %jBad% set /a nulP+=1 set errInf= goto :eof ) :: если титул раздела недоступен... set errInf=no web{SI} {%wUrl%} goto :eof :show оживляж + конкретная доп обработка текстов /чистка+дата_изменения/ if %cNum:~-1% == 0 set mark=%mrk1% gawk.exe "BEGIN{printf(\"%mark%\");exit}" set tmp0= %cNum% set tmp0=%tmp0:~-5,3%.%jMax% if "%cNum:~-2%" == "00" ( gawk.exe "BEGIN{printf(\" %%s\",\"%tmp0%\"strftime(\"%%M:%%S\",systime()-%ratW%,-1));exit}" echo. ) :: если это НЕ текст - всё if NOT defined outT goto :eof :: если текста у нас /и должного вида/ НЕТ нужно его причесать, иначе - лишь взять его атрибуты if exist %wFil% goto readTxt set fOut=%wFil% gawk.exe -f %awkT% %gFil% > nul if NOT exist %wFil% ( echo bad %wUrl% >> %jDir%\%datJ%.%gapD%.gAuthT.err goto :eof ) :: для свежескачанного надоть дату конечного результата вструмить... for /F "tokens=1,2,*" %%J in (' gawk.exe -f %awkT% %wFil% ') do set touc=%%K touch.exe -t %touc:~0,4%%touc:~5,2%%touc:~8,2%0100 %wFil% if NOT %errorLevel% == 0 set errInf=fail touch %touc% with %wFil% & goto :eof :: 0 1 2 3 :: 2014.07.10 2017.11.30 1821.1 "Скс." "Режим•бога" 0 "<a•href=/type/index_type_1-1.shtml>Роман</a>:" s~sks.111.text :readTxt set fOut= gawk.exe -f %awkT% %wFil% >> %tmpL% goto :eof :: 2024.03.04..07-dates 3:gapD 441:gNum \Stor\wOld\2024.03.04\2024.03.03.aHits \Stor\wOld\2024.03.07\2024.03.07.aHits :echoH разбор выдачи %awkH% set gapD=%1 set gNum=%2 set nErr=%3 set gDif=%4 set found=%~n4 if NOT "%1" == "]" if NOT "%1" == "gAuthH" goto :eof echo %* :: ! проблема - досвидания! if "%1" == "]" ( set errInf=%* & goto errExit ) goto :eof :errExit реакция на проблему: в пакете - выход if defined pMod goto :eof :: автономно - на экран + прекращение работы echo %errInf% exit :: 2020.11.04, nvv, creation :: 2020.11.13, nvv, будКлуб - глупость :: 2020.11.28, nvv, процесс делает вроде-бы всё нужное, хить и с заглушками ;(!!! без сети)... :: 2021.01.15, nvv, всё работает +несколько лидеров в разделе учитываются без фиксации :: +текст с "ограниченным доступом" в разделе => раздел исключён из списка :: 2021.02.02, nvv, minor turning :: 2021.02.12, nvv, minor turning (gNum) :: 2021.03.15, nvv, minor turning (gNum) :: 2021.03.26, nvv, minor turning (tmpF) :: 2021.04.09, nvv, *.bStat turned to *.lst.bStat :: 2021.05.11, nvv, очередная оптимизация с унификацией... :: 2021.06.02, nvv, minor turnings {job's timing added - ratW & wrks) :: 2021.10.11, nvv, minor turnings {в пакетном режкме на экране выбранные aHits} :: 2021.11.20, nvv, ещё одно улучшение оживляжа-с ;) :: 2021.12.10, nvv, ещё одно улучшение оживляжа-с ;) :: 2022.01.01, nvv, ещё одно улучшение оживляжа-с ;) :: 2022.01.19, nvv, исправлена неточность в выдачи ошибки в работе gAuthH.awk :: 2022.02.26, nvv, исправлена неточность в выдаче объёмов раздела/произведения (1.1Gb и 17 Mb однако...) :: 2022.03.04, nvv, изменена реакция на проблемы с aHits - теперь просто выход с уведомлением :: 2022.03.31, nvv, времянка minL из-за силных пертурбаций учёта в марте :: 2022.04.17, nvv, радикально переделано: унифицировано и оптимизировано :: 2022.06.24, nvv, исправлена неточность контроля успеха чистки скачанного текста :: 2022.08.03, nvv, if datJ == ПОСЛЕДНИЙ день месяца, then свежий aHits - со СКАЧКОМ /непригоден для/ :: 2022.08.19, nvv, отключены промежуточные: запросы на продолжение работы и выдача результатов в MEW :: 2023.01.21, nvv, сменил разрешение экрана /меньше пикселей/, пришлось слегка менять оживляж :: 2024.03.08, nvv, новый рисунок работы СИ: ежедневное полное обновление статистик в т.ч. aHits :: 2024.03.21, nvv, исправлена процедура пестарта после падения ОС :: соответственно привязка теперь только к aHits безотносительно ситуации с bStat.
Имя файла скрипта: "gAuth_.awk" V-текст скрипта-V- - - - - - - - - BEGIN{ # gAuth.awk сборка итогового списка для siTopAuthors # 2022.04.13, nvv, creation # 2023.07.28, nvv, rearrange inpChk & outPut # 2024.09.08, nvv, место под sizK увеличено до 99Gb (8+1 знако-место) # + 6+1 под sizN # test=1 bRd=":!:" # разделитель блоков в строке tIni=systime() for(str2 in ENVIRON){ # ! регистр букв в имени переменной может быть любой str1=tolower(str2) # Temp и temp - РАЗНЫЕ имена для gAwk... if(str1=="gsta") gSta=ENVIRON[str2] # исходный список if(str1=="gind") gInd=ENVIRON[str2] # исходный список if(str1=="gtxt") gTxt=ENVIRON[str2] # исходный список if(str1=="gtop") fOut=ENVIRON[str2] # исходный список } if(gSta==""){ if(test){ jj="2023.07.25.3" gSta="\\Jobs\\#gAuth\\"jj".gAuthS" gInd="\\Jobs\\#gAuth\\"jj".gAuthI" gTxt="\\Jobs\\#gAuth\\"jj".gAuthT" fOut=jj".gAuth" }else{ errS="] no envVar 'gSta'" exit } } # формат списка gSta, нужное: id_P txtL txtG id_T hitP numP new # 277 0 277 0 58367 29 1159 3 :!:k/kadawr:!:n "Псион":!:"Кадавр" "no•comments" # ;txtL txtG.2 Luck new.4 hitP numP.6 sizK sizN.8 ! id_P ! id_T.10 "namT" ! "namP".12 "moto" # <- - - - - - - block.1 - - - - - - - - - - -> block.2 <- block.3 -> <- block.4 -> if(test)printf("load gAuthS ... ") while((getline line<gSta)>0){ jj=split(line,aj,bRd) if(jj==4){ # строка раздела id_P=aj[2] # его ID aStH[id_P]=aj[1] # txtL txtG Luck new hitP numP sizK sizN aStT[id_P]=aj[3] # id_T "namT" aStP[id_P]=aj[4] # "namP" "moto" nSta++ # счётчик разделов-кандидатов в рейтинг } } close(gSta) if(test)print("nSta:"nSta) # формат списка gInd, нужное: id_P datP sizK sizN "namP" "moto" # 2021.09.22 1159 3:!:k/kadawr:!:n "Псион":!:"Кадавр" "no•comments" # ; datP sizK sizN ! id_P ! id_T "namT" ! "namP" "moto" if(test)printf("load gAuthI ... ") while((getline line<gInd)>0){ jj=split(line,aj,bRd) if(jj==4){ # строка раздела id_P=aj[2] # его ID aInH[id_P]=aj[1] # datP sizK sizN aInT[id_P]=aj[3] # id_T "namT" aInP[id_P]=aj[4] # "namP" "moto" nInd++ # счётчик разделов-кандидатов в рейтинг # }else{ # строка подвала # if(match(aj[1],/^;[0-9]/))aEnd[++nEnd]=line # прикопаем... } } close(gInd) if(test)print("nInd:"nInd) # формат списка gTxt, нужное: id_P id_T sizT endD "namT" "jnrT" # 2014.07.10 2017.11.30 1821.1 "Скс." "Режим•бога" 0 "<a•href=/type/index_type_1-1.shtml>Роман</a>:" s~sks.111.text # ; begD.1 endD.2 sizT.Ok "namA".4 "namT" "votT".6 "jnrT" fNam.8 fTmp if(test)printf("load gAuthT ... ") while((getline line<gTxt)>0){ split(line,aj) if(match(aj[1],/^[0-9\.]{10}$/)){ # строка текста раздела split(aj[8],ak,".") id_P=substr(ak[1],1,1)"/"substr(ak[1],3) # его ID if(match(aj[3],/^[0-9]+.1$/)){ # нам недоступные тексты неинтересны aTxt[id_P]=line # begD endD sizT.Ok "namA" "namT" "votT" "jnrT" fNam fTmp aTxI[id_P]=ak[2] # id_T aTxF[id_P]=aj[8] # id_F nTxt++ # счётчик разделов-кандидатов в рейтинг } }else{ # блок в подвале # ;1aPre hits 5:xNam 451:xNum 104684:xPas 2023.07.20:hDat 522207:hMax 1052:hPag 12:add2 388:h30k 1058:dnLd 0.08~ratW 2023.07.22:done 01:19:32~wrks 15:03 # ;1aCur hits 5:xNam 451:xNum 104693:xPas 2023.07.23:hDat 525898:hMax 1052:hPag 1250:add2 390:h30k 1076:dnLd 0.18~ratW 2023.07.25:done 04:22:17~wrks 15:03 # ;5G gapP 2023.07.22:datJ 3:gapD 1646:gNum 0:nErr 100:minL 1248:newH 2023.07.25:done at~15:43 # ;5H txL1 2023.07.22:datJ 3:gapD 122:nTxL 0:nErr 200:minT 0:txtD 2023.07.25:done at~15:55 # ;5I titl 2023.07.22:datJ 3:gapD 122:nTit 0:nErr 2023.07.25:done at~15:57 # ;5T txtL 2023.07.22:datJ 3:gapD 122:nTxt 0:nErr 2023.07.25:done at~15:57 if(match(aj[1],/^;[0-9][^ ]/))aEnd[++nEnd]=line # прикопаем... # соберём данные для отчёта if (match(line,/^;1aPre .+ ([0-9\.]+):hDat /,aj)){ dat1=aj[1] }else if(match(line,/^;1aCur .+ ([0-9\.]+):hDat /,aj)){ dat2=aj[1] }else if(match(line,/^;5G .+ ([0-9]+):gNum ([0-9]+):nErr .+ ([0-9]+):newH /,aj)){ gNum=aj[1] nErr=aj[2] newH=aj[3] }else if(match(line,/^;5H .+ ([0-9]+):nTxL ([0-9]+):nErr /,aj)){ nTxL=aj[1] nErr=nErr+aj[2] }else if(match(line,/^;5I .+ ([0-9]+):nTit ([0-9]+):nErr /,aj)){ nTit=aj[1] nErr=nErr+aj[2] }else if(match(line,/^;5T .+ ([0-9]+):nTxt ([0-9]+):nErr /,aj)){ nTxt=aj[1] nErr=nErr+aj[2] } } } close(gTxt) if(test)print("nTxt:"nTxt) if(nSta*nInd*nTxt==0){ print("] empty or bad any of above!") exit } # gHit: id_P hitP numP new # gSta: id_P txtL txtG id_T hitP numP new # gInd: id_P datP sizK sizN "namP" "moto" # gTxt: id_P id_T sizT endD "namT" "jnrT" # gSta: aStH[id_P] # txtL txtG Luck new hitP numP sizK sizN # gInd: aInH[id_P] # datP sizK sizN # gInd: aInP[id_P] # "namP" "moto" # gTxt: aTxt[id_P] # begD endD sizT.Ok "namA" "namT" "votT" "jnrT" fNam fTmp for(id_P in aTxt){ split(aStH[id_P],aS1) # txtL txtG.2 Luck new.4 hitP numP.6 sizK sizN split(aInH[id_P],aI1) # datP sizK.2 sizN split(aInP[id_P],aI2) # "namP" "moto".2 split(aTxt[id_P],aT1) # begD endD.2 sizT.Ok "namA".4 "namT" "votT".6 "jnrT" fNam fTmp aOut[++nOut]=sprintf("%5s %2s",aS1[1],aS1[2]) bRd # sort key aOut[nOut]=aOut[nOut] sprintf("%6s ",aS1[3]) # Luck aOut[nOut]=aOut[nOut] sprintf("%1s ",aS1[4]) # new aOut[nOut]=aOut[nOut] sprintf("%7s ",aS1[5]) # hitP aOut[nOut]=aOut[nOut] sprintf("%6s ",aS1[6]) # numP aOut[nOut]=aOut[nOut] sprintf("%8s ",aI1[2]) # sizK aOut[nOut]=aOut[nOut] sprintf("%6s ",aI1[3]) # sizN aOut[nOut]=aOut[nOut] sprintf("%5s ",aS1[1]) # txtL aOut[nOut]=aOut[nOut] sprintf("%2s ",aS1[2]) # txtG aOut[nOut]=aOut[nOut] sprintf("%7s ",aT1[3]) # sizT aOut[nOut]=aOut[nOut] sprintf( "%s ",aI1[1]) # datP aOut[nOut]=aOut[nOut] sprintf( "%s ",aT1[2]) # endD aOut[nOut]=aOut[nOut] sprintf( "%s ",id_P ) # id_P aOut[nOut]=aOut[nOut] sprintf( "%s ",aI2[1]) # "namP" aOut[nOut]=aOut[nOut] sprintf( "%s ",aI2[2]) # "moto" aOut[nOut]=aOut[nOut] sprintf( "%s ",aTxI[id_P]) # id_T aOut[nOut]=aOut[nOut] sprintf( "%s ",aT1[5]) # "namT" aOut[nOut]=aOut[nOut] sprintf( "%s ",aT1[7]) # "jnrT" aOut[nOut]=aOut[nOut] sprintf( "%s ",aTxF[id_P]) # id_F } # старый фомат конечного списка gAuth # 470 0 13756 139 3848 9 475 1 1821.1 2019.06.23 2017.11.30 s/sks "Скс" "Режим•бога" 111 "Режим•бога" "<a•href=/type/index_type_1-1.shtml>Роман</a>:" s~sks # :Luck new hitP numP sizK sizN hitT txtN sizT datP endD id_P "namP" "moto" id_T "namT" "jnrT" fNam # %%7s %%2s %%8s %%7s %%8s %%6s %%6s %%3s %%8s # :formItA %luck% %typH% %hitP% %numP% %sizK% %sizN% %hitT% %txtN% %sizT% # gawk.exe "BEGIN{printf(\"%%7s%%2s%%8s%%7s%%8s%%6s%%6s%%3s%%8s\",%1,%2,%3,%4,%5,%6,%7,%8,%9);exit}" >> %jLst% # echo. %datP% %endD% %id_P% %namP% %moto% %id_T% %namT% %jnrT% %fNam% >> %jLst% asort(aOut) for(jj=nOut;jj>0;jj--){ split(aOut[jj],aj,bRd) print(aj[2]) >fOut } print(\ ";Luck.1 new hitP.3 numP sizK.5 sizN txtL.7 txtG sizT.Ok.9 datP endD.11 id_P \"namP\".13 \"moto\" id_T.15 \"namT\" \"jnrT\".17 fNam"\ ) >fOut for(jj=1;jj<=nEnd;jj++)print(aEnd[jj]) >fOut # <- старый подвал + свежак -v exit } # ;Luck new.2 hitP numP.4 sizK sizN.6 hitT txtN.8 sizT datP.10 endD id_P.12 "namP" "moto".14 id_T "namT".16 "jnrT" fNam.18 # 290 0 12266 141 3848 9 293 1 1821.1 2019.06.23 2017.11.30 s/sks "Скс" "Режим•бога" 111 "Режим•бога" "<a•href=/type/index_type_1-1.shtml>Роман</a>:" s~sks END{ if(errS!=""){ print(errS) exit -1 } # выжимка для отчёта # 5A 2023.07.23:dat1 2023.07.27:dat2 600:gNum 229:newH 118:nTxL 117:nTit 117:nTxt 1:nErr print(dat1":dat1",dat2":dat2",gNum":gNum",newH":newH",nTxL":nTxL",nTit":nTit",nTxt":nTxt",nErr":nErr") }
Имя файла скрипта: "gAuthH.awk" V-текст скрипта-V- - - - - - - - - BEGIN{ # gAuthH.awk - прирост хитов двух последних списков aHits, # Out - сортированный список дифов, если нужные переменные среды не установлены, # работает автономно, результат - в текущем каталоге; выюор aHits: по _siTop.# # интервал дат (т.е. число дней в нём) == разница в датах создания выбранных aHits # modG ==0(или без параметров) == выбор/анализ ситуации с aHits с оживляжем на экране # ==1 == выбор/анализ ситуации с aHits, итоги на StdOut # ==2 на StdOut список разделов с удачей 10 для дальнейшей работы с оным # 2024.09.08, nvv, место под sizK увеличено до 99Gb (8+1 знако-место) # + 6+1 под sizN # ! прочая история в подвале extH="gAuthH" # тип работы (расширение полного списка дифов) bRd=":!:" # разделитель блоков в строке newH=0 # раздела нет в предыдущем aHits modG=0 # поиск/оценка; 0==оживляж на экране, 1==выдача данных на StdOut nErr=0 jDat=getEnv("jDat") # jDat - "сегодня" jRpt=getEnv("jRpt") # сводный отчёт по рассчётам siTopTexts xDir=getEnv("xDir")"\\" # склад сводок и выборок к рассчётам jDir=getEnv("jDir")"\\" # рабочая папка с файлами выборок для_расчёта modG=getEnv("modG") # 0 == поиск/оценка ситуации, 1-список разделов-^ minL=getEnv("minL") # минимальные хиты в сутки для проверки текстов раздела if(jRpt==""){ jRpt="\\Jobs\\_siTop.#" # общий лог расчётов xDir="\\Stor\\wOld\\" # общий склад списков jDir=".\\" # рабочая папка под файлы jDat=strftime("%Y.%m.%d") minL=100 # граница интереса (10 хитов в сутки) modG=0 # поиск/оценка; 0==оживляж на экране, 1==выдача данных на StdOut 2==список # 2024.03.02..04-dates # gapD=2 # gNum=817 # preF="\\Stor\\wOld\\2024.03.02\\2024.02.29.aHits # curF="\\Stor\\wOld\\2024.03.04\\2024.03.03.aHits } if(substr(jDat,9,2)<="02"){ # до 3-го числа месяца считать заведомо нечего errS="NO "extH" now, month beginning" exit } numD=0 while((getline line<jRpt)>0){ # ищем в _siTop.# нужные нам даты aHits и gAuth # ;1A hits 2:xNam 445:xNum 101285:xPas 2021.04.22:hDat 1018:hPag 806772:hMax 1018:DnLd 2021.04.27:done 25:mins gapT~14:53-15:18~ if(match(line,/^;1A .+ (20[\.0-9]{8}):hDat .+ (20[\.0-9]{8}):done /,arr0)){ curD=arr0[2] # дата в имени КАТАЛОГА с нужным aHits aFil[curD]=arr0[1] # дата в имени нужного ФАЙЛА aHits } if(match(line,/^;5Q .+ (20[\.0-9]{8}):dat2 .+ (20[\.0-9]{8}):done /,arr0)){ aFi2[arr0[2]]=arr0[1] # datF - дата в имени нужного aHits } } close(jRpt) curF=aFil[curD] # дата в имени самого свежего aHits if(jDat!=curD){ # а этот-то свежак - сегодняшний? errS="NOT toDay's last: " curD".aHit" exit } j0=substr(jDat,1,4)" "substr(jDat,6,2)" "substr(jDat,9,2)" 11 00 00" tic0=mktime(j0) # "сегодня" в секундах shft=0 # свиг в днях от сегодня gapD="" # искомый интервал дат while(++shft){ # ищем оный -^ j1=tic0-(86400*shft) j0=strftime("%Y.%m.%d",j1) # это очередная проверяемая дата if(shft==1)datJ=j0 # верхняя граница обсчитываемого интервала if(j0 in aFil){ # есть aHits за ету дату! preD=j0 # возможная нижняя дата нашего интервала gapD=shft # а это интервал дат } if(strftime("%d",j1)=="02")break # упёрлись в начало месяца, стоп if(j0 in aFi2) break # -""- в предыдущий расчёт, стоп } if(!gapD){ errS="NOT good gapDown from last: " curD".aHit" exit } preF=xDir preD"\\"aFil[preD]".aHits" # полное имя предыдущего aHits curF=xDir curD"\\"aFil[curD]".aHits" # полное имя текущего aHits # 1 2 3 4 5 6 7 # 441971 6 1077 3 k/kadawr "Кадавр" "no•comments" # hitP.1 numP.2 sizK.3 sizN.4 id_P.5 "namP".6 "moto".7 # загрузим опорный (aka предыдущий) список "разделы-хиты" if(!modG)print(extH" loading preHits "preF" ... ") # оживляж... preN=0 while ((getline line < preF) > 0) { split(line,aj) # v- для сравнения нужны ВСЕ разделы из старого списка # if(match(aj[1],/^[0-9]+$/)&&aj[4]&&(aj[6]!="\">?<\"")){ # нужна запись НЕ пустого раздела if(match(aj[1],/^[0-9]+$/)){ # нужна запись НЕ пустого раздела preN++ a2h[aj[5]]=aj[1] # массив hitP[id_P] }else if(aj[1]==";1A")iPre=";1aPre "substr(line,5) } close(preF) # всё/не_всё, - старый список тогось if(!preN){ # старый список пуст # if(modG)print("") errS="NO_or_BAD_preHits:" preF ", (jRpt:"jRpt")" exit } if(!modG)print(extH" found preN:"preN) # оживляж... if(!modG)print(extH" loading curHits "curF" ... ") # оживляж... # сравним оперативный (aka текущий) список с предыдущим (опорным - выцепим изменения в хитах) curN=0 while ((getline line < curF) > 0) { split(line,aj) # разделяем строку на элементы if(match(aj[1],/^[0-9]+$/)&&aj[4]&&(aj[6]!="\">?<\"")){ # это строка НЕ пустого раздела id_P=aj[5] if(id_P in a2h){ # был в предыдущем, считаем luck=aj[1]-a2h[id_P] # прирост хитов за gapD дней typH="0" # флаг "НЕ новый" раздел в aHits }else{ luck=aj[1] # все накопленные хиты typH="1" # флаг "НОВЫЙ" раздел newH++ } luck=sprintf("%7.1f",10*luck/gapD) # удача*10 раздела "начерно" split(luck,ak,".") luck=ak[1] # нам нужна целая часть (без дробной после запятой) if(luck-minL>=0){ # удачи "начерно" достаточно для более внимательной проверки hitP=aj[1] numP=aj[2] sizK=aj[3] sizN=aj[4] gNum++ aDif[id_P]=sprintf("%5s"bRd"%s %6s %6s %8s %6s"bRd"%s"\ ,luck,typH,hitP,numP,sizK,sizN,aj[6]" "aj[7]) } }else if(aj[1]==";1A")iCur=";1aCur "substr(line,5) } close(curF) # всё/не_всё, - новый список обработан if(!gNum){ # старый список пуст? errS="NO_or_BAD_curHits:" curF ", (jRpt:"jRpt")" exit } # старый список пуст if(!modG)print(extH" found difN:"gNum) # оживляж... # 2024.01.25:dat1 2024.01.28:dat2 817:gapD 596:gNum fOut=jDir datJ"."gapD"."extH # итоговый список "2020.11.14.3.gAuthH" if(!modG)print(extH" "preD".."substr(curD,9,2)"-dates",gapD":gapD", gNum":gNum", preF, curF) if(!modG)print(gapD,gNum,nErr,fOut) if(!modG)exit # поиск/оценка; 0==оживляж на экране, 1==выдача данных на StdOut # ;1aPre hits 5:xNam 461:xNum 105337:xPas 2024.02.25:hDat 502917:hMax 1059:hPag 1386:add2 309:h30k 1059:dnLd 0.26~ratW 2024.02.26:done 00:22:35~wrks 9:04 # ;1aCur hits 5:xNam 462:xNum 105343:xPas 2024.02.27:hDat 504808:hMax 1059:hPag 709:add2 310:h30k 1059:dnLd 0.14~ratW 2024.02.28:done 00:20:24~wrks 9:07 # формат конечного списка # 2456:!:0 53231 38 312 8:!:f/fox:!:"Fox" "Раздел..." # ;Luck.1 ! new hitP.3 numP sizK.5 sizN ! id_P.7 ! "namP" "moto".9 # block.1 <- - - - block.2 - - - - -> block.3 <- block.4 - -> for(j1 in aDif){ j2=split(aDif[j1],aj,bRd) # разделим строку на блоки aOut[++nOut]=aj[1] bRd aj[2] bRd j1 bRd aj[3] # и соберём для сортировки и выдачи в файл } info=";5G gapP "datJ":datJ "gapD":gapD "gNum":gNum "nErr":nErr "minL":minL "newH":newH "strftime("%Y.%m.%d:done at~%H:%M") asort(aOut) # сотртировка по возрастанию(!) "удачи" # nnn 15572 # 423515 6 1094 3 k/kadawr "Кадавр" "no•comments" for(j1=nOut;j1>0;j1--)print(aOut[j1]) >fOut print(";Luck.1 ! new hitP.3 numP sizK.5 sizN ! id_P.7 ! \"namP\" \"moto\".9") >fOut print(iPre) >fOut print(iCur) >fOut print(info) >fOut if(nErr){ for(j1=nErr;j1>0;j1--)print(aErr[j1]) >fOut".err" print(info) >fOut".err" } print(" == gNum:"gNum", gapD:"gapD", nErr:"nErr) exit } function mkSecs(fNam){ n1=split(fNam,aj,":") n1=split(aj[n1],aj,"\\") n1=split(aj[n1],aj,".") return(mktime(aj[1]" "aj[2]" "aj[3]" 12 00 00")) } function getEnv(env1) { # найти в массиве ENVIRON значение переменной с именем env1 for(env0 in ENVIRON){ # ! реГИстр букв в имени переменной МОЖЕТ быть лЮбОй if(tolower(env0)==tolower(env1)){ # имя переменной совпадает с указанным? return(ENVIRON[env0]) # вернём значение этой переменной } } return("") # ничего нет? знать не судьба... } END{ if(errS!=""){ print("") print("] "errS) exit -1 } # 2020.11.01, nvv, creation # 2020.11.27, nvv, minor improvements +comments adds +;1A-info -> ;1aPre/;1aCur # 2020.11.29, nvv, изменен формат имены вых.файла fOut curD.datG. # 2021.02.07, nvv, исправлена неточность в выявлении координат и имён последних *.aHits # 2021.02.12, nvv, добавлено извещение о числе разделов с "удачей" >=100 (gNum) # 2021.03.15, nvv, переписаны стартовые операции для корректного вычленения нужных *.aHIts # 2021.04.27, nvv, дифер занимается именно разницей aHits, прочее - в CMD # 2021.05.02, nvv, мелкая косметика # 2021.05.26, nvv, очередное вструмление-с # 2021.06.09, nvv, мелкое уточнение выявление preS и datJ # 2021.07.21, nvv, ручное задание дат нижней границы: pre? # 2021.09.29, nvv, ручное задание дат нижней границы: pre? # 2021.10.11, nvv, улучшена выдача на экран в пакетном режиме (оживляж-с;) # 2021.11.20, nvv, ещё одно улучшение оживляжа-с ;) # 2021.12.07, nvv, ещё одно улучшение оживляжа-с ;) # 2022.04.18, nvv, 3000+ посетителей в день - криминал! + серьёзно переделано # в том числе формат вых.файла (см. переменную bRd) # 2022.08.29, nvv, для сравнения нужны ВСЕ разделы из СТАРОГО списка, в т.ч. без текстов и ника # 2024.03.08, nvv, изменился рисунок публикации данных учёта посетителей СИ: # - с 2024.02.23 ЕЖЕДНЕВНО!, скрипт серьёзно переделан }
Имя файла скрипта: "gAuthI.awk" V-текст скрипта-V- - - - - - - - - BEGIN{ # gAuthI.awk разбор шапкок разделов СИ # 2020.11.28, nvv, объём (например "1899k/3") надлежит разделять (например: "1899" + "3") # 2021.05.02, nvv, мелкая косметика # 2022.04.17, nvv, радикально переделано # 2023.01.25, nvv, сменилось разрешение экрана, слегка меняем оживляж # 2024.03.04, nvv, исчезло двоеточие ":" после ника (ФИО) в главномм индексе # 2024.09.08, nvv, место под sizK увеличено до 99Gb (8+1 знако-место) # + 6+1 под sizN if(ARGV[1]=="")exit # защита от случайного пуска bRd=":!:" # разделитель блоков в строке for(str2 in ENVIRON){ # ! регистр букв в имени переменной может быть любой str1=tolower(str2) # Temp и temp - РАЗНЫЕ имена для gAwk... if(str1=="gsta") gSta=ENVIRON[str2] # исходный список } if(gSta=="")gSta="\\Jobs\\#gAuth\\2024.03.05.2.gAuthS" j0=split(gSta,aj,"\\") fOut=aj[j0] if(j0==1)fPth="" else{ fPth=aj[1]"\\" for(j1=2;j1<j0;j1++)fPth=fPth aj[j1]"\\" } split(fOut,aj,".") datJ=aj[1]"."aj[2]"."aj[3] gapD=aj[4] fOut=fPth datJ"."gapD".gAuthI" # формат входного списка # 277 0 277 0 58367 29 1159 3 :!:k/kadawr:!:n "Псион":!:"Кадавр" "no•comments" # ;txtL txtG.2 Luck new.4 hitP numP.6 sizK sizN.8 ! id_P ! id_T.10 "namT" ! "namP".12 "moto" # <- - - - - - - block.1 - - - - - - - - - - -> block.2 <- block.3 -> <- block.4 -> while((getline line<gSta)>0){ # ищем последнюю запись успешного скачивания этого списка jj=split(line,aj,bRd) # !!! причесать по новому! if(jj==4){ # строка раздела id_P=aj[2] # его ID aIdT[id_P]=aj[3] # его самый посещаемый текст aIdP[id_P]=aj[4] # его описание /из aHits/ nIdP++ # счётчик разделов-кандидатов в рейтинг }else{ # строка подвала if(match(aj[1],/^;[0-9][^ ]/))aEnd[++nEnd]=line # прикопаем... } } close(gSta) int7=(nIdP-(nIdP%100))/100 if(nIdP%100)int7=int7"+" buf="" errS="" nErr=0 tIni=systime() print("scan "nIdP" titles...") # ;Luck new.2 hitP numP.4 sizK sizN.6 hitT txtN.8 sizT datP.10 endD id_P.12 "namP" "moto".14 id_T "namT".16 "jnrT" fNam.18 # 290 0 12266 141 3848 9 293 1 1821.1 2019.06.23 2017.11.30 s/sks "Скс" "Режим•бога" 111 "Режим•бога" "<a•href=/type/index_type_1-1.shtml>Роман</a>:" s~sks # gHit: id_P hitP numP new # gSta: id_P txtL txtG id_T hitP numP new # gTtl: id_P datP sizK sizN "namP" "moto" # gTxt: id_P id_T sizT endD "namT" "jnrT" } { if(FNR==1){ if(NR!=1)chkSteps() # чем закончилась обработка предыдущего файла? step=0 # 0-владелец, 1-дата обновления, 2-id раздела, 3-разбор строк таблиц статистики buf="" fPth=FILENAME fNam=split(fPth,arr0,"\\") # NEW/NEXT входной файл as-is (с полным путём) fNam=split(arr0[fNam],arr0,".") # файл: чистое nam.ext (like "0-0.stat.htm") fNam=arr0[1] # fNam чистое имя (like "0-0" in "0-0.stat.htm") id_P=substr(fNam,1,1)"/"substr(fNam,3) if(!(id_P in aIdP)){ # это левый раздел (нет во вхолном списке) errS="] - NO in gAuthH: "id_P" " fNam nextfile # что-то не так с датой обновления } int8++ if(int8%100==0) print(sprintf(": %3s.%-3s",int8/100,int7),strftime("%H:%M")) else if(int8%10)printf(".") else printf(":") # оживляж... } gsub(/( )+|\xA0+|[\0-\31]+/," ",$0) # цепочки " " и прочих "пробелов" -> " " (пробел) buf=buf" "$0 # gTtl: id_P sizK sizN datP "namP" "moto" if(step==0){ # ищем/проверяем ФИО автора # <h3>Фонд А.:<br> <font color="#cc5555">всяко-разное</font></h3> if(match(buf,/<h3>([^:<]+):?<br> <[^>]+>([^<]+)<\/font><\/h3>/,aj)){ namo=pack(aj[1])" "pack(aj[2]) # "namP" "moto" buf=substr(buf,RSTART+RLENGTH) step=1 next } }else if(step==1){ # ищем/проверяем ФИО автора # <li><b><a href=/long.shtml><font color=#393939>Обновлялось:</font></a></b> 28/03/2022 # <li><b><a href=/rating/size/><font color=#393939>Объем:</font></a></b> 311k/1 if(match(buf,/>Обновлялось:<.+([0-9]{2})\/([0-9]{2})\/(20[0-9]{2}).+>Объем:<.+ ([0-9]+)k\/([0-9]+) +</,aj)){ aIdI[++nIdI]=aj[3]"."aj[2]"."aj[1] sprintf(" %8s %6s",aj[4],aj[5]) bRd id_P bRd aIdT[id_P] bRd namo buf=substr(buf,RSTART+RLENGTH) step=2 nextfile } } } function pack(f1s1) { # мешающие chars -> нейтральные + cut too long + закавычить результат f1n1=split(f1s1,f1a1) f1s1=f1a1[1] # обихаживание пробелов... " " -> "•" for(f1n2=2;f1n2<=f1n1;f1n2++)f1s1=f1s1"•"f1a1[f1n2] f1s2="" # двойные кавычки -> """ while(f1n1=index(f1s1,"\"")){f1s2=f1s2 substr(f1s1,1,f1n1-1)"""; f1s1=substr(f1s1,f1n1+1)} f1s1=f1s2 f1s1 f1s2="" # "%" -> "%" while(f1n1=index(f1s1,"%")){f1s2=f1s2 substr(f1s1,1,f1n1-1)"%"; f1s1=substr(f1s1,f1n1+1)} f1s1=f1s2 f1s1 if(length(f1s1)>999){ # обрезка слишком длинных литералов f1n1=index(substr(f1s1,1000),"•") if(!f1n1)f1n1=1000 else f1n1=f1n1+999 # v-вместо обрезанного - справка о факте ;) f1s1=substr(f1s1,1,f1n1-1)"•(+"(length(f1s1)-f1n1)" chars)" } return ("\""f1s1"\"") # результат "закавычивается!" } function chkSteps() { # проверка чем закончилась обработка очередного файла? if((step==2)&&(errS=="")){ # всё штатно ("ОК") return }else{ if(errS==""){ if(step==1){ errS="] no or bad datP/sizK for "id_P" in: " fNam }else if(step==0){ errS="] no or bad namP/moto for "id_P" in: " fNam } } aErr[++nErr]=errS errS="" # и очистим флаг-инфо } } END{ if(ARGV[1]==""){ print("] no_file_in") exit 1 # защита от случайного пуска } chkSteps() if(int8%100)print("") print(" == "int8":titls",strftime("%H:%M:%S",systime()-tIni,-1)) # проблем нет # print nIdI"~"aIdI[nIdI]"~"length(aIdI) asort(aIdI) for(jj=1;jj<=nIdI;jj++) print(aIdI[jj]) >fOut # for(jj=1;jj<=nIdI;jj++) print(jj" * "aIdI[jj]) print("; datP sizK sizN ! id_P ! id_T \"namT\" ! \"namP\" \"moto\"") >fOut for(jj=1;jj<=nEnd;jj++)print(aEnd[jj]) >fOut # <- старый подвал + свежак -v j0=";5I titl "datJ":datJ "gapD":gapD "nIdI":nTit "nErr":nErr "strftime("%Y.%m.%d:done at~%H:%M") print(j0) >fOut if(nErr){ for(jj=1;jj<=nErr;jj++) print(aErr[jj]) >fOut".err" nErr=nErr":nErr" }else nErr="" print(" ==",nIdI":nTit",nErr) }
Имя файла скрипта: "gAuthS.awk" V-текст скрипта-V- - - - - - - - - BEGIN{ # gAuthS.awk выченение хитов разделов/тектов за заданный интервал дат # отбираются тексты с 200+ удачи /по одному самому удачному на раздел/ # 2024.06.25, nvv, понижен порог отбора годных текстов с 20-и до 10-и хитов а день # ! прочая история в подвале if(ARGV[1]=="")exit # защита от случайного пуска bRd=":!:" # разделитель блоков в строке # массив имён месяцев для преобразования их в числа с лидирующим нулём 01..12 mNum["Jan"]="01" # .1 January . Jan. 31 . winter wint mNum["Feb"]="02" # .2 February .Feb. 28/29 mNum["Mar"]="03" # .3 March . . Mar. 31 . spring sprn mNum["Apr"]="04" # .4 April . . Apr. 30 mNum["May"]="05" # .5 May . . . May. 31 mNum["Jun"]="06" # .6 June . . .Jun. 30 . summer summ mNum["Jul"]="07" # .7 July . . .Jul. 31 mNum["Aug"]="08" # .8 August . .Aug. 31 mNum["Sep"]="09" # .9 September Sep. 30 . autumn autm mNum["Oct"]="10" # 10 October . Oct. 31 mNum["Nov"]="11" # 11 November .Nov. 30 mNum["Dec"]="12" # 12 December .Dec. 31 . winter wint split("",aSel) # в ячейках статистики: url,title,hits:all,12mon,mon0..monC-11,day0..day0-61 for(str2 in ENVIRON){ # ! регистр букв в имени переменной может быть любой str1=tolower(str2) # Temp и temp - РАЗНЫЕ имена для gAwk... if(str1=="gdif") gDif=ENVIRON[str2] # исходный список if(str1=="minl") minL=ENVIRON[str2] # минимальная удача*10 текста "начерно" } if((gDif=="")||(minL=="")){ # вызвали НЕ из CMD gDif="U:\\Jobs\\#gAuth220325\\2022.03.22.21.gAuthH" gDif="\\Jobs\\#gAuth\\2024.06.23.1.gAuthH" # gDif="2022.03.22.21.gAuthH" minL=100 # мин. кол-во хитов в день (в среднем) "начерно" } j0=split(gDif,aj,"\\") fOut=aj[j0] if(j0==1)fPth="" else{ fPth=aj[1]"\\" for(j1=2;j1<j0;j1++)fPth=fPth aj[j1]"\\" } split(fOut,aj,".") datJ=aj[1]"."aj[2]"."aj[3] gapD=aj[4] fOut=fPth datJ"."gapD".gAuthS" # print(">"fOut"<") # exit # minT=minL*2 # 200 минимальная удача*10 текста "набело" minT=minL # 100 минимальная удача*10 текста "набело" preS=strftime("%Y.%m.%d",mktime(substr(datJ,1,4)" "substr(datJ,6,2)" "substr(datJ,9,2)" 12 00 00")-86400*(gapD-1)) # формат входного списка # 2456:!:0 53231 38 312 8:!:f/fox:!:"Fox" "Раздел..." # ;Luck.1 ! new hitP.3 numP sizK.5 sizN ! id_P.7 ! "namP" "moto".9 # block.1 <- block.2 {aIdP[id_P]} -> block.3 <-block.4{aIdD[id_P]} - -> while((getline line<gDif)>0){ # ищем последнюю запись успешного скачивания этого списка split(line,aj,bRd) # !!! причесать по новому! if(match(aj[1],/^ *[0-9]+$/)){ # строка раздела id_P=aj[3] # его ID aIdP[id_P]=aj[2] # его данные из aHitc aIdD[id_P]=aj[4] # его описаните оттуда же nIdP++ # счётчик разделов-кандидатов в рейтинг }else{ # строка подвала if(match(aj[1],/^;[0-9][^ ]/))aEnd[++nEnd]=line # прикопаем... } } close(gDif) int7=(nIdP-(nIdP%100))/100 if(nIdP%100)int7=int7"+" txtD=0 # число текстов с интервалом МЕНЬШЕ заданного errS="" nErr=0 tIni=systime() print("scan "nIdP" stats within: "preS"-"datJ) } { # // -=- основной блок скрипта begs if(FNR==1){ if(NR!=1)chkSteps() # чем закончилась обработка предыдущего файла? step=0 # 0-владелец, 1-дата обновления, 2-id раздела, 3-разбор строк таблиц статистики fPth=FILENAME fNam=split(fPth,arr0,"\\") # NEW/NEXT входной файл as-is (с полным путём) fNam=split(arr0[fNam],arr0,".") # файл: чистое nam.ext (like "0-0.stat.htm") fNam=arr0[1] # fNam чистое имя (like "0-0" in "0-0.stat.htm") id_P=substr(fNam,1,1)"/"substr(fNam,3) if(!(id_P in aIdP)){ # это левый раздел (нет во вхолном списке) errS= "] - NO in gAuthH: "id_P" " fNam nextfile # что-то не так с датой обновления } maxL=0 # максимальная удача текста в разделе nTxt=0 # кол-во отобранных текстов dayB=0 # верхний день нашего интервала в таблицах статистики, значение: в диапазоне 17-77 dayE=0 # нижний день нашего интервала, НЕ входит в него maxT=0 # хиты лидера (литеров) inTab=0 # сначала - мы НЕ "в таблице" numT=0 # счётчик таблиц в файле статистики numR=0 # счётчик строк в текущей таблице selN=0 int8++ if(int8%100==0) print(sprintf(": %3s.%-3s",int8/100,int7),strftime("%H:%M")) else if(int8%10)printf(".") else printf(":") # оживляж... } gsub(/( )+|\xA0+|[\0-\31]+/," ",$0) # цепочки " " и прочих "пробелов" -> " " (пробел) if(step==0) { # ищем/проверяем ФИО автора # <h3>Статистика раздела "<a href=./>Влад</a>":</h3> if (match($0,/<h3>Статистика раздела \"<a href=\.\/>(.*)<\/a>\":<\/h3>/,arr0)) { if(arr0[1]==""){ errS="] NO nick in: " fNam nextfile # что-то не так с датой обновления } # namP=pack(arr0[1]) step++ # проверка ОК } }else if(step==1){ # вычленеие даты обновления статистики if(match($0,\ /<li><i>Статистика рассчитывается .+\. \(.+ (...) +([0-9]+) (..:..:..) (20[0-9][0-9])\)<\/i>/\ ,arr0)){ if(length(arr0[2])==1) arr0[2]="0"arr0[2] # причешем первые дни месяца "1" -> "01" ticS=mktime(arr0[4]" "mNum[arr0[1]]" "arr0[2]" 12 00 00") # тики на 12 часов даты статистики datS=arr0[4]"."mNum[arr0[1]]"."arr0[2] # сама дата пополнения статистики timS=arr0[3] # время оного-же step++ # дату статистики оптичили } }else if(step==2){ # ищем authID (!должен быть) в отсылке на top.mail.ru # [<a href=http://top.mail.ru/pages?id=77427&period=0&date=2018-10-02&filter_type=0 # &filter=n/nosow_w_w&pp=20&gender=0&agegroup=0>по дням</a>] if (match($0,/\[<a href=http.+&filter=([0-9a-z]\/[\-0-9a-z_]+)&pp=.+>по дням<\/a>]/,arr0)) { if(id_P!=arr0[1]){ # это ПОЛНЫЙ криминал! errS="] "arr0[1]" != fNam: " fNam nextfile } step++ # проверка ОК } }else if(step==3){ # таблицы статистики, просмотр строк, сборка данных в ячейках if($0=="<!--------- Подножие ------------------------------->"){ # разбор закончен step++ nextfile } if(inTab){ # Мы ВНУТРИ таблицы, собираем строки таблицы с хитами текстов buf0=buf0" "$0 # gain inpLines to buf0, then check contents while((match(buf0,/<tr ?[^>]*>/))||(int0=index(buf0,"</tr"))){ # seek <tr .. </tr for tabRow if(RSTART){ # new/next line begs numR++ buf0=substr(buf0,RSTART+RLENGTH) # cut <tr ?*> at the beginning of the line } if(int0=index(buf0,"</tr")){ # this line ends getSels(substr(buf0,1,int0-1)) # tabl_row -> arrow:sell_values buf0=substr(buf0,int0+4) # убрали эту строку из буфера и окультуриваем... sErr="" # пока этот текст/раздел НЕ в браке id_T=aSel[0] # имя+расшир файла с текстом (или "./" для раздела) namT=aSel[1] # пока фактическое (as-is) название текста в статистике if((numT==1)&&(numR==2)){ # хиты по разделу (спец.обслуживание) # namT="\"<!>\"" # id_T="~" # prt 8-раздел: 'хиты за 30 дней' # 0.1-имя/ссылка; хиты: 2-всего, 3-12мес, 4..15-заМес, 16..77-заСутки if(minT-luck>0){ # у раздела мало хитов за нужный интервал # errS="] step."step" (luck:"luck"; less:"minT" in fNam: " fNam " )" step=4 nextfile }else{ aIdL[id_P]=luck # реальная удача раздела } }else{ # обычная строка статистики текста if(minT-aSel[3]>0){ # дальше только неудачники step=4 nextfile } int0=split(id_T,arr0,".") id_T=arr0[1] if(int0!=2){ sErr="zOrg" # нарушен формат имени файла: name.ext }else if(arr0[2]!="shtml"){ sErr="xExt" # расширенеие не то-с }else if (gensub(/[\-0-9a-z_]/,"","g",arr0[1])!=""){ sErr="vNam" # левые символы в имени файла текста }else if(namT==""){ sErr="tHdr" # "пустое" название текста }else if(minT-luck>0){ sErr="lowH" # у текста мало хитов за нужный интервал }else{ if(maxL-luck<0){ # отбираем самый успешный текст maxL=luck if(nulN!=0){ nulN=gapD-nulN txtD++ } aTxL[id_P]=sprintf("%6.0f %2s ",luck,nulN) # удача текста за... это цифры aTxN[id_P]=id_T" "pack(namT) # и его атрибуты это цепочки символов } } sErr="" } } } if(int0=index(buf0,"</table")){ # this tabl ends buf0=substr(buf0,int0+4) # update buf0 inTab=0 } }else{ # ищем начало таблицы if(int0=index($0\ ,"<table border=1 cellspacing=0 cellpadding=0><tr><td><td colspan=2><b>Итого</b></td>")){ numT++ # new table numR=1 # певая строка каждой таблицы - календарь хитов статистики раздела buf0=substr($0,int0+80) if(numT==1){ # 1-st table 1-st row -> get col-dates & so-on match(buf0,/<tr[^>]*>(.+)<\/tr[^>]*>/,arr0) # собственно строка с календарём getSels(arr0[1]) # но самую первую такую - разберём-с tic0=ticS # и привяжем дату к нулевому (самому левому) дню посуточных данных int0=16 while(strftime("%d",tic0)!=aSel[int0])tic0=tic0-86400 # сдвинем стат.дату к нулевому дню while(int0<78){ int0++ tic0=tic0-86400 datS=strftime("%Y.%m.%d",tic0) if(datS==datJ)dayB=int0 if(datS==preS)dayE=int0 } if(!dayB){ errS="] NO datJ:"datJ", in " fNam nextfile } if(!dayE){ errS="] NO preS:"preS", in " fNam nextfile } } inTab=1 # мы ВНУТРИ таблицы buf0="" # буфер чист! } } } } # // -=- основной блок скрипта ends function getSels(rowLn){ # разделение строки таблицы статистики на массив значений hitT=0 # + сумма хитов "за 30 дней" selN=0 # sells count nulN=0 # число пустых ячеек в нашем интервале split("",aSel) aSel[0]="" while(match(rowLn,/<td[^>]*>/)){ # это объявление ячейки selN++ # 0.1-имя/ссылка; хиты: 2-всего, 3-12мес, 4..15-заМес, 16..77-заСутки rowLn=substr(rowLn,RSTART+RLENGTH) # выкусим объявление ячейки f3n2=index(rowLn,"</td") # это конец ячейки f3s2=substr(rowLn,1,f3n2-1) # это сама ячейка (с возможными внутренними тегами) if(selN==1){ # в ПЕРВОЙ ячейке - название текста и ссылка на него match(f3s2,/<a href=([^>]+)>(.*)<\/a>/,f3a1) # выцепим и разложим: aSel[1]=f3a1[2] # название текста aSel[0]=f3a1[1] # ссылка на текст: name.shtml }else aSel[selN]=rmTags(f3s2) # в ПРОЧИХ ячейках - только значение ячейки, очищенное от тегов rowLn=substr(rowLn,f3n2) # выкусим оптиченную ячейку if(selN-dayB>=0){ # начало /самый свежий день/ нашего интервала if(dayE-selN>=0){ # внутри этого интервала hitT=hitT+aSel[selN] # считаем сумму хитов за gapD if(aSel[selN]==0)nulN++ # пустая ячейка В интервале(!), зачтём } if(aSel[selN]!=0)nulN=0 # непустая ячейка ПОСЛЕ начала интервала } } if(gapD==nulN)luck=0 # удача этой строки статистики else luck=sprintf("%5.0f",10*hitT/(gapD-nulN))+0 # print numT,numR,luck if(selN==77)return # row HAVE had 77 sells nextfile # битая таблица == битый файл } function rmTags(f2s1){ # удаление ВСЕХ тегов в литерале while(match(f2s1,/<\/?[a-zA-Z][1-6a-zA-Z]?[a-zA-Z]*[ \/]?[^>]*>/)) f2s1=substr(f2s1,1,RSTART-1) substr(f2s1,RSTART+RLENGTH) return(f2s1) } function pack(f1s1) { # мешающие chars -> нейтральные + cut too long + закавычить результат f1n1=split(f1s1,f1a1) f1s1=f1a1[1] # обихаживание пробелов... " " -> "•" for(f1n2=2;f1n2<=f1n1;f1n2++)f1s1=f1s1"•"f1a1[f1n2] f1s2="" # двойные кавычки -> """ while(f1n1=index(f1s1,"\"")){f1s2=f1s2 substr(f1s1,1,f1n1-1)"""; f1s1=substr(f1s1,f1n1+1)} f1s1=f1s2 f1s1 f1s2="" # "%" -> "%" while(f1n1=index(f1s1,"%")){f1s2=f1s2 substr(f1s1,1,f1n1-1)"%"; f1s1=substr(f1s1,f1n1+1)} f1s1=f1s2 f1s1 if(length(f1s1)>999){ # обрезка слишком длинных литералов f1n1=index(substr(f1s1,1000),"•") if(!f1n1)f1n1=1000 else f1n1=f1n1+999 # v-вместо обрезанного - справка о факте ;) f1s1=substr(f1s1,1,f1n1-1)"•(+"(length(f1s1)-f1n1)" chars)" } return ("\""f1s1"\"") # результат "закавычивается!" } function chkSteps() { # проверка чем закончилась обработка очередного файла? if((step==4)&&(errS=="")){ # всё штатно ("ОК") # if(maxL)aIdP[id_P]=aIdP[id_P]" "aTxL[id_P] # в разделе есть годный текст return }else{ if(errS==""){ # что-то не так, но нужно уточнить... if(step==3){ if(inTab==1){ # уточним проблему... if(selN!=77){ # row HAVE had 77 sells errS="] step."step" (selN:"selN" Tab:"numT" Row:"numR"{not 77}): " fNam " )" }else if((numT==1)&&(numR==2)){ errS="] step."step" (bad 1-st table 2-nd row in: " fNam " )" }else{ errS="] step."step" (unClosed table in: " fNam " )" } }else{ errS="] step."step" (no or bad table in: " fNam " )" } }else if(step==2){ errS="] step."step" (no or bad author's ID in: " fNam " )" }else if(step==1){ errS="] step."step" (no or bad refresh date:{"$0"}: " fNam " )" }else if(step==0){ errS="] step."step" (no partition`s owner in: " fNam " )" } } aErr[++nErr]=errS errS="" # и очистим флаг-инфо } } END{ # отстрелялись; ну почти... if(ARGV[1]==""){ print("? NO file in") exit 1 # защита от случайного пуска } # exit chkSteps() # чем закончилась обработка последнего файла? if(int8%100)print("") print(" == "int8":stats",strftime("%H:%M:%S",systime()-tIni,-1)) # проблем нет # aTxt == 10*Luck, id_P, id_T, namP, namT, fNam # (! в массиве наверняка есть "лишние" тексты из-за алгоритма: aHit[int0] < maxT ) # id_P=aj[3] # ID раздела # aIdL[id_P] # его реальная удача # aIdP[id_P] # его данные из aHitc # aTxL[id_P] # его удача текста за... # aTxN[id_P] # и атрибуты его текста # aIdD[id_P] # его описание оттуда же # для правильной сортировки по успеху именно текста припишем его спереди for(jj in aTxL)aOut[++nOut]=aTxL[jj] sprintf("%5s %s",aIdL[jj],aIdP[jj] bRd jj bRd aTxN[jj] bRd aIdD[jj]) # формат вЫходного списка # 613 0 65951 29 1159 3 613 0:!:k/kadawr:!:n "Псион":!:"Кадавр" "no•comments" # ;Luck new.2 hitP numP.4 sizK sizN.6 txtL txtG.8 ! id_P ! id_T.10 "namT" ! "namP".12 "moto" # <- - - - - - - block.1 - - - - - - - - - - - -> block.2 <- block.3 -> <- block.4 -> asort(aOut) for(jj=nOut;jj>0;jj--)print(aOut[jj]) >fOut # при выдаче приписанное надоть изъять! print(";txtL txtG.2 Luck new.4 hitP numP.6 sizK sizN.8 ! id_P ! id_T.10 \"namT\" ! \"namP\".12 \"moto\"")>fOut for(jj=1;jj<=nEnd;jj++)print(aEnd[jj]) >fOut # <- старый подвал + свежак -v j0=";5H txL1 "datJ":datJ "gapD":gapD "nOut":nTxL "nErr":nErr "minT":minT "txtD":txtD "strftime("%Y.%m.%d:done at~%H:%M") print(j0) >fOut if(nErr){ asort(aErr) for(int0=1;int0<=nErr;int0++)print(aErr[int0])>fOut".err" print(j0) >fOut".err" nErr=nErr":nErr" }else nErr="" print(" ==",nOut":nTxL",nErr) # 2020.11.23, nvv, creation # 2021.01.11, nvv, it works ok... # 2021.05.02, nvv, мелкая косметика # 2022.04.18, nvv, радикально переделано - теперь выдача точней и структурирована в блоки # 2023.01.25, nvv, сменилось разрешение экрана, слегка меняем оживляж }
Имя файла скрипта: "iNetR.awk" V-текст скрипта-V- - - - - - - - - BEGIN{ # iNetR.awk - оформление в HTML приложения "siTopAuthors" if(!(1 in ARGV))exit # защита от случайного пуска minT=333 # нижняя граница отбора в наш список: 33.3 посетителя в день, 999 за 30 дней minT=100 # 2024.08.27, nvv, отключена отметка "Upd" для: "Исходные тексты скриптов" # ! прочая история - в подвале rTyp="<b>siTopAuthors</b>" # siTopAuthors ancW="t" # общий признак типа рейтинга в якорях, комментах и т.п. ancS=":" # частный признак якоря места (в формате: "ггммвв:NNN" flag=0 # флаг для чередующейся раскраски строк таблиц tGap=50 # строк в одной таблице tMax=1000 # строк в списке всего oldP=0 # (раздел)размещено более года назад curP=0 # (-"-) - "" - в границах интервала и позже oldT=0 # (текст)размещено более года назад curT=0 # (-"-) - "" - в границах интервала и позже txtM=0 # число разделов с более чем одним лидером (с одинаковым успехом) auUp=0 # раздел, сдвиг вверх auDn=0 # раздел, сдвиг вниз auNw=0 # новый автор upAu=0 # объём+ раздела dnAu=0 # объём- раздела nwTx=0 # новый текст upTx=0 # объём+ текста dnTx=0 # объём- текста pDat=-1 # дата aHits по СИ preH=-1 # дата "скачан" (aHits) pPag=-1 # страниц aHits hDat=-1 # дата aHits по СИ donH=-1 # дата "скачан" (aHits) hPag=-1 # страниц aHits hMax=-1 # хиты раздела-лидера aHits minL=-1 # минимальная "удача" раздела hold=-1 # дата "расчёт" # "/" == общий префикс урла СИ: samlib.ru nUrl="n/nosow_w_w" # nvv-с... # jDat=strftime("%y%m%d%H%M%S",systime()) # дата для якорей таблиц for ( jj in ENVIRON ) { # ! регистр букв в имени переменной может быть любой j1=tolower(jj) if ( j1 == "fold" ) fOld=ENVIRON[jj] # ИМЯ опорного файла (like 2018.11.29.mText) if ( j1 == "hdir" ) hDir=ENVIRON[jj]"\\" # место для файлов *.HTML if ( j1 == "mint" ) minT=ENVIRON[jj] # минимальный успех*10 текста-лидера в разделе if ( j1 == "minl" ) minL=ENVIRON[jj] # минимальный успех*10 раздела } if(fOld==""){ fOld="U:\\Stor\\Text\\zOld.gAuths\\2021.05.26.3.gAuth" minL=100 } nMth[ 1]="января" nMth[ 2]="февраля" nMth[ 3]="марта" nMth[ 4]="апреля" nMth[ 5]="мая" nMth[ 6]="июня" nMth[ 7]="июля" nMth[ 8]="августа" nMth[ 9]="сентября" nMth[10]="октября" nMth[11]="ноября" nMth[12]="декабря" color[0]="\"#FFFFE0\"" # (четная строка таблицы) светло-жёлтый line color 0 color[1]="\"#F5F5DC\"" # (НЕчетная строка таблицы) грязно-жёлтый line color 1 color[2]="\"#C0C0C0\"" # gray серый (всё плохо) color[3]="\"#FFF4E0\"" # светло-розовый (ниже, меньше, плохо, нет) color[4]="\"#F0FFE0\"" # светло-зелёный (выше, больше, хорошо) color[5]="\"#FFFFB0\"" # светло-жёлтый - новое color[6]="\"#FFFF70\"" # yellow желтый (нечётные ячейки в шапках таблиц) color[7]="\"#F8F8F8\"" # светло-серый - наш рейтинг color[8]="\"#0000FF\"" # синий (птичка nvv) color[9]="\"#000000\"" # чёрный (вратый объём) color[10]="\"#E8F8B8\"" # зелёный - ячейки с текстом нашего рейтинга color[11]="\"#E0F8FF\"" # светло-сиреневый - размещено "давно" больше года назад color[12]="\"#FFD700\"" # оранжевый "потеряшки" /скрытые разделы/ aad2 # jDir datJ"."gapD"."nJob == U:\Jobs\2020.11.14.3.gGapR jr=split(ARGV[1],aq,"\\") # "U:" + "Jobs" + "2020.11.14.3.gGapR" split(aq[jr],aq,".") # "2020.11.14.3.gGapR" rYea=aq[1] # год рейтинга !привязан к верхней дате выборки rMth=aq[2] # месяц его же rDay=aq[3] # день его же datJ=rYea"."rMth"."rDay # дата верхнего конца интервала (включая) gapD=aq[4] # интервал (в днях) обсчитанного периода fOut=hDir datJ"."gapD".gAuth.html" # "U:\Stor\Html\" + "2020.11.14" + ".3" + ".auth.html" fPre=hDir datJ"."gapD".gAuth.z.html" # "U:\Stor\Html\" + "2020.11.14" + ".3" + ".auth.z.html" dBeg=strftime("%Y.%m.%d",mktime(rYea" "rMth" "rDay" 12 00 00")-86400*(gapD-1)) # дата 1-го дня выборки yBeg=substr(dBeg,1,4) # год этого 1-го дня интервала нашей выборки oldD=rYea-1"."rMth"."rDay # "год назад" - привязка к КОНЦУ нашей выборки tOld="года" qGap=gapD"_дн." if(gapD==1) sGap="день" else if(gapD-5<0) sGap="<b>"gapD"</b> дня" else sGap="<b>"gapD"</b> дней" info="<!-- (L) nvv; type: 'Auth' \"curr siTopAuthors\" "strftime("%Y.%m.%d %H:%M")" -->" # mark inf2="<!-- (L) nvv; type: 'Auth' \"prev siTopAuthors\" "strftime("%Y.%m.%d %H:%M")" -->" # mark print "--- " strftime("%H:%M:%S") " Begs..." # начали работу (оживляж;) # подвязка позиций прошлого рейтинга, для отметок "сдвиг" (места) # $1 $2 $3 $4 $5 $6 $7 $8 $9 $10 $11 $12 $13 $14 $15 $16 $17 $18 # Luck new hitP numP sizK sizN hitT txtN sizT datP endD id_P "namP" "moto" id_T "namT" "jnrT" fNam # 5527 0 218357 13 936 6 4937 1 7 2020.11.15 2020.08.31 z/zhan "Tony" "kjujdj•xbnfntkz" flibustain "Известные•мне•зеркала•Флибусты•и•Либрусека" "<a•href=/type/index_type_5-1.shtml>Статья</a>:" z~zhan # 10330 0 206377 14 938 8 10333 1 7.1 2021.04.03 2020.08.31 z/zhan "Tony" "kjujdj•xbnfntkz" flibustain "Известные•мне•зеркала•Флибусты•и•Либрусека" "<a•href=/type/index_type_5-1.shtml>Статья</a>:" z~zhan if(fOld!=""){ tmp0=0 while ((getline line < fOld) > 0) { # fOld: like 2018.11.29.mText split(line,aj) if(match(aj[1],/^[\.0-9]+$/)){ # это именно строка с успехом раздела &Co if((aj[7]-minT>=0)&&(aj[1]-minL>=0)){ # успех текста/раздела МОЖЕТ быть ниже границ tmp0++ # старая позиция раздела в старом списке a0a[aj[12]]=tmp0 # место раздела в старом списке a0k[aj[12]]=aj[5] # объём раздела в кбайтах a0n[aj[12]]=aj[6] # наполнение в штуках ;) a0t[aj[12]]=aj[15] # id_T (текста-лидера) split(aj[9],aq,".") a0z[aj[12]]=aq[1] # объём текста } }else if(match(line,/^;5H .+ 20([0-9]+)\.([0-9]+)\.([0-9]+):done /,aj))oDat=aj[1] aj[2] aj[3] } } close(fOld) # всё/не_всё, - старый список тогось jj=0 split("",a90) print "fOld: "fOld print "fLst: "ARGV[1] print "fOut: "fOut print "dBeg:"dBeg,"gapD:"gapD,"datJ:"datJ,"oDat:"oDat # exit } function mkPage() { # сборка всей страницы рейтинга/приложения (тип, строк, куда-с) if(strftime("%j")-355>0)jj="С наступающим" else if(strftime("%j")-11<0)jj="С" else jj="" if(jj!=""){ aHnY[++nHnY]="<table align=center border=0 cellspacing=0 cellpadding=2>" aHnY[++nHnY]="<tr align=center bgcolor=navy><td><font size=+2 color=aqua>" aHnY[++nHnY]="<b> ❄ "jj" новым годом! <font color=white>❄" aHnY[++nHnY]="<font size=+2 color=lime>Happy New Year! ❄ </b></td>" aHnY[++nHnY]="</tr></table>" aHnY[++nHnY]="<hr>" } aHdr[++nHdr]="См. <i>также</i>:" aHdr[++nHdr]="<br>?" aHdr[++nHdr]="<a href=/"nUrl"/si_pop-brief.shtml>Как узнать<b>" aHdr[++nHdr]="популярность произведения</b> в \"Самиздате\"</a>" aHdr[++nHdr]="(\"<b>где/что смотреть</b>\" - основное, вкратце)." aHdr[++nHdr]="<br>~" aHdr[++nHdr]="<a href=/"nUrl"/si_top500look-curr.shtml>Рейтинг" aHdr[++nHdr]="<b>siTopTexts</b> \"Произведения\"</a>" aHdr[++nHdr]="(\"Самиздат\", самое популярное за <b>30 дней</b>)." # † массив строк шапки ТОЛЬКО у последнего рейтинга aHd1[++nHd1]="<br>#" # aHd1[++nHd1]="<font color=\"#DC143C\">Upd</font>" # 2024.07.27 11:43 aHd1[++nHd1]="<a href=/"nUrl"/sitopscriptslist.shtml>" aHd1[++nHd1]="Исходные <b>тексты скриптов</b> задач \"<b>siTop…</b>\"</a>" aHd1[++nHd1]="<br>±" # <font color=red size=-2>New</font>" 2022.12.01 off aHd1[++nHd1]="<a href=/n/nosow_w_w/si_votes-brief.shtml><b>Оценка произведений</b>" aHd1[++nHd1]="в \"Самиздате\"</a> (<b>что, где, как</b> и почему…)." aHd1[++nHd1]="<br>√" aHd1[++nHd1]="<a href=/n/nosow_w_w/si-ini_reg.shtml><b>Регистрация</b> в \"Самиздате\" для получения" aHd1[++nHd1]="статуса «<b>пользователь</b>»</a> (оформление своего аккаунта)." aHd1[++nHd1]="<hr>" aHd1[++nHd1]="<b>NB.</b> <i>Названия</i> произведений и <i>псевдонимы</i>" aHd1[++nHd1]="авторов (как и прочие <i>сведения</i> в таблицах) приведены" aHd1[++nHd1]="<i>\"<a title=\"как есть\"" aHd1[++nHd1]="href=\"https://ru.wikipedia.org/wiki/%D0%9A%D0%B0%D0%BA_%D0%B5%D1%81%D1%82%D1%8C\"><u>as" aHd1[++nHd1]="is</u></a>\", по состоянию на момент</i> сбора" aHd1[++nHd1]="данных. <i>Текущее</i> состояние можно узнать, пройдя" aHd1[++nHd1]="<i>по ссылкам</i> (в ячейках таблиц)." aHd1[++nHd1]="<br><b>(!)</b> <i><u>Если</u></i> на месте некоторых букв" aHd1[++nHd1]="(символов) в <i>названии</i> произведения или в <i>псевдониме</i>" aHd1[++nHd1]="автора вы видите \"<i><u>пустоту</u></i>\", то <i><u>у" aHd1[++nHd1]="вас</u></i>, скорей всего, <i><u>отсутствует</u></i>" aHd1[++nHd1]="шрифт с такими символами (иероглифы, руны, etc.)." aHd1[++nHd1]="<br><b>(?!)</b> \"<i>Успех</i>\" - <i>среднее</i> число" aHd1[++nHd1]="посетителей за <b>сутки</b>. Нижняя граница: <b>10</b> хитов." # aHd1[++nHd1]="посетителей за <b>сутки</b>. Причём /за период между" # aHd1[++nHd1]="<i>обновлениями</i> учётных данных/ успех <b>раздела</b>" # aHd1[++nHd1]="должен быть <i>не ниже</i> <b>"minL"</b> (отбор начерно)," # aHd1[++nHd1]="а успех произведения-<b>лидера</b> (в нём) - <i>не" # aHd1[++nHd1]="ниже</i> <b>"sprintf("%4.1f",minT/10)"</b> (отбор начисто)." aHd1[++nHd1]="<br><b>(#)</b>" # 2023.08.02 # aHd1[++nHd1]="<font color=\"#DC143C\">NEW</font>" # 2023.06.23 crimson # aHd1[++nHd1]="" # 2023.07.08 # aHd1[++nHd1]="<font color=\"#A52A2A\"><b>Скрытые</b></font> авторы <u><i>отсутствуют</i></u>" # brown aHd1[++nHd1]="<i>Скрытые</i> авторы <u><i>отсутствуют</i></u>" # brown aHd1[++nHd1]="в \"<a href=/rating/hits/>Рейтинге по количеству посетителей</a>\"" aHd1[++nHd1]="<br><b>(~)</b>" aHd1[++nHd1]="<i>Новые</i> авторы/произведения отсутствовали в <i><u>предыдущем</u></i> рейтинге." # aHd1[++nHd1]="" # aHd1[++nHd1]="<br><b>(!) <font color=broun>Изменён приоритет</font></b>: теперь" # aHd1[++nHd1]="<i>место раздела</i> определяется <i>самым успешным произведением</i> в нём." # † массив строк шапки ТОЛЬКО у предпоследнего рейтинга if(!auUp)auUp=" --" # так красивше (чем унылый "0";) if(!curP)curP=" --" if(!upAu)upAu=" --" if(!curT)curT=" --" if(!upTx)upTx=" --" if(!auDn)auDn=" --" if(!oldP)oldP=" --" if(!dnAu)dnAu=" --" if(!oldT)oldT=" --" if(!dnTx)dnTx=" --" # † массив строк шапки краткой справки последнего рейтинга aTb1[++nTb1]="<hr>" aTb1[++nTb1]="" aTb1[++nTb1]="<table align=center border=1 cellspacing=0 cellpadding=2>" aTb1[++nTb1]="<tr align=center>" aTb1[++nTb1]="<td bgcolor="color[1]" colspan=\"6\">Краткая сводка + цвет некоторых" aTb1[++nTb1]="ячеек таблиц (<i>предыдущий рейтинг -" aTb1[++nTb1]="<a href=/"nUrl"/si_top6author-prev.shtml><b>"oDat"</b></a></i>)</td></tr>" # † массив строк шапки краткой справки ПРЕДпоследнего рейтинга aTb2[++nTb2]="<hr>" aTb2[++nTb2]="" aTb2[++nTb2]="<table align=center border=1 cellspacing=0 cellpadding=2>" aTb2[++nTb2]="<tr align=center>" aTb2[++nTb2]="<td bgcolor="color[1]" colspan=\"6\">Краткая сводка + цвет некоторых" aTb2[++nTb2]="ячеек таблиц (<i>предыдущий рейтинг - <b>"oDat"</b></i>, последующий" aTb2[++nTb2]="- <a href=/"nUrl"/si_top6author-curr.shtml><b>здесь</b></a>)</td></tr>" # † массив строк тела краткой справки общий aTbl[++nTbl]="<tr align=center bgcolor="color[0]">" aTbl[++nTbl]="<td colspan=3><b>Авторы</b> (разделы)</td>" aTbl[++nTbl]="<td rowspan=\"5\"></td>" aTbl[++nTbl]="<td colspan=2><b>Произведения</b> (лидеры)</td></tr>" if(auNw+nwTx){ aTbl[++nTbl]="<tr align=center>" if(auNw+length(a90)){ # если есть новое ИЛИ скрытое j0="<td bgcolor="color[12]">скрытые.<b>"length(a90)"</b></td>" j0=j0"<td bgcolor="color[5]" colspan=2>новые.<b>"auNw"</b></td>" # <td> </td> }else{ j0="<td colspan=3></td>" # иначе - пусто } aTbl[++nTbl]=j0 if(nwTx)aTbl[++nTbl]="<td bgcolor="color[5]" colspan=2>новые.<b>"nwTx"</b></td></tr>" else aTbl[++nTbl]="<td colspan=2></td></tr>" } aTbl[++nTbl]="<tr align=center bgcolor="color[1]">" aTbl[++nTbl]= "<td><b>N</b>(место), сдвиг</td>" aTbl[++nTbl]= "<td><b>Наполнение</b> стало</td>" aTbl[++nTbl]= "<td><b>Обновлялось</b></td>" aTbl[++nTbl]= "<td><b>Изменено</b></td>" aTbl[++nTbl]= "<td><b>Объём</b> стал</td>" aTbl[++nTbl]="</tr><tr align=center bgcolor="color[4]">" aTbl[++nTbl]= "<td>вверх.<b>" auUp"</b></td>" aTbl[++nTbl]= "<td>больше.<b>" upAu"</b></td>" aTbl[++nTbl]= "<td>намедни.<b>"curP"</b></td>" aTbl[++nTbl]= "<td>намедни.<b>"curT"</b></td>" aTbl[++nTbl]= "<td>больше.<b>" upTx"</b></td>" aTbl[++nTbl]="</tr><tr align=center>" aTbl[++nTbl]="<td bgcolor="color[3] ">вниз.<b>"auDn"</b></td>" aTbl[++nTbl]="<td bgcolor="color[3]">меньше.<b>"dnAu"</b></td>" aTbl[++nTbl]="<td bgcolor="color[11]">давно.<b>"oldP"</b></td>" aTbl[++nTbl]="<td bgcolor="color[11]">давно.<b>"oldT"</b></td>" aTbl[++nTbl]="<td bgcolor="color[3]">меньше.<b>"dnTx"</b></td>" aTbl[++nTbl]="</tr></table>" aTbl[++nTbl]="<table align=center border=0 cellspacing=0 cellpadding=2><tr>" aTbl[++nTbl]="<td>(</td>" aTbl[++nTbl]="<td bgcolor="color[11]"> <b><i>давно</i></b>" aTbl[++nTbl]="– больше <b>"tOld"</b> назад </td>" aTbl[++nTbl]="<td>)</td>" aTbl[++nTbl]="</tr></table>" aTbl[++nTbl]="<hr>" aTbl[++nTbl]="" aTbl[++nTbl]="<font size=\"-2\" face=monospace color="color[8]">" aTbl[++nTbl]=" /\\ /\\ <br>" aTbl[++nTbl]=" ·--·--·--· <br>" aTbl[++nTbl]=" \\/ <br>" aTbl[++nTbl]=" /\\ <br>" aTbl[++nTbl]=" ·--· <br></font>" # † титулы (названия) и рейтинга и его копии "Предыдущий" Ttl1="<center><font size=\"+2\">Рейтинг "rTyp"-"ancD"</font>" Ttl2="<center><font size=\"+2\">Предпоследний рейтинг "rTyp"-"ancD"</font>" aOut[++nOut]="<br>\"Самиздат\", самые посещаемые авторы" # (<i><b>намедни</b></i>) aOut[++nOut]="<table align=center border=0 cellspacing=0 cellpadding=2>" aOut[++nOut]="<tr bgcolor="color[4]">" # <td>(</td> if(gapD==1){ # sGap="намедни" aOut[++nOut]="<td> намедни: "dat_str(dBeg)" "yBeg" г.</td>" }else{ j0="с "dat_str(dBeg) if(yBeg!=rYea)j0=j0" "yBeg" г." j0=j0" по "dat_str(datJ,1)" " aOut[++nOut]="<td> за "sGap": "j0"</td>" } # if(dOff!="0.0")aOut[++nOut]="<td bgcolor="color[3]">(<i><u>нет данных</u> за: "dOff"</i>)</td>" aOut[++nOut]="</tr></table>" # aOut[++nOut]="(приложение к рейтингу <b>siTopTexts</b>-"ancD")" aOut[++nOut]="</center></blockquote>" bLin=mkCap() # шапка - первая (нулевая-с) строка таблиц lMax=tMax # всего строк в таблице for ( tIni=1; tIni<=lMax; tIni=tIni+tGap ) { aOut[++nOut]="<blockquote>" # начало очередной таблицы aOut[++nOut]="<table align=center border=1 cellspacing=0 cellpadding=2>" # навигация в aOut[++nOut]="<caption><a id=\""ancD ancW tIni"\"></a>"mkGoTo(tIni)"</caption>" # заголовке if(tIni==1)aOut[++nOut]=mkCap0() # шапка "ini" aOut[++nOut]=bLin # шапка таблицы tEnd=tIni+tGap for (tBeg=tIni;tBeg<tEnd;tBeg++) { if(tBeg<=lMax) mkTabLn(tBeg,tBeg) # строка данных в таблице } if ((tBeg-tMax)>0) aOut[++nOut]=bLin aOut[++nOut]="</table>" # таблица готова aOut[++nOut]="</blockquote>" # закрытие блока } aOut[++nOut]="<blockquote>" # подвал страницы aOut[++nOut]="<center>" mkGoTo(0) "</center>" # заголовке aOut[++nOut]="<ul>" aOut[++nOut]="<table border=0 cellspacing=0 cellpadding=2><tr>" # навигация в aOut[++nOut]="<td><b>Попутные сведения</b> (к "rTyp"-"ancD")" aOut[++nOut]="<td></tr></table>" aOut[++nOut]="<li>Последний <u>полный</u>" aOut[++nOut]="\"<a href=/rating/hits/index.shtml><i><b>Рейтинг" aOut[++nOut]="по количеству посетителей</b></i></a>\": за "hDat aOut[++nOut]="(от "dat_str(donH)")" aOut[++nOut]="<br>сравнивался с <i>предпоследним</i>: за "pDat aOut[++nOut]="(от "dat_str(preH)")." aOut[++nOut]="<li><i>Прочие</i> данные - по состоянию на "dat_str(hold)"." # if(txtM){ # aOut[++nOut]="<li>Разделы с <i>несколькими</i> (‡) лидерами: <b>"txtM"</b>." # } aOut[++nOut]="</ul>" aOut[++nOut]="<table align=center border=0 cellspacing=0 cellpadding=2>" # навигация в aOut[++nOut]="<tr><td>(copyleft "rYea"</td>" aOut[++nOut]="<td bgcolor="color[6]"><b>/\\/.\\/.\\/.</b></td><td>)</td></tr></table>" } function mkGoTo(lCur) { # сборка строки навигации для титула таблиц lBeg=1 # начало очередного интервала lEnd=lBeg+tGap-1 # и его конец if ((lEnd-lMax)>0) lEnd=lMax # но не выше общего конца sNav="<center>Интервал <b>N</b>: <b>" # начало строки навигации for(j0=1;j0<=lMax;j0++) { if (j0==lBeg) { # компоновка очередного элемента навигации if ((lBeg-1)>0) sNav=sNav " | " # первый разделитель опускаем if (lBeg==lCur) sNav=sNav "<big>" lBeg "-" lEnd "</big>" # это у своей таблицы, v-иначе else { sNav=sNav "<a title=\"Перейти к интервалу: " lBeg "-" lEnd "\" href=\"#" sNav=sNav ancD ancW j0"\">" lBeg "-" lEnd "</a>" # оформление как ссылка на ЯКОРЬ } lBeg=lEnd+1 # сдвинем границы на шаг tGap lEnd=lEnd+tGap if ((lEnd-lMax)>0) lEnd=lMax } } sNav=sNav"</b></center>" # завершение строки return(sNav) } function mkCap0() { # сборка доп.над.шапки (только для первой таблицы) tmp0= "<tr align=center bgcolor="color[0]">" tmp0=tmp0 "<td colspan=5>Самые посещаемые <b>разделы</b></td>" tmp0=tmp0 "<td bgcolor="color[1]" colspan=5>Самые посещаемые <b>произведения</b> /в этих разделах/</td>" return( tmp0 "</tr>" ) # шапка готова } function mkCap() { # сборка шапки таблиц tmp0= "<tr align=center bgcolor="color[flag]">" # шапки начало; v-место:хиты tmp0=tmp0 "<td bgcolor="color[6]" title=\"Местов списке, Хиты за сутки\"><b>N</b>: Успех</td>" tmp0=tmp0 "<td><a title=\"Раздел за 12мес: место, хиты\"><b>Автор</b></a></td>" # Автор tmp0=tmp0 "<td bgcolor="color[6]"><b>Девиз</b></a></td>" # Произведение tmp0=tmp0 "<td><small><b>Объём</b>/шт.</small></td>" tmp0=tmp0 "<td bgcolor="color[6]"><small><b>Обновлялось</b></small></td>" tmp0=tmp0 "<td title=\"Хиты за сутки\"><small><b>Успех</b></small></td>" tmp0=tmp0 "<td bgcolor="color[6]" title=\"Самый популярный в разделе\"><small><b>Лидер</b></small></td>" tmp0=tmp0 "<td><a title=\"Дата последнего изменения текста\"" # Создан +v tmp0=tmp0 "><small><b>Изменено</b></small></a></td>" # ^+ Создан tmp0=tmp0 "<td bgcolor="color[6]"><a title=\"Текст в килобайтах\"" # Объём +v tmp0=tmp0 "><small><b>Объём</b></small></a></td>" # ^+ Объём tmp0=tmp0 "<td><a title=\"Текста\"><small><b>Форма</b>: Жанр (жанры)</small></a></td>" # Форма: Жанр(ы) return( tmp0 "</tr>" ) # шапка готова } function mkTabLn(nLn,tLn) { # выдача строки номер nLn (строка исходного списка за номером tLn) flag=!flag # чередующаяся раскраска строк aOut[++nOut]="<tr "substr(nLn+1000,2)" align=center bgcolor="color[flag]">" # собираем строку... aOut[++nOut]="<td "a01[tLn]" title=\""a00[tLn]"\"><b>"nLn"</b>: "a14[tLn]"</td>" # Место(N): хиты if(a10[tLn] in a90)ownColor=" bgcolor="color[12] # "скрытый" автор /потеряшка/ 2023.07.08 else ownColor="" aOut[++nOut]="<td align=left"ownColor" title=\"место:"a12[tLn]", хиты:"a13[tLn]"\"><a href=/"a10[tLn]"/ id=\""ancA[tLn]"\">"a11[tLn]"</a></td>" aOut[++nOut]="<td"a03[tLn]"><i><font color=Maroon>"a15[tLn]"</font></i></td>" # Девиз aOut[++nOut]="<td"a02[tLn]" "a06[tLn]">"a16[tLn]"</td>" # Объём aOut[++nOut]="<td "a18[tLn]">"rusDat(a17[tLn])"</td>" # Обновлялось v-Успех aOut[++nOut]="<td><a href=/"a10[tLn]"/stat.shtml#"a20[tLn]".shtml id=\""a20[tLn]".shtml\">"a22[tLn]"</a></td>" if(a10[tLn]==nUrl)nvvColor=" title=\"это то, на что вы смотрите ;)\" bgcolor="color[10] else nvvColor="" # ^-моё? МОЁ! Моё... ;) aOut[++nOut]="<td"nvvColor" align=left><a href=/"a10[tLn]"/"a20[tLn]".shtml id=\""ancA[tLn]":"a20[tLn]"\">"a21[tLn]"</a></td>" aOut[++nOut]="<td"a34[tLn]">"rusDat(a31[tLn])"</td>" # Изменено ^-Лидер aOut[++nOut]="<td"a04[tLn]" align=right "a05[tLn]">"a32[tLn]"k</td>" # Объём aOut[++nOut]="<td>"a40[tLn]"</td>" # Форма: Жанр (жанры) aOut[++nOut]="</tr>" return # строку собрали, вываливаем! } # $1 $2 $3 $4 $5 $6 $7 $8 $9 $10 $11 $12 $13 $14 $15 $16 $17 $18 # Luck new hitP numP sizK sizN hitT txtN sizT datP endD id_P "namP" "moto" id_T "namT" "jnrT" fNam # 5527 0 218357 13 936 6 4937 1 7 2020.11.15 2020.08.31 z/zhan "Tony" "kjujdj•xbnfntkz" flibustain "Известные•мне•зеркала•Флибусты•и•Либрусека" "<a•href=/type/index_type_5-1.shtml>Статья</a>:" z~zhan { # загрузка исходного списка (с разборкой и оформлением значений, отображаемых в ячейках) if(match($1,/^[0-9]+$/)){ # признак - "строка основных данных" if($7-minT>=0){ # !!! успех раздела МОЖЕТ быть и ниже minT jj++ if($12 in a0a){ # раздел БЫЛ в старом списке j0=a0a[$12]-jj if(j0>0){ # auth, раздел съехал вверх auUp++ # auth, счётчик, раздел, сдвиг вверх a00[jj]="Сдвиг:"j0"-^" # auth, сдвиг () a01[jj]=" bgcolor="color[4] # auth, цвет фона () }else if(j0<0){ # auth, раздел съехал вниз auDn++ # auth, счётчик, раздел, сдвиг вниз a00[jj]="Сдвиг:"0-j0"-v" # auth, сдвиг () a01[jj]=" bgcolor="color[3] # auth, цвет фона () }else{ # auth, "на месте" a00[jj]="Сдвиг:0==" # auth, сдвиг () a01[jj]="" # auth, цвет фона () } }else{ # раздел в старом списке ОТСУТСТВУЕТ, оформляем "новьё" auNw++ # auth, счётчик, "новый" a00[jj]="Новый" # auth, сдвиг (новый) a01[jj]=" bgcolor="color[5] # auth, цвет фона (новый) } a14[jj]=sprintf("%2.1f",$1/10) # автор, "Успех" за цикл обновления статистик a10[jj]=$12 # автор, id_P - урл раздела (мой - n/nosow_w_w;) ancA[jj]=substr($12,1,1)"~"substr($12,3) # формат: "aChr~aNik" a11[jj]=unpack($13) # автор, namP - ФИО a12[jj]=$4 # автор, numP - позиция раздела в рейтинге посещаемости if(!a12[jj])a90[$12]++ # СКРЫТЫЙ раздел, учтём произведение из 2023.06.23 a13[jj]=$3 # автор, hitP - хиты раздела (в рейтинге посещаемости) a15[jj]=unpack($14) # "moto" if($2)a03[jj]=" title=\"создано намедни\" bgcolor="color[5] # new Author else a03[jj]="" a16[jj]="<b>"$5"</b>k/"$6 # a0k[aj[12]]=$5 # объём раздела в кбайтах # a0n[aj[12]]=$6 # наполнение в штуках ;) if($12 in a0a){ # раздел в старом списке БЫЛ, оформляем "разницу" if((a0k[$12]-$5<0)||(a0n[$12]-$6<0)){ upAu++ a02[jj]=" bgcolor="color[4] a06[jj]=" title=\"Наполнение стало больше\"" }else if((a0k[$12]-$5<0)||(a0n[$12]-$6<0)){ dnAu++ a02[jj]=" bgcolor="color[3] a06[jj]=" title=\"Наполнение стало меньше\"" } }else{ a02[jj]=" bgcolor="color[5] # auth, цвет фона (новый) a06[jj]=" title=\"Новый раздел\"" } a17[jj]=$10 # раздел, datP - дата "Обновлялось" # (разделы) выявим/отметим "свежак" и "старьё"... if(dBeg<=a17[jj]){ # "свежак" (с начала нашего интервала) a18[jj]=" title=\"обновлено намедни\" bgcolor="color[4] curP++ }else if(oldD>a17[jj]){ # "старьё" (год и более назад) a18[jj]=" title=\"обновлено давно\" bgcolor="color[11] oldP++ # счётчик "давно" }else a18[jj]="" # норма... a22[jj]=sprintf("%2.1f",$7/10) # текст, hitT - хиты текста (в статистике раздела) # if($8-1>0){ # число текстов-лидеров txtN в разделе >одного # txtM++ # a22[jj]=a22[jj]"‡" # } a20[jj]=$15 # текст, id_T - имя файла (без расширения .shtml) a21[jj]=unpack($16) # текст, namT - заголовок a31[jj]=$11 # текст, endD - дата последнего изменения # (лидеры) выявим/отметим "свежак" и "старьё"... if(dBeg<=a31[jj]){ # "свежак" (с начала нашего интервала) a34[jj]=" title=\"изменено намедни\" bgcolor="color[4] curT++ }else if(oldD>a31[jj]){ # "старьё" (год и более назад) a34[jj]=" title=\"изменено давно\" bgcolor="color[11] oldT++ # счётчик "давно" }else a34[jj]="" # $1 $2 $3 $4 $5 $6 $7 $8 $9 $10 $11 $12 $13 $14 $15 $16 $17 $18 # Luck new hitP numP sizK sizN hitT txtN sizT datP endD id_P "namP" "moto" id_T "namT" "jnrT" fNam # 5527 0 218357 13 936 6 4937 1 7 2020.11.15 2020.08.31 z/zhan "Tony" "kjujdj•xbnfntkz" flibustain "Известные•мне•зеркала•Флибусты•и•Либрусека" "<a•href=/type/index_type_5-1.shtml>Статья</a>:" z~zhan split($9,aq,".") a32[jj]=aq[1] # текст, sizT - объём в килобайтах a33[jj]=aq[2] # текст, sizB - "1"==объёмOk, "0"=="доступ ... ограничен" if($12 in a0a){ # раздел в старом списке БЫЛ, оформляем "разницу" if(a0t[$12]==$15){ # id_T (текста-лидера) был в старом j0=aq[1]-a0z[$12] if(j0>0){ upTx++ # объём+ текста a04[jj]=" bgcolor="color[4] a05[jj]=" title=\"+"j0"k\"" }else if(j0<0){ dnTx++ # объём- текста a04[jj]=" bgcolor="color[3] # 3 a05[jj]=" title=\""j0"k\"" } }else{ # это новый текст того же автора nwTx++ # новый текст a04[jj]=" bgcolor="color[5] a05[jj]=" title=\"New\"" } # a0t[aj[12]]=aj[15] # id_T (текста-лидера) # a0z[aj[12]]=aj[9] # объём текста } a40[jj]=unquot(unpack($17)) # текст, jnrT - жанр(ы) (может отсутствовать) # Жанр(ы) split(a40[jj],aq,":") # разделим форму и жано(ы) if(aq[2]=="") aq[2]="--" # два дефиса подряд смотрятся красивше (jnrT;) a40[jj]="<b>"aq[1]"</b>: "aq[2] } # else print(sprintf("%4s%4s",NR,$7),$12,$13,$15,$16)>"z.#" }else{ # /^;1aPre .+ hDat:20..\.(.+)\.(.+) hGap:([0-9]+)\..+ hPag:([0-9]+) .+ done:(20[\.0-9]+) /,aj)){ # pDat=aj[2]"/"aj[1] # за дата # preH=aj[5] # от дата # pPag=aj[4] # страниц aHits # /^;1aCur .+ hDat:20..\.(.+)\.(.+) hGap:([0-9]+)\..+ hPag:([0-9]+) .+ done:(20[\.0-9]+) /,aj)){ # hDat=aj[2]"/"aj[1] # donH=aj[5] # hPag=aj[4] # страниц aHits # hMax=aj[3] # хиты раздела-лидера aHits # /^;5H minL:([0-9]+) .+ txtM:([0-9]+) done:([\.0-9]+) /,aj)){ # minL=sprintf("%2.1f",aj[1]/10) # нижняя граница "успеха" в выборке # /^;5G .+ done:([\.0-9]+)\//,aj)){ # hold=aj[1] # дата сборки "yyyy.MM.dd" # ;1aPre hits 2:xNam 446:xNum 101267:xPas 2021.04.22:hDat 1018:hPag 801964:hMax 1009:pGet 2021.04.24:done gap1:14:43-15:04 # ;1aCur hits 2:xNam 445:xNum 101285:xPas 2021.04.22:hDat 1018:hPag 806772:hMax 1018:DnLd 2021.04.27:done 25:mins gapT~14:53-15:18~ # ;5G gapP 3:gapD 100:minL 758:gNum 2021.04.27:done 19:02 # ;5H gapT 100:minL 0:nulS 0:badS 0:nulP 0:badP 0:tNul 2:tBad 0:unAv 2:txtM 133:dnLd 2021.04.27:done 6:mins 20:10-20:16:gapT if(match($0,/^;1aPre .+ 20..\.(.+)\.(.+):hDat /,aj))pDat=aj[2]"/"aj[1] # pre дата aHits по СИ if(match($0,/^;1aPre .+ ([\.0-9]+):done /,aj)) preH=aj[1] # дата "скачан" (aHits) if(match($0,/^;1aPre .+ ([0-9]+):hPag /,aj)) pPag=aj[1] # страниц aHits if(match($0,/^;1aCur .+ 20..\.(.+)\.(.+):hDat /,aj))hDat=aj[2]"/"aj[1] # дата aHits по СИ if(match($0,/^;1aCur .+ ([\.0-9]+):done /,aj)) donH=aj[1] # дата "скачан" (aHits) if(match($0,/^;1aCur .+ ([0-9]+):hPag /,aj)) hPag=aj[1] # страниц aHits if(match($0,/^;1aCur .+ ([0-9]+):hMax /,aj)) hMax=aj[1] # хиты раздела-лидера aHits # if(match($0,/^;5G .+ ([0-9]+):minL / ,aj)) minL=sprintf("%2.1f",aj[1]/10) # minLuckP if(match($0,/^;5H .+ ([\.0-9]+):done /,aj)) hold=aj[1] # дата "расчёт" ancD=substr(hold,3,2) substr(hold,6,2) substr(hold,9,2) # дата сборки "yyMMdd" } } function dat_str(d0,d2) { # "2020.05.23" -> "23 мая" (d2==nul) or "23 мая 2020 г." (d2!=nul) d1=split(d0,ad,".") if(!d2)return("<b>"ad[3]+0" "nMth[ad[2]+0]"</b>") else return("<b>"ad[3]+0" "nMth[ad[2]+0]"</b> "ad[1]" г.") } function rusDat(s0) { # 2019.19.25 -> 25.19.2019 split(s0,aq,".") return(aq[3]"."aq[2]"."aq[1]) } function unpack(j1) { # восстановление литерала, свёрнутого при сборе сведений с СИ if (substr(j1,1,1)=="\"") j1=substr(j1,2,length(j1)-2) # откусим обрамляющие двойные кавычки j2="" # "•" -> пробел while(n=index(j1,"•")) { j2 = j2 substr( j1, 1, n-1 ) " "; j1 = substr( j1, n+1 ) } j1=j2 j1 j2="" # "”" -> двойные кавычки while(n=index(j1,"”")) { j2 = j2 substr( j1, 1, n-1 ) """; j1 = substr( j1, n+1 ) } j1=j2 j1 return( j1 ) } function unquot(j1) { # восстановление литерала "жанр(ы), свёрнутого при сборе сведений с СИ j2="" # '"' -> '"' while(n=index(j1,""")) { j2 = j2 substr( j1, 1, n-1 ) "\""; j1 = substr( j1, n+6 ) } j1=j2 j1 return( j1 ) } END{ # данные загружены и разобраны, оформляем рейтинг и приложения... if(!(1 in ARGV)){ print "NO input file!" # защита от случайного пуска exit -1 } if(hold=="") { print "NO date to bind siTopAuthors" exit -1 } # if(pDat==-1)aVar["pDat"]=1 # pre дата aHits по СИ # if(preH==-1)aVar["preH"]=1 # pre дата "скачан" (aHits) # if(pPag==-1)aVar["pPag"]=1 # pre страниц aHits # if(hDat==-1)aVar["hDat"]=1 # дата aHits по СИ # if(donH==-1)aVar["donH"]=1 # дата "скачан" (aHits) # if(hPag==-1)aVar["hPag"]=1 # страниц aHits # if(hMax==-1)aVar["hMax"]=1 # хиты раздела-лидера aHits # if(minL==-1)aVar["minL"]=1 # минимальная "удача" раздела # if(hold==-1)aVar["hold"]=1 # дата "расчёт" # if(j0=length(aVar)){ # tmp0="? no var(s):" # for(j1 in aVar)tmp0=tmp0" "j1 # print(tmp0" in "FILENAME) # exit -1 # } # print("-*-") tMax=jj if(500-tMax>=0)tGap=50 if(250-tMax>=0)tGap=25 mkPage() print("<blockquote>") >fOut print(info) >fOut # служебная отметка (для порядку) if(nHnY)for(jj=1;jj<=nHnY;jj++)print(aHnY[jj]) >fOut for(jj=1;jj<=nHdr;jj++)print(aHdr[jj]) >fOut for(jj=1;jj<=nHd1;jj++)print(aHd1[jj]) >fOut for(jj=1;jj<=nTb1;jj++)print(aTb1[jj]) >fOut for(jj=1;jj<=nTbl;jj++)print(aTbl[jj]) >fOut print(Ttl1) >fOut for(jj=1;jj<=nOut;jj++)print(aOut[jj]) >fOut print(info) >fOut # служебная отметка (для порядку) printf("%s","</blockquote>") >fOut print("<blockquote>") >fPre print(inf2) >fPre if(nHnY)for(jj=1;jj<=nHnY;jj++)print(aHnY[jj]) >fPre for(jj=1;jj<=nHdr;jj++)print(aHdr[jj]) >fPre for(jj=1;jj<=nHd2;jj++)print(aHd2[jj]) >fPre for(jj=1;jj<=nTb2;jj++)print(aTb2[jj]) >fPre for(jj=1;jj<=nTbl;jj++)print(aTbl[jj]) >fPre print(Ttl2) >fPre for(jj=1;jj<=nOut;jj++)print(aOut[jj]) >fPre print(inf2) >fPre printf("%s","</blockquote>") >fPre endS=mktime(substr(hold,1,4)" "substr(hold,6,2)" "substr(hold,9,2)" 00 00 00") # seconds "до" print "--- " strftime("%H:%M:%S") " Ends..." # закончили работу (оживляж;) # 2020.11.29, nvv, creation by siTop-fHtml.awk (2020.11.18) # 2020.12.03, nvv, it works! (off line, alas) # 2021.01.11, nvv, it works ok... ;) пока без опорного предыдущего списка # 2021.01.29, nvv, всё запланированное обустроено, включая 2 и более лидеров в разделе ("‡") # 2021.02.06, nvv, отключена отладочная выдача в "z.#" отвергнуты записей с низкими хитами # + уточнен сбор данных по призёрам предыдущего приложения (именно его призёры, # но не присутствовавшие лишь в прошлом ОБЩЕМ списке) # 2021.03.11, nvv, мелкая неточность вычленения даты предыдущего списка + косметика # 2021.03.21, nvv, new text color+title added # 2021.04.24, nvv, new text color+title off # 2021.06.10, nvv, мелкая косметика # 2021.07.09, nvv, исправлена неточность в маркировке цветом текстов-лидеров # 2022.01.13, nvv, исправлена неточность в выявлении новогоднего периода # 2022.06.07, nvv, мелочёвка # 2022.10.19, nvv, в шапку добавлена ссылка на текст: "Регистрация в СИ"" # 2022.12.01, nvv, текст: "Регистрация в СИ" перестал быть New # 2023.07.08, nvv, добавоена поддержка скрытых разделов место "0" /numP/ в рейтинге по хитам # + хоть это и приложение к siTopTexts, но таки тоже рейтинг, что теперь явно сказано в заголовке # 2023.08.02, nvv, убран анонс скрытых разделов # 2024.03.09, nvv, изменился рисунок работы СИ - изменено оформление шапки siTopAuthors # 2024.02.07, nvv, добавлена отметка "Upd" для: "Исходные тексты скриптов" # 2024.08.19, nvv, """ -> "·" }
Имя файла скрипта: "iNetR.cmd" V-текст скрипта-V- - - - - - - - - @if not defined nJob @echo off echo %date% %time:~0,8% %~nx0 Begs :: iNetR.cmd - оформление в HTML списка топовых разделов прошедшего цикла обновления статистик :: + 20??.??.??.*.gAuth (like 2021.05.19.6.gAuth) - оформляемый последний список :: + 20??.??.??.*.gAuth (like 2021.05.14.3.gAuth) - оформляемый ПРЕД последний список :: проверить-найти: :: - свежий *.gAuth, например: 2021.04.27.4.gAuth :: - старый *.gAuth, например: 2021.04.24.3.gAuth :: - свежий *.gAuth.html, например: 2021.04.27.4.gAuth.html :: - старый *.gAuth.html, например: 2021.04.24.3.z.gAuth.html :: 2021.05.29, nvv, creation на основе fHtml.cmd от 2021.05.25 :: 2021.06.13, nvv, confirmation to move PREV data off set nJob=iNetR if NOT defined jDat set jDat=%date% set ok2upDt=%1 set aHtm=%~dp0%nJob%.awk :: wDir - общее рабочее место set wDir=%~d0\Jobs :: sDir - общее складское хранилище set sDir=%~d0\Stor :: dDir - склад для уже ненужных списков 20??.??.??.gAuth set dDir=%sDir%\Text\zOld.gAuths if NOT exist %dDir% set errInf=NO %dDir% found & goto nExit :: hDir - склад под выходные файлы с таблицами *.html set hDir=%sDir%\Html set pDir=%hDir%\gAuths if NOT exist %hDir%\ mkDir %hDir% if errorLevel 1 set errInf=fail mkDir %hDir% & goto nExit :: fOld - прошлый опорный список для "siTopTexts" set fOld= :: fCur - свежий список для "siTopTexts" - 1k популярных текстов (со всеми атрибутами) set fCur= for %%A in (%wDir%\20??.??.??.*.gAuth) do call :findCurOld %%A if NOT defined fOld set errInf=!? NO old 20*.gAuth found & goto nExit if defined errInf goto nExit set fHtm=%hDir%\%dCur%.%gCur%.gAuth.html echo prev:%fOld% echo curr:%fCur% echo fHtm:%fHtm% if NOT exist %fHtm% goto mkHtm :: итоговый файл есть. если нужно прибрать - идём прибирать, иначе выясняем... if defined ok2upDt goto upDt :: запрос (конечный HTML уже есть!) set tmp0= echo fHtm found; reBuild it? [yes] == y set /p tmp0=?[no]? if /i NOT %tmp0%. == y. ( echo job canceled {NO to reBuild} exit ) :mkHtm собственно оформлялка ("от и до";) gawk.exe -f %aHtm% %fCur% if errorLevel 1 set errInf=!!! X someThing's wrong with %~n0.awk & goto nExit :: блокируется оптичивание преобразованного в HTML goto nExit :upDt запрос (точно ненада?) set tmp0= echo confirm PREV data OFF? [yes] == y set /p tmp0=?[no]? if /i NOT %tmp0%. == y. ( echo job canceled {NO to reBuild} exit ) :: уберём уже ненужный старый список рейтинга на склад Text\zOld.gAuths if exist %fOld% ( echo move %fOld% to %dDir% move /Y %fOld% %dDir% if errorLevel 1 set errInf=!! fail to move old *.gAuth to %dDir% & goto nExit ) :: опубликованный %dCur%.gAuth.html (убрать) set tmp0=%hDir%\%dCur%.%gCur%.gAuth.html if exist %tmp0% ( echo move %tmp0% to %pDir% move /Y %tmp0% %pDir% if errorLevel 1 set errInf=!! fail to move %tmp0% to %pDir% & goto nExit ) :: опубликованный %dOld%.%gOld%.gAuth.z.html ("предыдущее" удалить) set tmp0=%hDir%\%dOld%.%gOld%.gAuth.z.html if exist %tmp0% ( echo erase %tmp0% erase %tmp0% if errorLevel 1 set errInf=!! fail to erase %tmp0% & goto nExit ) :nExit if defined errInf ( echo ! %errInf% set errInf= ) echo %date% %time:~0,8% Job:%nJob% Ends goto :eof :findCurOld :: dOld dCur - даты в именах файлов опорного и текущего списков if defined fOld if defined fCur set errInf=too many *.gAuth files in %wDir% & goto :eof set fOld=%fCur% set gOld=%gCur% set dOld=%dCur% set fCur=%1 set dCur=%~n1 set gCur=%dCur:~11% set dCur=%dCur:~0,10% goto :eof
Имя файла скрипта: "zChk.cmd" V-текст скрипта-V- - - - - - - - - @if NOT defined pJob echo off :: nJob - ID процесса и связанных с оным файлов set nJob=zChk :: itog - непустой == файл для загрузки в me по успеху set itog= echo %date% %time:~0,8% %nJob% Begs :: zChk.cmd - утренние основные проверки ситуации в СИ :: проверяется: :: 1j - вчерашний расчёт прибран? нет == выход :: 0j - доступ: zhurnal.lib samlib budclub /siUrl - последний ОК/ :: 2j + свежая статистика nvv: есть - выход /на сегодня всё сделано/ :: 3j + свежий /за вчера/ лог СИ: есть - запрос статистик :: 4j + свежая отметка в протокол: доступ к СИ: есть - скачивание логов/статистик :: 5j + проверка статуса: inSpam и inBan -} отметка в протокол :: 6j -+ после 07:05 проверячется наличие локально вчерашнего лога /нет - скачивается/ :: 7j --+ ожидание появления статистики Tony z/zhan :: ! с любым параметром скачивается на скорость 30MB с этих сайтов и ВЫХОД :: 2024.08.09, nvv, zIniChk.cmd - zChk.cmd + работа в пакетном режиме :: прочая история - в подвале :: 0j А не забыл ли я обиходить прошедщий намедни расчёт? call :chkOld set jDat=%date% :: jDay - день месяца "сегодня" set jDay=%jDat:~-2% set errInf= set wGetSiz=1 :: 0j - доступ: zhurnal.lib samlib budclub /siUrl - последний ОК/ set wDir=\Jobs\ if NOT exist %wDir%*.* ( mkDir %wDir% if errorLevel 1 echo fail mkDir %wDir% & exit ) :: wFil - рабочаа времянка set wFil=%wDir%%nJob%.tmp :: xMin - пауза между проверками обновления статистики Tony z/zhan set xMin=5 :: siUrl - рабочий из zhurnal.lib, samlib или budclub set siUrl= rem i/iw ... примерно 30Mb статистики rem n/nosow_w_w ... примерно 50kb статистики set urlT=n/nosow_w_w if NOT %1. == . set urlT=i/iw set wLin= set siNum=0 echo %time:~0,8%~%jDat% si Urls Checks... call :chkRate zhurnal.lib %urlT% if defined urlW set siUrl=%urlW% call :chkRate samlib %urlT% if defined urlW set siUrl=%urlW% call :chkRate budclub %urlT% if defined urlW set siUrl=%urlW% set wLin=%time:~0,8%%wLin% if NOT %1. == . exit :: нет доступа ни к одноу сайту СИ if NOT defined siUrl set errInf=NO siUrls available & exit echo siUrl=%siUrl% :: 2j nDir - склад для накопления nvv.stats /должен быть/ set nDir=\Stor\nvv\ if NOT exist %nDir%*.* ( mkDir %nDir% if errorLevel 1 echo fail mkDir %nDir% & exit ) :: nSuf - файл статистики nvv /общая часть/ set nSuf=n~nosow_w_w.stat.htm :: nFil - последний наличный файл статистики nvv :: nDat - дата -^- в формате "YYYY.mm.dd" /like: "2022.08.03"/ set nDat= for %%A in (%nDir%*.%nSuf%) do ( set nFil=%%A set nDat=%%~tA ) if NOT defined nDat goto doLogChk set nDat=%nDat:~0,10% :: и обрадуем наблюдателя касаемо if %nDat% == %jDat% ( echo nvv.stat now: %nDat% goto :eof ) echo nvv.stat old: %nDat% :doLogChk 3j логи СИ вычислим год, месяц и день для "вчера" for /F "tokens=1-9*" %%A in ( 'gawk "BEGIN{print(strftime(\"%%Y %%m %%d\",systime()-86400));exit}"' ) do (set Year=%%A&set Mnth=%%B&set mDay=%%C) :: логи СИ группируютя по годам в отдельные папки set lDir=Q:\#-Logs\%Year%\ if NOT exist %lDir%*.* ( mkDir %lDir% if errorLevel 1 echo fail mkDir %lDir% & exit ) set lFil=%lDir%%Mnth%-%mDay%.log :: если этот лог уже у нас - значит осталась только статистика if exist %lFil% ( echo. == ok %lFil% goto doStats ) :: 4j рабочвя папка, свежая отметка в протокол: доступ к СИ: есть - скачивание логов/статистик :: logI - лог проверок IP set logI=%wDir%%nJob%.log :: logD - дата лога проверок IP - для организации в одну строку всех записей за день set logD= for %%A in (%logI%) do set logD=%%~tA if NOT defined logD goto doIpChk if NOT %jDat% == %logD:~0,10% goto doIpChk echo. == ok %lFil% goto iniChkDon :doIpChk 5j + проверка статуса: inSpam и inBan -} отметка в протокол rem батник для проверки своего статуса "спамер"/"забанен" в СИ: rem ::: http://budclub.ru/cgi-bin/ip_ban_check rem окультуренный итог выдаётся на экран и в одноимённый лог рядом с батником :: 2024.08.09~07:39 myIp:109.110.47.111 - NO.inSpam - NO.inBan 224_KB/s_zhurnal.lib 238_KB/s_samlib 237_KB/s_budclub set tmp0=0 set IpErr=0 for /F "tokens=*" %%J in ( ' wGet -q http://%siUrl%/cgi-bin/ip_ban_check -O- ' ) do call :getLn %%J if errorLevel 1 echo wGet: %siUrl% ERR %errorLevel% & exit set tmp0=%time:~0,5% if %tmp0:~0,1%. == . set tmp0=0%tmp0:~1% set tmp0=%date%~%tmp0% myIp:%myIp% echo %tmp0% IpErr.%IpErr% gAwk.exe "BEGIN{printf(\"%tmp0% %wLin:~8%\n\");exit}" >> %logI% rem echo %date%~%tmp0% myIp:%myIp% >> %logI% if %IpErr%. == 0. goto iniChkDon :: у нас проблемы... Таки продолжим? set tmp0= echo my IP in troubles, ignore them? [yes] == y set /p tmp0=?[no]? if /i NOT %tmp0%. == y. ( echo job canceled exit ) :: 6j -+ после 07:05 проверячется наличие локально вчерашнего лога /нет - скачивается/ :: 7j --+ ожидание появления статистики Tony z/zhan :iniChkDon tBeg - граница ожидания {+ 0..5 секунды} ДО {в п/п waitTill в формате "чч:мм"} set tBeg=07:05 call :waitTill %jDat%~%tBeg% :: вчерашний лог в СИ set wUrl=%siUrl%/logs/%Year%/%Mnth%-%mDay%.log :: оживляж echo. ? req %Year%/%Mnth%-%mDay%.log call wGetUrl2fil.cmd %wUrl% %lFil% >nul if defined errInf goto nExit if %wGetSiz% == 0 ( erase %lFil% set errInf=ZERO-size: %lFil% goto nExit ) :: ну и дату лога вструмить след: touch.exe -t YYYYmmdd1200 "fNam" touch.exe -t %Year%%Mnth%%mDay%1200 %lFil% :doStats утренниние проверки оптичены, ждём обновления статистики Tony set wUrl=http://%siUrl%/z/zhan/stat.shtml :again if exist %wFil% erase %wFil% wGet.exe %wUrl% -t2 -O%wFil% > nul 2>&1 if NOT %errorLevel% == 0 set errInf=NO web now & goto nExit call :getStatDay %wFil% if defined errInf goto nExit if %wDay% == %jDay% goto zhanOk if %time:~1,5% GEQ 7:50 set xMin=1 rem echo.%time:~1,5% now.%jDay% Tony.%wDay% xMin.%xMin% call :waitMins %xMin% goto again :zhanOk теперь статистика nvv... echo now.%jDay% Tony.%wDay% stat upDated :: если сегодняшняя статистика nvv уже у нас, завершаем... if %nDat% == %jDat% goto nvvOK set wUrl=http://%siUrl%/n/nosow_w_w/stat.shtml if exist %wFil% erase %wFil% wGet.exe %wUrl% -t2 -O%wFil% > nul 2>&1 if NOT %errorLevel% == 0 set errInf=NO web now & goto nExit call :getStatDay %wFil% if defined errInf goto nExit if NOT %wDay% == %jDay% set errInf=NO toDay's nvvStat & goto nExit set nFil=%nDir%%jDat%.%nSuf% copy /b %wFil% %nFil% >nul if NOT %errorLevel% == 0 set errInf=fail copy %wFil% %nFil%& goto nExit :nvvOK echo nvv.stat OK :nExit if defined errInf echo %errInf% goto :eof :getStatDay stat2check rem <li><i>Статистика рассчитывается раз в сутки. (Thu May 18 02:05:32 2023)</i> set wDay= for /F "tokens=1-9,*" %%A in ( 'gawk.exe "{if(match($0,/<li><i>.+\. \(... (...) (..) ..:..:.. (20..)\)<\/i>/,a)){print(a[3],a[1],a[2]);exit}}" %1' ) do set wDay=%%C if NOT defined wDay set errInf=BAD stat: %1 & goto :eof if %wDay% LEQ 9 set wDay=0%wDay% goto :eof :getLn %%J set /a tmp0+=1 set tmp1=%6 set tmp1=%tmp1:~1% if %tmp0% == 1 set myIp=%3 if %tmp0% == 2 ( if '%tmp1%' == 'not' ( set myIp=%myIp% - NO.inSpam ) else ( set myIp=%myIp% ! IS.inSpam set /a IpErr+=1 ) ) if %tmp0% == 3 ( if '%2' == 'эх' ( set myIp=%myIp% - NO.inBan ) else ( set myIp=%myIp% ! IS.inBan set /a IpErr+=2 ) ) goto :eof rem 15:37:12 55_zhurnal.lib 58_samlib 56_budclub :chkRate siUrl id_P п/п определения времени скачивания i/iw.stat.shtml в зависимости о урл-а :: страница для тестового скачивания - set /a siNum+=1 gawk.exe "BEGIN{printf(\"check-%siNum%... \");exit}" set wUrl=http://%1.ru/%2/stat.shtml wGet.exe %wUrl% -O- -t2 -o%wFil% >nul if NOT %errorLevel% == 0 goto errU :: всё ОК, вычленим время скачивания set urlW= for /F "tokens=*" %%J in ( ' gAwk.exe "{if(match($0,/ \(([0-9]+) (.+)\)/,a))print(a[1]\"_\"a[2])}" %wFil% ' ) do set urlW=%%J erase %wFil% :: годный домен echo %urlW% %1 :: для отчёта set wLin=%wLin% %urlW%_%1 set urlW=%1.ru goto :eof :errU скачивание провалилось, уберём за собой if exist %wFil% erase %wFil% set urlW= -_%1 set wLin=%wLin% -_%1 echo %urlW% set urlW= goto :eof :chkOld А не забыл ли я обиходить прошедщий намедни расчёт? set jClA=0 set jClT=0 :: должно быть for %%A in (U:\Jobs\20??.??.??.dText) do set /a jClT=1 for %%A in (U:\Jobs\20??.??.??.*.gAuth) do set /a jClA+=1 if %jClT%%jClA% == 11 goto :eof echo dText.%jClT% gAuth.%jClA% exit exit ======= комплект п/п для обустройства заданных ожиданий в CMD :waitMins minutes [с новой строки] ожидание заданное число минут if NOT %2. == . echo. :: jSec - UNIX-секунд в момент ВЫЗОВА п/п :: tics - UNIX-секунд до момента ЗАВЕРШЕНИЯ ожидания: tics-jSec - время нашего ожидания :: jTim - этот момент -^- в формате "HH:MM:SS" for /F "tokens=1-9,*" %%W in ( ' gawk.exe "BEGIN{t=systime();b=%1*60+t;print(t,b,strftime(\"%%H:%%M:%%S\",b-t,1));exit}"' ) do ( set jSec=%%W set tics=%%X set jTim=%%Y ) if %tics% == -1 echo %~nx0, bad [%1] {%waitTill%} for sub:waitTill :: а ждать-то может и поздно уже?... if %jSec% GEQ %tics% goto :eof :: нет, обрадуем и побежали ждать gawk.exe "BEGIN{print(\"now.%jDay% Tony.%wDay% xMin.%xMin% -- waiting \"strftime(\"%%M:%%S\",%tics%-systime(),1)\" unTill\",strftime(\"%%H:%%M:%%S\",%tics%));exit}" :: ждём, известив о waitTill set curM=0 goto sleep6 :: ждать ДО.123456789.123456789. :waitTill гггг.мм.дд~чч:мм [с новой строки] с оживляжем до заданного момента /%1 == / if NOT %2. == . echo. set curM=%1 :: waitTill - этого момента 2024.03.10~15:57 set waitTill=%curM:~0,4% %curM:~5,2% %curM:~8,2% %curM:~11,2% %curM:~14,2% 00 for /F "tokens=1-9,*" %%W in ( ' gawk.exe "BEGIN{t=systime();b=mktime(\"%waitTill%\");print(t,b,strftime(\"%%H:%%M:%%S\",b-t,1));exit}"' ) do ( set jSec=%%W set tics=%%X set jTim=%%Y ) if %tics% == -1 echo %~nx0, bad [%1] {%waitTill%} for sub:waitTill :: а ждать-то может и поздно уже?... if %jSec% GEQ %tics% goto :eof :: нет, обрадуем и побежали ждать gawk.exe "BEGIN{print(\" -- waiting \"strftime(\"%%M:%%S\",%tics%-systime(),1)\" unTill\",strftime(\"%%H:%%M:%%S\",%tics%));exit}" :: ждём, известив о waitTill set curM=0 goto sleep6 :ticShow оживляж - это наше всё gawk.exe "BEGIN{if(%curM%==%preM%){printf(\".\")}else{printf(%curM%)}exit}" :: строка терминируется 10-й минутой /"0"/ if %curM% == 0 if NOT %curM% == %preM% echo. %curT% :: проверка истечения заданного срока; "да"==вЫход if %curS% GEQ %tics% echo. %curT% & goto :eof :sleep6 шаг задержки - 6 секунд sleep 6 :: рабочая фиксация очередного момента call :ticSet goto ticShow :ticSet запомним старое значение момента времени относительно начального /jSec/ set preM=%curM% for /f "tokens=1-9,*" %%P in ( ' gawk.exe "BEGIN{t=systime();print(t,strftime(\"%%H:%%M:%%S %%M\",t-%jSec%,1));exit}" ' ) do ( set curS=%%P set curT=%%Q set curM=%%R ) set curT=+%curT:~1% :: и текущее /новое/ значение минут /последняя цифра/ set curM=%curM:~1% goto :eof :: 2024.03.17, nvv, созданно на основе zSchk.cmd и siLogs.cmd :: 2024.03.21, nvv, до 07:50 пауза 5 минут в проверке обновления z/zhan, после - 1 минута :: 2024.04.06, nvv, в конце - тестовое скачивание 30 Mb /скорость канала/ :: 2024.04.20, nvv, существенное улучшение логики и интерфейса :: 2024.05.22, nvv, улучшение вида записей в логе: все записи задень в одной строке этого дня :: + под занавес /после запуска показа статистики nvv/ тестируется скорость скачивания 30 mb :: 2024.06.10, nvv, мелкая прака интерфейса :: 2024.06.19, nvv, уточнена реакция на проблемы с доступом к домену /budclub, в частности/ :: 2024.08.01, nvv, скачивание большого файла только по параметру при запуске
Имя файла скрипта: "wGetUrl2fil.cmd" V-текст скрипта-V- - - - - - - - - @if not defined nJob @echo off :: установленная переменная nJob (вызов из "моего" батника) блокирует команду echo off set nReV=2.23, 2024.03.07 if NOT %2.==. goto nStart :nHelp echo CmdName: %~nx0 (wGetUrl2fil.cmd) echo Usage: . %~nx0 iNetUrl_to_downLoad File_for_DL-ed [cmdLog] echo Example: %~nx0 %siUrl%/n/nosow_w_w n-nosow_w_w.idx.html echo Example: %~nx0 %siUrl%/ siTitle.idx.html my.log echo Created: 2018.09.19 echo Author : NVV (Vladislav Nosov) echo nReV: %nReV% echo. echo Description: ФУНКЦИЯ скачивания файла из интернета в локальный файл echo Третий, НЕобязательный ключ задаёт лог +режим отладки для wGet.exe echo ^^-без, - режим "всё молча" (для всего) echo. echo NB#1. ! В месте размещения юзается времянка %~n0.tmp echo NB#2. В %%wGetErr%% код ошибки: 0==Ок, 1==no_DL_файла, 3==NO_СИ echo + В %%wGetSiz%% - размер DL_файла (File_for_DL) == 0, если оного нет echo. echo При возникновении проблемы выставляется ErrorLevel 1, echo описание проблемы помещается в переменную среды %%errInf%% echo. set errInf=It's HELP (params: %*) :nErrExit set errInf=! Error in %~nx0:%errInf% if NOT defined nJob echo %errInf% exit /b 1 2019.01.14 11:03, nvv, оптимизация алгоритма; по мелочам, но много где... 2019.11.29, nvv, samlib.ru budclub.ru - основной и альтернативный адреса "Самиздата" 2020.01.06, nvv, in errInf "iNet unavailable" reqURL added 2020.03.22, nvv, вместо титула моего раздела проверяется доступность логов СИ (/logs/) 2020.11.13, nvv, будКлуб - глупость 2021.04.27, nvv, ^-не факт + добавлен инкремент внешнего счётчика DnLd при успехе 2021.05.09, nvv, инкремент по-любому (если без ошибок) отсутствие файла по адресу - не ошибка! 2023.06.03, nvv, обустроена работа с wGetErr /см. nHelp/ 2024.03.03, nvv, новации в СИ: урл "%siUrl%/logs" ДОЛЖЕН иметь "/" в конце, иначе НЕТУ! + аварийное сообщение выдаётся при вызове НЕ из CMD /пуста переменная nJob/ 2024.03.07, nvv, добавлен ключ --no-cache 2024.06.16, nvv, добавлен ключ -t2 - до двух попыток попробовать при проблеме :nStart if NOT defined siUrl set siUrl=samlib.ru if NOT defined wKey set wKey=-U "Mozilla/5.0" --no-cache -t2 if NOT defined wTim0 set wTim0=%time% if NOT defined wTim2 set wTim2=%time% set wGetLog=%3 if defined wGetLog echo {sub} %~nx0 [%*] :: если заказанное уже у нас, пропускаем (с отметкой) if NOT exist %2 goto wait0 for %%W in (%2) do set wGetSiz=%%~zW if defined wGetLog echo == Ok, done already, size=%wGetSiz% goto :eof :wait0 set errInf=wGet.exe -q %wKey% %1 -O %2 if defined wGetLog ( set errInf=wGet.exe %wKey% -d %1 -O %2 -a %3 echo ? %errInf% ) :wait1 организация паузы (секунда) на запрос к СИ if "%wTim0%" GTR "%time%" goto gogo1 if "%wTim2%" GTR "%time%" goto wait1 :gogo1 call :wTim1sec "взвести таймер" :: собственно скачивание заказанного... %errInf% set wGetErr=%errorLevel% for %%W in (%2) do set wGetSiz=%%~zW if defined wGetLog echo ~~~ wGetErr=%wGetErr%, size=%wGetSiz% if %wGetErr% GTR 0 goto chkSi set errInf= rem set wGetErr= :: увеличим счётчик фактов скачиваний set /a DnLd+=1 goto :eof коды, которые возвращает wget и пояснения к ним. 0 - ошибок нет 1 - ошибка кода общего характера (generic error code) 2 - ошибка разрбора (parse error) при аналие опций командной строки и/или .wgetrc или .netrc 3 - ошибка файлового ввода/вывода 4 - ошибка сети 5 - ошибка проверки SSL 6 - ошибка аутентификации (неверное имя или пароль) 7 - ошибка протокола 8 - сервер при ответе выдал какую-либо ошибку :chkSi какие-то проблемы..., а Самиздат-то жив? set errInf=wGet.exe %wKey% -q %siUrl%/logs/ -O- if defined wGetLog ( echo ? %errInf% to- nul set errInf=wGet.exe %wKey% -d -a %3 %siUrl%/logs/ -O- ) rem echo err.%wGetErr% %wGetLog% %errInf% :wait2 организация паузы (секунда) на запрос к СИ if "%wTim0%" GTR "%time%" goto gogo2 if "%wTim2%" GTR "%time%" goto wait2 :gogo2 скачать требуемое не удалось, глянем заведомо существующее call :wTim1sec "взвести таймер" %errInf% > nul set wGetChk=%errorLevel% if defined wGetLog echo ~~~ wGetChk=%wGetChk% if %wGetChk% == 0 ( set errInf= set wGetErr=1 if defined wGetLog echo x is gone=%1 & goto :eof if NOT defined nLob echo x is gone=%1 goto :eof ) set wGetErr=3 if exist %2 erase %2 set errInf=%1 is unavailable now... goto nErrExit :wTim1sec {sub} взведение таймера на 1 секунду :: time is like 13:18:24.21 !!! НЕ использовать на ГРАНИЦЕ суток! set wTim0=%wTim2% set wTim2=%time% :: час требует доп.плясок, т.к. при часе <10 в %time% лидирует пробел, а НЕ ноль ("0") set /a wHou=100+%wTim2:~0,2% :: CMD чудит на числа с лидирующими нулями... ;( set wMin=1%wTim2:~3,2% set wSec=1%wTim2:~6,2% set /a wSec+=1 if %wSec% GTR 159 ( set /a wSec-=60 set /a wMin+=1 ) if %wMin% GTR 159 ( set /a wMin-=60 set /a wHou+=1 ) :: для часа пробел -v- если <10 (в %time% лидирует пробел {" "}, а НЕ ноль {"0"}) if %wHou% LEQ 109 (set wHou= %wHou:~-1%) else (set wHou=%wHou:~-2%) :: соберём время == текущий момент + 1 секунда set wTim2=%wHou%:%wMin:~-2%:%wSec:~-2%%wTim2:~-3% goto :eof
(copyleft 2024 | /\/.\/.\/. | ) |
|
Новые книги авторов СИ, вышедшие из печати:
О.Болдырева "Крадуш. Чужие души"
М.Николаев "Вторжение на Землю"