Влад : другие произведения.

Комплект скриптов "для сборки sitoptexts"

Самиздат: [Регистрация] [Найти] [Рейтинги] [Обсуждения] [Новинки] [Обзоры] [Помощь|Техвопросы]
Ссылки:


 Ваша оценка:
  • Аннотация:
    То, что собственно и собирает мой рейтинг siTopTexts. ;)

См. также:
? Как узнать популярность произведения в "Самиздате" ("где/что смотреть" - основное, вкратце)
~ Рейтинг siTopTexts ("Самиздат", самое популярное за 30 дней).
= Сборка siTopTexts (среда, скрипты, обстоятельства и рекомендации).
Disclaimer: Я не несу никакой ответственности за последствия касаемо. Далеко не факт, что у вас получится то, на что вы рассчитываете, если станете использовать нижеописанное. Пользуйтесь оным исключительно на свой страх и риск.
   "       "   
  / \     / \  
 "---"---"---" 
      \ /      
       "       
      / \      
     "---"     
Комплект скриптов для сборки списка топовых текстов
Приложение к тексту: «Полуавтоматическая сборка "siTopTexts"»
(среда, скрипты, обстоятельства и рекомендации; редакция: 2020.09.29)
    Состав:
  1. Основной комплект (сборка списка топовых текстов):
    • siTop-aHits.awk - обработчик страниц рейтинга "по хитам";
    • siTop-aHits.cmd - обвязка-пускач siTop-aHits.awk;
    • siTop-bStat.awk - обработчик статистик разделов;
    • siTop-bStat.cmd - обвязка-пускач siTop-bStat.awk.
    • siTop-cChkH.awk - извлекатель хитов текста для siTop-cChkH.cmd;
    • siTop-cChkH.cmd - верификация набранных хитов;
    • siTop-dText.awk - извлекатель атрибутов текста для siTop-cChkH.cmd и siTop-dText.cmd;

  2. Вспомогательный комплект (наполнение и оформление siTop1000texts):
    • siTop-dText.cmd - комплектователь списка siTopTexts дополнительными сведениями;
    • siTop-dTextR.awk - извлекатель данных по гостевой к тексту;
    • siTop-dTextV.awk - извлекатель данных по оценкам текста;
    • siTop-fHtml.awk - оформитель таблиц и справок списка siTopTexts;
    • siTop-fHtml.cmd - обвязка-пускач siTop-fHtml.awk.

  3. Универсальный скрипт "качалка":

Имя файла скрипта: "siTop-aHits.awk" V-текст скрипта-V
BEGIN{ # siTop-aHits.awk - просмотр локальных страниц рейтинга и создание списка разделов с хитами # В процессе: считывается дата обновления рейтинга, и количество страница рейтинга хитов # Источник - рейтинг "по хитам": /rating/hits/ может использоваться самостоятельно. # Для правильной нумерации мест разделов, ИМЯ входных файлов должно начинаться с ЧИСЛА # (номер страницы рейтинга,например: 0025.html). Расширение - любое. # Причём, итоговые списки (пере)создаются РЯДОМ (jDir) с входными файлами: # - fOut=jDir"]aHits.lst" # основной список - OK_элементы ]aHits.lst # - fBad=jDir"]aHits.bad" # список брака - BAD_элементы ]aHits.bad # + выдача на StdUot: cDat,jNum,xNam,xNum,xPas,hMax,hMin,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: "Влад" или "Уксус•Сергей") # 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) НЕ создаётся # НЕштат (НЕ рейтинг или НЕ в порядке) выдача на StdUot: # "] Hole or no data ("step" lines) in file:" fNam) # "] DifDates;" cDat "!=" cYea"."cMth"."cDay "! in file:" fNam) # "] DifPageNums;" jNum "!=" 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],a1,"\\") if(j1==1)jDir=".\\" # иесто для результатов ТАМ ЖЕ, где исходные файлы else for(j2=1;j1-j2>0;j2++)jDir=jDir a1[j2]"\\" fOut=jDir"]aHits.lst" # основной список - OK_элементы ]aHits.lst 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 # хиты 10k разделов "макс" hMin=99999 # хиты 10k разделов "мин" jNum="" # номер страницы рейтинга (в имени файлов) } { # // -=- основной блок скрипта if(FNR==1){ # секция завершения работ с одним файлом и подготовки к работе со следущим if(NR!=1)chkSteps() # страница пройдена; она в порядке? fNam=FILENAME # U:\Jobs\#aHits\0001.hits.htm p100=split(FILENAME,a1,"\\") # NEW/NEXT входной файл разделим на подкаталоги и имя.расширение p100=split(a1[p100],a1,".") # имя.расширение входного файла разделим на части p100=(a1[1]-1)*100 # p100 чистые сотни (начиная с нуля, like: "1400" для "0015.hits.htm") step=-1 # 0-владелец, 1-дата обновления, 2-id раздела, 3-разбор строк таблиц статистики } #<b>СТАТИСТИКА за 22/11:</b> if (step==-1) { # считывание обязательной ДАТЫ рейтига if(match($0,/^<b>СТАТИСТИКА за ([0-3][0-9])\/([01][0-9]):<\/b>$/,a1)){ # 30 09 (30/09) cMth=a1[2] cDay=a1[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>/,a1)){ # это обязательно! hitP=a1[1] # хиты раздела за "12мес" id_P=a1[2]"/"a1[3] # ID раздела if(a1[4]==""){ # no: ФИО/псевдоним/nick xNam++ # errInf hitP numP id_P namP="\">?<\"" # ВМЕСТО ФИО/ник_владельца - спец.отметка sizK=0 # а объём - обнуляем sizN=0 # как и кол-во moto="" # как и девиз }else{ namP=pack(a1[4]) # ФИО/ник_владельца раздела if(match($0,/<\/a> "(.*)" \(([0-9]+)k,([0-9]+)\)/,a2)){ # (3776k,10) это - если не пусто xPas++ moto=pack(a2[1]) # девиз раздела (может отсутствовать) sizK=a2[2] # общий объём текстов в разделе sizN=a2[3] # кол-во текстов в разделе } else { # пусто (нет наполнения раздела) xNum++ # список брака - BAD_элементы ]aHits.bad moto="" sizK=0 sizN=0 } } print(sprintf("%7s%6s%8s%7s",hitP,numP,sizK,sizN),id_P,namP,moto) > fOut hTot=hTot+hitP # счёчик "hits total" if(hMin-hitP>0)hMin=hitP # хиты списка разделов "мин" if(hMax-hitP<0)hMax=hitP # хиты - "макс" step++ } } } 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 ) "&quot;"; 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 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"\"") } function chkSteps() { # страница пройдена; она в порядке? if(step!=101){ # количество записей на странице штатное? print("] Hole or no data ("step" lines) in file:" fNam) # нет! exit 3 }else{ if(cDat==""){ # это ПЕРВЫЙ файл страницы с хитами cYea=jYea # отпределимся с датой статистики (относительно "сегодня") if(jMth!=cMth) if(cMht==12)cYea-- # если месяц иной + предыдущий - декабрь => прошлый год cDat=cYea"."cMth"."cDay # полная дата для: "СТАТИСТИКА за дд/мм" }else if(cDat!=cYea"."cMth"."cDay){ # это второй и последующие файлы, даты совпабают? print("] DifDates: " cDat "!=" cYea"."cMth"."cDay " in file:" fNam) # нет! exit 1 } if(jNum=="")jNum=pNum # это ПЕРВЫЙ файл с хитами, запомним общее кол-во страниц в рейтинге else if(jNum!=pNum){ # это вторай и последующие файлы "с хитами", это кол-во тоже самое? print("] DifPageNums: " jNum "!=" pNum " in file:" fNam) # нет! exit 2 } } } END{ if(ARGV[1]==""){print("NO input file!");exit -1} # защита от случайного пуска chkSteps() # страница пройдена; она в порядке? print(cDat,jNum,xNam,xNum,xPas,hMax,hMin,hTot) # общая сводка работы с рейтингом "по хитам" }

Имя файла скрипта: "siTop-aHits.cmd" V-текст скрипта-V
@if not defined nJob @echo off echo %date% %time:~0,8% %~nx0 Begs :: siTop-aHits.cmd - сборка списка 10.000 топовых авторов СИ :: %time% - HH:MM:SS,tt HH<=9 -> "HH" == " H" лидирующий пробел для часа меньше 10 :: %date% - YYYY.mm.dd :: 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 pOld=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 :: основные сеты и прочая подготовка к работе... set nJob=aHits set jDat=%date% set errInf= :: pOld минимум страниц в рейтинге, должно быть не меньше set pOld=1004 :: pGet количество скачиваемых страниц рейтинга (ьольше - нет смысла) set pGet=300 :: dOld заведомо слишком старая дата рейтинга, должна быть иная set dOld=2000.01.01 :: wait - флаг/таймер зацикливания ожидания полного списка aHits set wait=%1 :: если заказано зацикливание, цикл ожиданий - 5 минут (300 секунд) if defined wait set /a wait=60*5 :: основной и резервный URL Самиздата (желательно работать с резервом) rem set siUrl=samlib.ru set siUrl=budclub.ru :: wDir - общее рабочее место set wDir=%~d0\Jobs :: sDir - общее складское хранилище set sDir=%~d0\Stor :: jDir - место для оперативных файлов set jDir=%wDir%\#%nJob% :: jRpt - общий отчёт с итоговыми сводками процессов set jRpt=%wDir%\_siTop.# :: zStL - общий подкаталог для посуточных подкаталогов с итоговыми списками set zStL=%sDir%\wOld\%jDat% :: проверить/создать нужные структуры для работы (оперативные площадки) if NOT exist %jDir%\ mkDir %jDir% if errorLevel 1 set errInf=fail mkDir %jDir%& goto nExit if NOT exist %zStL%\*.* mkDir %zStL% if errorLevel 1 set errInf=fail mkDir %zStL% & goto nExit :: hDat - дата рейтинга в СИ set hDat= set tmp0=%wDir%\20??.??.??.%nJob% :: ищем самый свежий ПОЛНЫЙ 20??.??.??.aHits, берём дату в его имени for %%A in (%wDir%\20??.??.??.%nJob%) do set dOld=%%~nA ::]1A hits xNam:0 xNum:36 xPas:9964 hDat:2020.03.08 hGap:837052.706 hTot:36515178 hPag:997 done:2020.03.09 09:43 if NOT %dOld% == 2000.01.01 ( for /F "tokens=1-9*" %%A in ( 'gawk "{if(match($0,/ hGap:([0-9]+)\.[0-9]+ .+ hPag:([0-9]+) /,j))print(j[2],j[1])}" %wDir%\%dOld%.%nJob%' ) do ( set pOld=%%A set nOld=%%B ) ) else echo NO old aHits if NOT %dOld% == 2000.01.01 echo . dOld=[%dOld%] pOld=[%pOld%] nOld=[%nOld%] set linN=0 set wUrl=%siUrl%/rating/hits/index.shtml set wFil=%jDir%\]%nJob%.chk :Again 1. притащить первую страницу рейтинга в файл 000.aHits.htm if exist %wFil% erase %wFil% if errorLevel 1 set errInf=fail erase %wFil%& goto nExit echo ? check siHitsPages... call wGetUrl2fil.cmd %wUrl% %wFil% if defined errInf goto nExit :: 2020.03.08 997 0 1 99 837052 44158 13048132 :: A B C D E F :: cDat,jNum,xNam,xNum,xPas,hMax,hMin,hTot :: 2. проверить исправность и новизну даты в притащеном. for /F "tokens=1-9*" %%A in ('gawk.exe -f %~dpn0.awk %wFil%') do ( set hDat=%%A set hPag=%%B set hNum=%%F ) echo . hDat=[%hDat%] hPag=[%hPag%] hNum=[%hNum%] :: новое? (сравниваются даты, число страниц и хиты лидера) if %dOld%%pOld%%nOld% == %hDat%%hPag%%hNum% set errInf=NO diffs, all the same& goto nExit :: список может чуть-чуть просесть, но именно чуть-чуть... set /a tmp0=%hPag%+9 set errInf=low hitsPages:%hPag% {pOld=%pOld%} if %pOld% LEQ %tmp0% goto getNew :: неполный список; цикл заказывали? if NOT defined wait goto nExit :: а заказано именно ЧИСЛО (секунд в цикле ожидания)? for /F %%A in ( 'gawk "BEGIN{print(strftime(\"%%H:%%M:%%S\",systime()+%wait%));exit}"' ) do set tmp0=%%A :: не число - не судьба... ;) if %tmp0% == 0 goto nExit :: иначе ждём-с ;) echo ! tooLow pagNum[%hPag%]; WAITing till %tmp0% gawk "BEGIN{t=systime()+%wait%;while(t>systime()){printf(\"%%s\",\".\");j=systime()+1;while(j>systime()){k=1}};exit}" echo. goto Again :getNew ОК - стираем старьё и тащим новый комплект set errInf= :: запустим "таймер" set tmp0=%time:~0,5% if "%tmp0:~0,1%" == " " set tmp0=0%tmp0:~1% set gap1=%tmp0% if exist %jDir%\*.hits.htm erase /F /Q %jDir%\*.hits.htm if exist %jDir%\*.aHits erase /F /Q %jDir%\*.aHits :: первая страница уже у нас(!) сразу прикопаем на правильное место move /Y %wFil% %jDir%\0001.hits.htm if errorLevel 1 set errInf=fail move %wFil% TO %jDir%\0001.hits.htm & goto nExit :: прочее контрольное-с - нафик! if exist %wDir%\]%nJob%.* erase %wDir%\]%nJob%.* if errorLevel 1 set errInf=fail erase old %wDir%\]%nJob%.* & goto nExit :: jLst задаётся в *.awk а здесь - для удобства-с set jLst=%jDir%\]%nJob%.lst :: скачивание страниц свежего СПИСКА топовых АВТОРОВ СИ (первая страница уже есть)... echo scans topHits for %hDat%... for /L %%A in (2,1,%pGet%) do if NOT defined errInf call :reqSiHits %%A if defined errInf goto nExit :: остановим "таймер" set tmp0=%time:~0,5% if "%tmp0:~0,1%" == " " set tmp0=0%tmp0:~1% set gap1=%gap1%-%tmp0% :: cDat,jNum,xNam,xNum,xPas,hMax,hMin,hTot - сканирование/сборка свежего локального списка aHits for /F "tokens=*" %%A in ('gawk.exe -f %~dpn0.awk %jDir%\*.hits.htm') do call :chkIt %%A :: если что не так ("]") => полный стоп! if %tmp0%[ == ][ set errInf=%tmp1% & goto nExit :: устаревшее - прикопаем-с... (до следующего обновления;) if exist %wDir%\*.%nJob% move /y %wDir%\*.%nJob% %jDir% if errorLevel 1 set errInf=fail move %wFil%\*.%nJob% TO %jDir%& goto nExit :: вытащим результаты в общее рабочее место copy /y %jLst% %wDir%\%hDat%.%nJob% > nul if errorLevel 1 set errInf=fail copy %jLst% TO %wDir%\%hDat%.%nJob%& goto nExit :: теперь новый == текущий. Старый - УЖЕ на полочке в подсобке set jLst=%wDir%\%hDat%.%nJob% :: оформим сводку результатов + замеченные проблемы... echo ; hitP numP sizK sizN id_P "namP" "moto" >> %jLst% set tmp0=;1A hits xNam:%xNam% xNum:%xNum% xPas:%xPas% hDat:%hDat% ^ hGap:%hMax%.%hMin% hTot:%hTot% hPag:%hPag% pGet:%pGet% done:%jDat% gap1:%gap1% echo %tmp0% >> %jLst% echo %tmp0% >> %jRpt% echo == Ok %hDat% xNam:%xNam% xNum:%xNum% xPas:%xPas% hGap:%hMax%.%hMin% hTot:%hTot% :: прикопаем итоги для истории... if NOT defined zStL goto nExit copy /b %jLst% %zStL% > nul if errorLevel 1 set errInf=fail copy %jLst% TO %zStL% :nExit if defined errInf echo ! %errInf% echo %date% %time:~0,8% %~nx0 Ends goto :eof :reqSiHits {sub} %%J получение очередной страницы рейтинга set /a linN+=1 set tmp0=000%1 set tmp0=%tmp0:~-4% :: оживляж - это святое! echo ? req %tmp0% hitsPage set uNum=-%1 if %1 == 1 set uNum= set wUrl=%siUrl%/rating/hits/index%uNum%.shtml set wFil=%jDir%\%tmp0%.hits.htm call wGetUrl2fil.cmd %wUrl% %wFil% goto :eof :chkIt запомним цифры итогов сканирования: пустые_ФИО (xNam) нет_файлов (xNum) записей_всего (xPas) set tmp0=%1 rem set a2a2=%2 set xNam=%3 set xNum=%4 set xPas=%5 set hMax=%6 set hMin=%7 set hTot=%8 set tmp1=%* goto :eof

Имя файла скрипта: "siTop-bStat.awk" V-текст скрипта-V
BEGIN{ # siTop-bStat.awk scan+check *.stat.htm +mkLst книг-кандидатов в siTopTexts # NB. Наличие текстов в статистике НЕ проверяется! minT=400 # минимальное кол-во хитов текста "за 30 дней", дабы "прорехи штопать" (если есть;) # 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=rDir"]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, слегка перепахано для более тонкого разбора наличности # + итоговый отчёты см. переменную rDir # + итоговый fOut формируется сразу отсортированный и оформленный # + в конце строк с атрибутами отобранных текстов - dat01 (1-й_полный_день) # ----- пример содержания отчёта по обработке статистик ("]bStat.rpt") # freshDate - 1-st_day maxHits numTot xDel/=Keep hitP numP h30d id_P id_T # 2020.09.13-2020.09.10 0 1 x 0.0% 0 0 0 # 2020.09.15-2020.09.14 81986 12245 x 55.8% 567481 3 81986 d/dront_n courtier3 # 2020.09.16-2020.09.14 27908 8125 x 37.0% 224062 14 27908 s/smekalin_d_o gospodinmag # 2020.09.17-2020.09.16 0 1564 = 7.1% 0 0 0 # ;2B stat 2020.09.14:dPre 12245:nPre 81986:hPre 20371:miss 2020.09.17/02:39:15~last # ;2C scan 2020.09.16:dEnd 1564:nEnd 0:hEnd 21935:nTot 7:pGis 00:09:59.tGap st1k:571 errS="] step.0 (NO file)" if(ARGV[1]=="")exit # защита от случайного пуска ticB=systime() jDat=strftime("%Y.%m.%d",ticB) 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(str1=="rdir")rDir=ENVIRON[str2]"\\" # место для всех ВЫХ.списков } if(fHit==""){ # если вызов НЕ из CMD, aHits ищем сами str0="U:\\Jobs\\_siTop.#" while((getline line<str0)>0){ # ищем последнюю записб успешного скачивания этого списка #;1A hits xNam:1 xNum:65 xPas:29934 hDat:2020.09.01 hGap:970691.489 hTot:49138995 hPag:1007 /.../ if(match(line,/^;1A hits xNam:.+ hDat:20([\.0-9]{8}) hGap:/,arr0))fHit=arr0[1] } close(str0) fHit="U:\\Jobs\\20"fHit".aHits" # строим полное имя нужного списка } # 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,"minT:"minT) # заполним массив атрибутов разделов в *.aHits int1=0 while((getline line<fHit)>0){ # fHit: like 2020.03.01.aHits split(line,arr0) # arr0[5] == k/kadawr if(match(arr0[1],/^[0-9]+$/)){ aHitP[arr0[5]]=arr0[1] # arr0[1] == 201661 aNumP[arr0[5]]=arr0[2] # arr0[2] == 21 aNamP[arr0[5]]=arr0[6] # arr0[6] == "Кадавр" int1++ }else if(arr0[1]==";1A")infH=line # для итогового списка отобранных текстов } close(fHit) # всё/не_всё, - старый список тогось if(int1==0){ errS="] step.0 (no or empty %fHit%: "fHit " )" exit } errS="" # массив имён месяцев для преобразования их в числа с лидирующим нулём 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 nTxt=0 # кол-во отобранных текстов tNum=0 # число принятых ГОДНЫХ текстов hitT=0 # сумма хитов "за 30 дней" ripN=0 # число пустых суток (там же) ripP=0 # число разделов-кандидатов на "штопку" endH=0 # последний НЕ ноль "за 30 дней" rip1=0 # первый ноль (там же) hitY=0 # хиты за "12мес" errN=0 # объявим массивыы для общего использования в подпрограммах split("",aDatN) # счётчики пар дат5 "fresh"-"dat01" split("",aDatM) # макс хиты каждой найденной пары дат split("",aNumD) # счётчики строк с записями в файлах выдачи split("",aSel) # в ячейках статистики: url,title,hits:all,12mon,mon0..monC-11,day0..day0-61 fBad=rDir"]bStat.bad" # список проблем и проблемных статистик (если-с;) fRpt=rDir"]bStat.rpt" # итоговый отчёт-сводка fDel=rDir"BadStats.fDat.lst" # список забракованных статистик fGis=rDir"]bStat.gis" # гистограммы посуточных хитов разделов с "прорехами" fTim=rDir"]bStat.tim" # сортированные моменты обновления статистик fOut=rDir"]bStat.lst" # итоговый список текстов-кандидатов siTopTexts } { # // -=- основной блок скрипта begs if(FNR==1){ # секция завершения работ с одним файлом и подготовки к работе со следущим if(NR!=1)chkSteps() # чем закончилась обработка предыдущего файла? fPth=FILENAME fNam=split(FILENAME,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") step=0 # 0-владелец, 1-дата обновления, 2-id раздела, 3-разбор строк таблиц статистики id_P="" namP="" inTab=0 # сначала - мы НЕ "в таблице" numT=0 # счётчик таблиц в файле статистики numR=0 # счётчик строк в текущей таблице selN=0 int8++ printf("%s",".") # оживляж... if(int8==100){ int9++ int8=0 print(sprintf("%3s",int9)) } nTot=int9*100+int8 # оживляж заканчивается, последний штрих ;) } if(step==0) { # ищем/проверяем ФИО автора # <h3>Статистика раздела &quot;<a href=./>Влад</a>&quot;:</h3> if (match($0,/<h3>Статистика раздела \&quot;<a href=\.\/>(.*)<\/a>\&quot;:<\/h3>/,arr0)) { if(arr0[1]==""){ errS="] step."step" (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] if(mark<datS"/"timS)mark=datS"/"timS if(strftime("%Y.%m.%d",ticS)!=datS){ errS="] step."step" (bad timeStamp in: " fNam " )" nextfile # что-то не так с датой обновления } 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)) { id_P=arr0[1] if(!aHitP[id_P]){ # этот раздел УШЁЛ из рейтинга "по хитам" errS="] step."step" (No in aHits: " 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) } if(int0=index(buf0,"</tr")){ # this line ends getSels(substr(buf0,1,int0-1)) # tabl_row -> arrow:sell_values buf0=substr(buf0,int0+4) # убрали эту строку из буфера и окультуриваем... setH=0 # добавленные -""- хиты sErr="" # пока этот текст/раздел НЕ в браке id_T=aSel[0] # имя+расшир файла с текстом (или "./" для раздела) namT=aSel[1] # пока фактическое (as-is) название текста в статистике if((numT==1)&&(numR==2)){ # хиты по разделу (спец.обслуживание) namT="\"<!>\"" id_T="~" # prt 8-раздел: 'хиты за 30 дней' if((hitT-minT>0)&&(rip1!=0)&&((endH-rip1>0)||rip1==1)){ ripP++ # число разделов-кандидатов на "штопку" selsOutG() # гистограмма: хитов много + есть "прореха" } aTot[nTot]=datS"-"timS" "dat01 sprintf("%6s%8s%8s %s %s"\ ,aNumP[id_P],aHitP[id_P],hitT,id_P,aNamP[id_P]) # заполняем массив моментов обновления статистик if(hitT-minT<0){ # в этом разделе слишком МАЛО "за последние 30 дней" step=4 # т.е. "наших" текстов нет априори nextfile } }else{ # обычная строка статистики текста int0=split(id_T,arr0,".") namT=pack(namT) # запакованное (свёрнутое!) название текста 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" # мало хитов } if(sErr==""){ # 0-"всё ОК" поток строк с текстами и хитами для выбора top1000 if(aHitP[id_P]==""){ errS="] step."step" (NO hitP for id_P: " id_P " in: " fHit " )" nextfile # что-то не так с датой обновления } if(match(namT,/^""$/)){ namT=hitT":noNamT" hitT=2 }else tNum++ # число принятых ГОДНЫХ текстов aTxt[++nTxt]=sprintf("%7s%8s%6s",hitT,aHitP[id_P],aNumP[id_P])" "id_P\ " "arr0[1]" "namP" "namT" "aNamP[id_P]" "fNam" "dat01 # строка для итогового списка текстов if(hitT-aDatM[dGap]>0){ # максимум - только у принятых! aDatM[dGap]=hitT # <- хиты, v- чьи-с ;) aDatI[dGap]=sprintf("%7s%6s%7s",aHitP[id_P],aNumP[id_P],hitT)" "id_P" "arr0[1] } if(dat01>max01)max01=dat01 # даты верхней границы надоть контролить... aDat1[dat01]++ } sErr="" 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 # сдвинем стат.дату к нулевому дню dat01=strftime("%Y.%m.%d",tic0-86400) # полная дата первого дня в интервале 30 дней dat30=strftime("%Y.%m.%d",tic0-86400*30) #полная дата последнего дня в этом же интервале dGap=datS"-"dat01 print(FILENAME) >rDir dGap".fDat.lst" aDatN[dGap]++ # счётчики "dat01" дат в статистиках aNumD[dGap]++ } 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] 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"") print("") >fGis split("",aStr) # готовим (собираем гистаграмму) 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 хитов) aStr[int2]=aStr[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 print(str0) >fGis # оформляем всё от... # |19 15 10 05 31 26 21.01.2020 # пример посуточной шкалы времени print("v...:....v....:....v....:....v") >fGis # 31302922396567855______0629939 # пример самой нижней строки гистограммы (с "прорехой") for(int2=1;int2<=int0;int2++)print(aStr[int2])>fGis print("|...:....|....:....|....:....|") >fGis print(id_P"/"id_T" "namT" " fNam) >fGis # ... и до } function pack(f1s1) { # мешающие chars -> нейтральные + cut too long + закавычить результат f1s2="" # TAB -> "•" while(f1n1=index(f1s1,"\x09")){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 f1s2="" # неразрывный_пробел -> "•" while(f1n1=index(f1s1,"\xA0")){f1s2=f1s2 substr(f1s1,1,f1n1-1)"•"; f1s1=substr(f1s1,f1n1+1)} f1s1=f1s2 f1s1 f1s2="" # двойные кавычки -> "&quot;" while(f1n1=index(f1s1,"\"")){f1s2=f1s2 substr(f1s1,1,f1n1-1)"&quot;"; f1s1=substr(f1s1,f1n1+1)} f1s1=f1s2 f1s1 f1s2="" # "%" -> "&#x25;" while(f1n1=index(f1s1,"%")){f1s2=f1s2 substr(f1s1,1,f1n1-1)"&#x25;"; 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(substr(f1s1,1,1)=="•")f1s1=substr(f1s1,2) # del "•" at beg f1n1=length(f1s1) if(substr(f1s1,f1n1,1)=="•")f1s1=substr(f1s1,1,f1n1-1) # del "•" at the end 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 " )" } } print(fPth) >fDel # зафиксируем проблему print(errS) >fBad errN++ errS="" # и очистим флаг-инфо } } function mkRpt(ln2rpt,int5) { # дабы нужное отправлять и в отчёт, и на экран print(ln2rpt) print(ln2rpt) >fRpt if(int5)print(ln2rpt) >fOut # это -> И в итоговой список текстов! } END{ # отстрелялись; ну почти... if(errS!=""){ print("") print(errS) # есть проблем-с => подудим exit 1 # и на выход с вещами } chkSteps() # чем закончилась обработка последнего файла? if(errS!=""){ print("") print(errS) # есть проблем-с => подудим exit 1 # и на выход с вещами } nTot=int9*100+int8 # оживляж заканчивается, последний штрих ;) print(" == " nTot) split("",aSel) # финальное оформление итогов обработки int2=0 # сётчик пар дат dEnd="2000.01.01" # максимальный 'dat01' mkRpt("freshDate - 1-st_day numTot xDel/=Keep hitP numP h30d id_P id_T") #шапка итога for(str0 in aDatN){ int2++ if(!aDatM[str0])aSel[int2]=sprintf("%s%6s",str0,aDatN[str0]) #datS-dat01 0 filN else aSel[int2]=sprintf("%s%6s",str0,aDatN[str0]) #datS-dat01 hitN filN split(str0,arr0,"-") # dGap=datS"-"dat01 if(dEnd<arr0[2])dEnd=arr0[2] # самая свежая дата dat01 } hPre=0 # ищем максимум хитов за 30 дней ВНЕ самых свежих статистик nEnd=0 # и кол-во +максХиты для ВНУТРИ latest 'dat01' hEnd=0 for(str0 in aDatN){ split(str0,arr0,"-") # dGap=datS"-"dat01 if(arr0[2]!=dEnd){ # это НЕ "статистики нужного 'dat01'" if(hPre-aDatM[str0]<0){ # здесь хитов больше? dPre=arr0[2] # запомним обстоятельства... hPre=aDatM[str0] nPre=aDatN[str0] } }else{ nEnd=nEnd+aDatN[str0] # кол-во статистик с 'dat01' if((hEnd-aDatM[str0])<0)hEnd=aDatM[str0] # maxHits for 'dat01' } } if(!nPre){ # и такое бывает,.. после траблов-с nPre=0 hPre=0 dPre=" -noDate- " } asort(aSel) keep=((nEnd/(nTot-errN))>0.995) # ==0 оставить ВСЁ за последнюю dat01 иначе - кроме старейшего for(int1=1;int1<=int2;int1++){ dat01=substr(aSel[int1],12,10) # 2020.07.18-2020.07.17 98107 4280 = # 123456789.123456789.123456789.123456789. j1=substr(aSel[int1],22,7)*100 if(dat01!=dEnd) str0=" x" # НЕ последняя dat01 - НЕнада! else{ if(keep){ keep=0; str0=" x" # набор полон, оставляем всё КРОМЕ самого старого }else str0=" =" # набор НЕ полон, оставляем ВСЁ с ПОСЛЕДНЕЙ dat01 } j2=aDatI[substr(aSel[int1],1,21)] if(j2=="")j2=" 0 0 0" mkRpt(aSel[int1] sprintf("%6.1f%",j1/(nTot-errN)) str0" "j2) } # общие итоги обработки if(length(aDat1)>1)max01="mod:~" # ВЕРХНИХ границ БОЛЬШЕ одной - НЕ собирается! else max01="mod:v" asort(aTxt) # подготовка for(int1=nTxt;int1>0;int1--){ # и выдача списка ОТОБРАННЫХ текстов print(aTxt[int1]) >fOut } split(aTxt[nTxt-999],arr0) # хиты 1000-го текста в списке надо вычленять #. . . . . 18675 394807 6 k/kadawr n "Кадавр" "Псион" "Кадавр" k~kadawr 2020.09.14 print("; hitT hitP numP id_P id_T \"namP\" \"namT\" \"moto\" fNam dat01") >fOut print(infH) >fOut mkRpt(";2B stat"sprintf(" %s:dPre%6s:nPre%7s:hPre%6s:miss",dPre,nPre,hPre,nTot-nEnd-errN)\ " "mark"~last "max01,1) # mkRpt(";2C scan"sprintf(" %s:dEnd%6s:nEnd%7s:hEnd%6s:nTot %s:pGis st1k:%s tNum:%s",dEnd,nEnd\ ,hEnd,nTot,ripP,arr0[1],tNum),1) #strftime("%H:%M:%S",mktime("2000 01 01 00 00 00")+systime()-ticB) if(errN)mkRpt("BadStats found: "errN" x (may_be_NumsMISmatch)") #такие файлы учитываются абы как nTot=length(aTot) asort(aTot) # подготовка for(int1=1;int1<=nTot;int1++)print(aTot[int1]) >fTim # и выдача МОМЕНТОВ обновления статистик #. . . . 2020.09.17-02:39:15 2020.09.16 21128 577 63 p/pilar "Пилар" print("; datS-timS dat01 numP hitP h30d id_P \"namP\"") >fTim }

Имя файла скрипта: "siTop-bStat.cmd" V-текст скрипта-V
@if not defined nJob @echo off echo %date% %time:~0,8% %~nx0 Begs :: siTop-bStat.cmd - докачиватель статистик 10k авторов (обновление устаревших) :: ! ЛЮБОЙ параметр при запуске == блокировка удаления устаревшего (надо для перезапуска упавшего) :: скачав недостающее, строится комплект отчётов и список текстов-претендентов в siTop1000texts :: minT - минимальные допустимые хиты текста (меньше - брак, для siTop-bStat.awk и проч.) set minT=400 :: 2019.07.15 creation from siTop-dStat.cmd (2019.07.11) :: ... :: 2020.01.06, nvv, (!)ЕСЛИ гранд СИ попал в отсеянные по ДАТЕ обновления - сборка рейтинга НЕВОЗМОЖНА! :: 2020.03.27, nvv, радикально переделано (ВСЕ проверки и ВСЕ итоги - в siTop-bStat.awk) :: + более тонкая работа с наличностью (с уже имеющимися файлами статистик) :: 2020.04.25, nvv, some updates :: 2020.05.31, nvv, нижняя граница для разделов из списка *.aHits - hitP>hitL (==670), а не конец списка :: 2020.06.05, nvv, hitL=665 :: 08 650 :: 10 645 :: 14 610 :: 2020.06.18, nvv, нижнюю границу (hitL=NNN) можно задать файлом-маркой "NNN.lowHits" :: 2020.08.21, nvv, статистики, обновлённые "СЕГОДНЯ" или с той же датой ВЕРХНЕЙ границы интервала :: НЕ удаляются! Т.е. киллер не трогает сегодняшний комплект для рассчёта :: 2020.09.18, nvv, слегка перепахано для более тонкого разбора наличности :: + итоговый fOut формируется сразу отсортированный и оформленный :: + в конце строк с атрибутами отобранных текстов - dat01 (1-й_полный_день) :: 2020.09.18, nvv, исправлена неточность в работе со списком BadStats (если упомянут в ]bStat.rpt) :: образец имени списка (в U:\Jobs\#bStatRpt\): 2020.03.23-2020.03.21.fDat.lst :: здесь: :: 2020.03.23 - дата обновления статистик в списке :: 2020.03.21 - дата "day1" (1-й полный день хитов) статистик в списке :: .fDat.lst - общий суффик в именях списков :: идея - оставить только статистики с самой свежей датой "day1" :: окромя самых старых (по дате обновления в них) :: OS windows - должны быть настроены системные переменные окружения: :: %time% - HH:MM:SS,tt HH<=9 -> "HH" == " H" лидирующий пробел для часа меньше 10 :: %date% - YYYY.mm.dd :: основные сеты и прочая подготовка к работе... set nJob=bStat set jDat=%date% set errInf= :: признак "НЕ удалять старые статистики" set keepOld=%1 :: основной и резервный URL Самиздата (желательно работать с резервом) rem set siUrl=samlib.ru set siUrl=budclub.ru :: hitL - хитов за "12мес" (у РАЗДЕЛА должно быть НЕ меньше) set hitL=600 :: уточнение по *.lowHits рядом (если есть); его имя - нижняя граница хитов 12мес. разделов по *.aHits for %%A in (%~d0\*.lowHits) do set hitL=%%~nA rem set /p tmp0=%hitL% rem if /i NOT %tmp0% == y goto :eof :: wDir - общее рабочее место set wDir=%~d0\Jobs :: sDir - общее складское хранилище set sDir=%~d0\Stor :: jDir - место для оперативных файлов set jDir=%wDir%\#%nJob% :: rDir - место для рабочих сводок процесса set rDir=%wDir%\#%nJob%Rpt :: jRpt - общий отчёт с итоговыми сводками процессов set jRpt=%wDir%\_siTop.# :: bErr отчёт-сводка разбора статистик set bErr=%wDir%\]%nJob%.bad :: zStL - общий подкаталог для посуточных подкаталогов с итоговыми списками set zStL=%sDir%\wOld\%jDat% :: bRpt рабочая отчёт-сводка разбора статистик set bRpt=%rDir%\]%nJob%.rpt :: bGis гистограмы разделов с ВОЗМОЖНОЙ прорехой (надо бы глянуть) set bGis=%rDir%\]%nJob%.gis :: linN счётчик статистик (оживляж) set linN=0 :: eNul счётчик "статистик недоступно" (0b) set eNul=0 :: dnLd счётчик "скачано статистик" (за сеанс) set dnLd=0 :: wGetSiz - размер скачанного файла (default 1b минимум) set wGetSiz=1 :: fHit - ВХОДНОЙ список "Топ10к" (популярных АВТОРОВ СИ) set fHit= :: найти последний 20??.??.??.aHits и запомнить его имя (например, U:\Jobs\2019.06.27.aHits) for %%A in (%wDir%\20??.??.??.aHits) do set fHit=%%A if NOT defined fHit set errInf=? NO 20??.??.??.aHits found & goto nExit :: установим счётчик на максимум... for /F %%A in ('gawk.exe "{if($1-%hitL%<0){print(NR);exit}}" %fHit%') do set linN=%%A :: проверить/создать нужные структуры для работы (оперативные площадки) if NOT exist %jDir%\*.* mkDir %jDir% if errorLevel 1 set errInf=fail mkDir %jDir% & goto nExit if NOT exist %rDir%\*.* mkDir %rDir% if errorLevel 1 set errInf=fail mkDir %rDir% & goto nExit if NOT exist %zStL%\*.* mkDir %zStL% if errorLevel 1 set errInf=fail mkDir %zStL% & goto nExit :: запустим "таймер" set tmp0=%time:~0,5% if "%tmp0:~0,1%" == " " set tmp0=0%tmp0:~1% set gap2=%tmp0% rem set /p tmp0=OK-0 to go on? rem goto nvv :: нет сводки - списки теряют смысл if NOT exist %bRpt% goto oldOk :: обрадуем наблюдателя перечнем списков "xDel/=Keep" gawk.exe "{if(match($4,/^[x=]$/))print($0)}" %bRpt% :: разберёмся с наличностью-с, ЕСЛИ не было отмены разборок if defined keepOld goto oldOk :: и если есть разбираться с чем... это списки ОСТАВЛЯЕМОГО (они не нужны - статистики уже у нас) for /F %%A in ( 'gawk.exe "{if(match($4,/^=$/))print($1)}" %bRpt%' ) do ( if exist %rDir%\%%A.fDat.lst erase %rDir%\%%A.fDat.lst set getD=%%A ) rem echo getD:%getD% jDat:%jDat% :: списки с датой "сегодня" НЕЛЬЗЯ обрабатывать удалялкой if %getD:~0,10%. == %jDat%. ( set getD=%getD:~11% ) else ( set getD= ) rem set /p tmp0=OK-2 to go on? :: а это - списки того, что следует удалить for /F %%A in ( 'gawk.exe "{if(match($4,/^x$/))print($1)}" %bRpt%' ) do if NOT defined errInf if exist %rDir%\%%A.fDat.lst call :killOlds %%A :oldOk скачивание недостающих статистик разделов... rem exit rem set /p tmp0=OK-3 hitL:%hitL% to go on? echo ! freshening stats 2>%bErr% for /F "tokens=*" %%A in ( %fHit% ) do if NOT defined errInf call :reqSiStat %%A if defined errInf goto nExit if exist %rDir%\*.* erase /F/Q %rDir%\*.* if errorLevel 1 set errInf=fail erase %rDir%\*.* & goto nExit :nvv : разбор содержимого файлов статистики echo ... prepare to scan *.stat.htm... gawk.exe -f %~dpn0.awk %jDir%\*.stat.htm if errorLevel 1 set errInf=fail scaning *.stat.htm & goto nExit :: выцепим главные итоги разбора статистик (29961:hPre - максХиты устаревшего) for /F "tokens=1-9*" %%A in ( 'gawk "{if(match($0,/ ([0-9]+):hPre +([0-9]+):miss.+~last mod:(.)$/,a))print(a[1],a[2],a[3])}" %bRpt%' ) do (set hPre=%%A& set miss=%%B& set jYes=%%C) :: 2020.03.13:dEnd - day1 для for /F "tokens=1-9*" %%A in ( 'gawk "{if(match($0,/ (20..\...\...):dEnd .+ st1k:([0-9]+) tNum:([0-9]+)$/,a))print(a[1],a[2],a[3])}" %bRpt%' ) do (set dEnd=%%A& set st1k=%%B& set tNum=%%C) :: соственно сборка закончена; последние штрихи +разложить всё по полочкам if exist %wDir%\*.%nJob% move /y %wDir%\*.%nJob% %rDir% > nul if errorLevel 1 set errInf=fail move %wDir%\*.%nJob% to %rDir% & goto nExit :: jLst - итоговый список топовых текстов if "%jYes%" == "~" ( :: если грандов обнесли - готовый список использовать НЕЛЬЗЯ! set jLst=%wDir%\%dEnd%.~.%nJob% set jYes==NO set mark=~ ) else ( :: иначе - штатно set jLst=%wDir%\%dEnd%.%nJob% set jYes==OK set mark== ) rem echo hPre:%hPre% miss:%miss% jYes:%jYes% mark:%mark% st1k:%st1k% tNum:%tNum% jLst:%jLst% rem exit :: в любом случае, прямой/кривой итоговый список таки должон быть (с признаком, если нада...) copy /b /y %rDir%\]%nJob%.lst %jLst% > nul if errorLevel 1 set errInf=fail copy ]%nJob%.lst to %jLst% & goto nExit :: остановим "таймер" set tmp0=%time:~0,5% if "%tmp0:~0,1%" == " " set tmp0=0%tmp0:~1% set gap2=%gap2%-%tmp0% :: строим красивую строку с итоговой сводкой (для отчёта) в ]bStat.rpt hitL:%hitL% gawk.exe "BEGIN{printf(\";2D %%s \",strftime(\"%mark%%%a%mark%\",systime()));exit}" >>%bRpt% echo nHit:%numP%.%hitP% st1k:%st1k% tNum:%tNum% minT:%minT% dnLd:%dnLd% eNul:%eNul% done:%jDat% gap2:%gap2% >>%bRpt% echo ;2D scrn %mark% nHit:%numP%.%hitP% st1k:%st1k% tNum:%tNum% eNul:%eNul% done:%jDat% gap2:%gap2% :: разнесём отчётные строки по всем положенным местам gawk.exe "{if(match($1,/^;2D$/))print($0)}" %bRpt% >> %jLst% gawk.exe "{if(match($1,/^;2.$/))print($0)}" %bRpt% >> %jRpt% :: разложим полученное по полочкам всяческим-с... copy /b /y %jLst% %zStL% > nul if errorLevel 1 set errInf=fail copy %jLst% to %zStL% & goto nExit copy /b /y %bRpt% %zStL% > nul if errorLevel 1 set errInf=fail copy %bRpt% to %zStL% & goto nExit copy /b /y %bRpt% %wDir% > nul if errorLevel 1 set errInf=fail copy %bRpt% to %wDir% & goto nExit copy /b /y %rDir%\]%nJob%.tim %zStL% > nul if errorLevel 1 set errInf=fail copy ]%nJob%.tim to %zStL% & goto nExit :: проблемы надо выложить в общее место if exist %rDir%\]%nJob%.bad type %rDir%\]%nJob%.bad >> %bErr% copy /b /y %bErr% %zStL% > nul if errorLevel 1 set errInf=fail copy %bErr% to %zStL% & goto nExit if exist %bGis% ( copy /b /y %bGis% %zStL% > nul if errorLevel 1 set errInf=fail copy %bGis% to %zStL% & goto nExit copy /b /y %bGis% %wDir% > nul if errorLevel 1 set errInf=fail copy %bGis% to %wDir% & goto nExit ) :nExit если была проблем-с - известим всяко (особливо при запуске "с выключение компа") if defined errInf echo !!! %errInf% echo %date% %time:~0,8% %~nx0 Ends (dnLd=%dnLd%, miss:%miss% jYes=%jYes%) parms:%* goto :eof :reqSiStat %%J проверка/обновление очередной статистики раздела :: 717 9986 85 82 m/maks "Я" "всякое" :: 1 2 3 4 5 6 7 :: hitP numP sizK sizN id_P "namP" "sigP" :: нижняя граница - по хитам разделов за "12мес", а не по концы списка aHits if %hitL% GTR %1 goto :eof :: обратный отсчёт нагляднейб хе-хе... ;) set /a linN-=1 :: бракованные разделы (sizN==0) нам НЕ интересны, но СЧИТАЕМ и их if %4. == 0. goto :eof :: вот и выцепим эту нижнёё границу... set hitP=%1 set numP=%2 rem set sizK=%3 rem set sizN=%4 set id_P=%5 rem set namP=%6 rem set sigP=%7 :: оживляж должен быть красив... ;))) set tmp0= %linN% set tmp1= %hitP% set tmp0=%tmp0:~-6% %tmp1:~-7% :: имя локального файла из authID (d/dront -> d~dront) set wFil=%jDir%\%id_P:~0,1%~%id_P:~2%.stat.htm if exist %wFil% echo = has %tmp0% statPage %id_P% & goto :eof :: если файла у нас нет - тащить-с! set wUrl=%siUrl%/%id_P%/stat.shtml :: файла нет => тащим с СИ echo ? req %tmp0% statPage %id_P% call wGetUrl2fil.cmd %wUrl% %wFil% if defined errInf goto :eof set /a dnLd+=1 if NOT %wGetSiz% == 0 goto :eof :: если статистика раздела недоступна... set /a eNul+=1 echo ;eNul hitP:%1 numP:%2 %wUrl% >> %bErr% erase %wFil% goto :eof :killOlds %%A грохаем все файлы по списку в файле %rDir%\%1.fDat.lst... set kFil=%rDir%\%1.fDat.lst if NOT exist %kFil% goto :eof set kLst=%1 :: явный брак киляем не глядя if /i %kLst% == BadStats goto killStat :: ЕСЛИ в имени нет даты "сегодня" if %jDat%. == %kLst:~0,10%. ( echo ? skip stats: %1 - toDay goto killList ) :: и ЕСЛИ в имени нет ВЕРХНЕЙ даты расчёта if %getD%. == %kLst:~11%. ( echo ? skip stats: %1 - upDat goto killList ) :killStat а вот это грохаем не глядя echo ? kill stats: %1 for /F %%J in (%kFil%) do if exist %%J erase %%J :killList а затеи и сам список - туда же, под нож! erase %kFil% goto :eof

Имя файла скрипта: "siTop-cChkH.awk" V-текст скрипта-V
BEGIN{ # siTop-cChkH.awk - хиты текста по факту в интервале от "Размещен:" до верхней границы if(ARGV[1]=="")exit # защита от случайного пуска # 2020.06.10, nvv, creation, на основе siTop-bStat.awk от 2020.05.31 # 2020.06.16, nvv, it's working! =) if(!test)rDir="U:\\Jobs\\#bStatRpt\\" # штатно здесь, в тесте - в текущем месте for ( str2 in ENVIRON ) { # ! регистр букв в имени переменной может быть любой str1 = tolower( str2 ) # Temp и temp - РАЗНЫЕ имена для gAwk... if ( str1 == "begd" ) begD=ENVIRON[str2] # дата "Размещен:" if ( str1 == "id_t" ) t_id=ENVIRON[str2]".shtml" # имя файла с текстом, чьи хиты нужны } # begD="2020.06.12" # t_id="popdanec23.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>Статистика раздела &quot;<a href=./>Влад</a>&quot;:</h3> if (match($0,/<h3>Статистика раздела \&quot;<a href=\.\/>(.*)<\/a>\&quot;:<\/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(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-16>0)&&(selN-16-selE<=0)){ # 21 = 16+5<=21 17..21 hitT=aSel[selN]+hitT # сразу подсчитаем сумму хитов "за 30 дней" }else if(selN-16-selE==1){ # ячейка сразу за границей sel1=aSel[selN] }else if(selN-16-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 # защита от случайного пуска } }

Имя файла скрипта: "siTop-cChkH.cmd" V-текст скрипта-V
@if not defined nJob @echo off :: siTop-cChkH.cmd - просмотр списка *.bStat, скачивание ВСЕХ текстов из (кривое оставляется!) :: смотрится дата "Размещён", если она ПОСЛЕ верхней границы выцепляемого интервала - игнорировать! :: если ПОСЛЕ нижней границы - уточняются фактичкеи хиты в интервале :: по результатам собирается уточнённый НЕ сортированный список *.cChkH (а`ля *.bStat) :: отсотрированый список годится для полноценной сборки рейтинга :: noReGet - запрет повторного скачивания пустых/битых текстов set noReGet=%1 :: minT - минимальные допустимые хиты текста (меньше - брак) set minT=400 :: set noReGet=1 :: %time% - HH:MM:SS,tt HH<=9 -> "HH" == " H" лидирующий пробел для часа меньше 10 :: %date% - YYYY.mm.dd :: 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 set nJob=cChkH set awkT=%~dp0siTop-dText.awk if NOT exist %awkT% set errInf=NO %awkT% found & goto nExit set siUrl=samlib.ru set siUrl=budclub.ru set jDat=%date% :: wDir - общее рабочее место set wDir=%~d0\Jobs :: sDir - общее складское хранилище set sDir=%~d0\Stor :: zStL - общий подкаталог для посуточных подкаталогов с итоговыми списками set zStL=%sDir%\wOld\%jDat% set jRpt=%wDir%\_siTop.# :: dirT - склад для топовых текстов (лидеры рейтингов) set dirT=%sDir%\Text :: счётчики проблем... set errInf= :: nulT текст - недоступен: 0b set nulT=0 :: badT текст - битый (нет любого): begD,endD,sizT,namA,namT set badT=0 :: down - хиты изменены set down=0 :: datJ - верхняя граница интервала: дата в имени последнего ВХОДНОГО списка *.bStat set datJ= :: найти последний 20??.??.??.bStat и запомнить его имя (т.е. дату в нём, например, 2019.07.14.bStat) for %%A in (%wDir%\20??.??.??.bStat) do set datJ=%%~nA if NOT defined datJ set errInf=? NO 20??.??.??.bStat found & goto nExit :: 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 - НЕ сортированный список для "siTop1000m" set jLst=%jDir%\]%nJob%.lst :: eLst - список ПРОБЛЕМ с текстами/гостевыми set eLst=%wDir%\]%nJob%.bad :: hold - опорная дата в имени склада с текстами set hold=%jDat% :: tDir - папка для текстов "наших" 30-дней (like: 2019.08.02.text) set tDir=%dirT%\%hold%.text 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 %zStL%\*.* mkDir %zStL% if NOT exist %jDir%\ set errInf=fail mkDir %zStL%\ & 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 :: установим счётчик текстов на максимум... for /F %%A in ( 'gawk.exe "{if(!match($1,/^[0-9]+$/)||($1-%minT%<0)){print(NR);exit}}" %wDir%\%datJ%.bStat' ) do set linN=%%A :: wGetSiz - объём файла, полученного с СИ (default 1b) set wGetSiz=1 echo req topTexts... linN:%linN% :: gap3 - интервал работы скрипта set gap3=%time:~0,5% if "%gap3:~0,1%" == " " set gap3=0%gap3:~1% :: hitT hitP numP id_P id_T xDat "namA" "namT" for /F "tokens=*" %%A in ( 'gawk.exe "{if(match($1,/^[0-9]+$/)&&($1-%minT%>=0))print($0)}" %wDir%\%datJ%.bStat' ) do if NOT defined errInf call :reqSiText %%A if defined errInf goto nExit 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 set jLst=%wDir%\%datJ%.%nJob% :: выясним хиты 1000-го текста for /F %%A in ('gawk.exe "{if(NR==1000)print($1)}" %jLst%') do set ck1k=%%A set tmp0=%time:~0,5% if "%tmp0:~0,1%" == " " set tmp0=0"%tmp0:~1%" set gap3=%gap3%-%time:~0,5% :: оформим сводку результzатов... echo ; hitT oldH. hitP numP id_P id_T "namP" "namT" "sigP" sFil >> %jLst% :: сначала сводки от aHits и bStat gawk.exe "{if(match($1,/^;[1-3].$/))print($0)}" %wDir%\%datJ%.bStat >> %jLst% set tmp0=;3C chkH :: затем собственная сводка set tmp0=%tmp0% dInt:%dBeg%-%datJ% ^ ck1k:%ck1k% ^ down:%down% ^ nulT:%nulT% ^ badT:%badT% ^ done:%jDat% gap3:%gap3% echo %tmp0% >> %jLst% if NOT defined noReGet echo %tmp0% >> %jRpt% echo %tmp0% :: да и результат прикопать надлежитЪ copy /b/y %jLst% %zStL% > nul if errorlevel 1 set errInf=fail copy %jLst% to %zStL% :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" "sigP" sFil :: 4943 8349 843 m/mir_i putnik "Мир..." "Путник" "потеряллогиникод..." m-mir_i set hitT=%1 set hitP=%2 set numP=%3 set id_P=%4 set id_T=%5 set namP=%6 set namT=%7 set sigP=%8 set gFil=%9 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 %awkT% %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 goto fixErr :mark0 смотрим атрибуты (в т.ч. дату создания, точно название и автор[а/ов]) текста... set fOut=%tFil% for /F "tokens=*" %%J in ('gawk.exe -f %awkT% %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% %sigP% %gFil% goto :eof :txtInOK текст как-бы ОК, а дата "Размещен:" - ОК? 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 -f %~dpn0.awk %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% %sigP% %gFil% goto :eof :: 400 : 8651 501 s/set 13 "СэтКонстантин" "NoName(Безимени)" "СэтКонстантин" s~set ::; hitT oldH. hitP numP id_P id_T "namP" "namT" "sigP" sFil :: 1 2 3 4 5 6 7 8 9 :formIt %hitT% %typT% %hitP% %numP% %id_P% %id_T% %namP% %namT% %sigP% %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% %sigP% %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

Имя файла скрипта: "siTop-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 # защита от случайного пуска # 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, обрабатываемая страница буфферизируется; выдача - только если всё ОК # Скрипт выдаёт на 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 # объём (в килобайтах) этого текста 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(hitT)hitT=sprintf("%7s",hitT) fErr="P eAvt:"hitT" NO owner FIO" # бывает-с, хотя и очень редко... flgO=1 split("",aOut) # массив под строки обихоженной страницы с текстом aNum=0 # счётчик строк в массиве aOut } 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 ) "&quot;"; j1 = substr( j1, n+1 ) } j1=j2 j1 j2="" # "••" -> "•" while(j0=index(j1,"%")) { j2 = j2 substr( j1, 1, j0-1 ) "&#x25;"; 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"\"") } { # scan text head (шапка текста) outP($0) #6 "namA" ФИО ("Федорочев Алексей" или "Калашников Сергей Александрович, Андрей_М11") #Буревой Андрей: <small><a href=/b/burewojandrej/>другие произведения.</a></small> #Ил Саган, Кейн Алекс: <small><a href=/s/sagan_i/>другие произведения.</a></small> if (!step) { # нулевой шаг - автор if (match($0,/^(.+): <small><a href=.+>другие произведения\.<\/a><\/small>$/,aj)) { namA=pack(aj[1]) 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]) 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=/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="/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($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($0=="<!----------- Собственно произведение --------------->")chkLn=NR+4 if(NR==chkLn){ if(index($0,"<h3>Извините, доступ к этому произведению ограничен.</h3>"))sizT=sizT".0" else sizT=sizT".1" # для обычных текстов, ".0" для -^- хитромудрых # begD maxD endD sizT namA namT votT jnrT print(sprintf("%11s%11s%8.1f %s %s %s %s",begD,endD,sizT,namA,namT,votT,jnrT),fNam) step=NR next } } if ((step-6)>0) { # завершающмй шаг if($0=="<!--------------------------------------------------->"){ step=NR # flgO=0 next } # если это есть - всё ОК, закругляемся if($0=="<!---- Блок описания произведения (слева внизу) ----------------------->"){ flgO=1 # 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,fNam) # у нас проблема exit } for(j1=1;j1<=aNum;j1++)print(aOut[j1])>fOut }

Имя файла скрипта: "siTop-dText.cmd" V-текст скрипта-V
@if not defined nJob @echo off echo %date% %time:~0,8% %~nx0 Begs :: siTop-dText.cmd - сборка и оснащение 30d списка 1k топовых текстов доп.данными о них и их гостевых :: %time% - HH:MM:SS,tt HH<=9 -> "HH" == " H" лидирующий пробел для часа меньше 10 :: %date% - YYYY.mm.dd :: 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, подправлен оживляж (нагляднее-с;) set nJob=dText set noRepl=%1 set mark=;m set awkV=%~dpn0V.awk set awkR=%~dpn0R.awk set awkT=%~dpn0.awk set siUrl=samlib.ru 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= :: nulT текст - недоступен: 0b set nulT=0 :: badT текст - битый (нет любого): begD,endD,sizT,namA,namT set badT=0 :: nulG гостевая - недоступна: 0b set nulG=0 :: badG гостевая - битая (нет любого на проверяемых страницах): endD,sizT set badG=0 :: rNot гостевая - пуста (нет любого): Dat,rNum set rNot=0 :: zipR гостевая - архив(ы) set zipR=0 :: datJ - дата в имени последнего ВХОДНОГО списка "Популярные КНИГИ 10k топовых авторов СИ" set datJ= :: найти последний 20??.??.??.cChkH и запомнить его имя (т.е. дату в нём, например, 2019.07.14.cChkH) for %%A in (%wDir%\20??.??.??.cChkH) do set datJ=%%~nA if NOT defined datJ set errInf=? NO 20??.??.??.cChkH found & goto nExit :: 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% :: jLst - список для "siTop1000m" - 1k популярных текстов месяца (со всеми атрибутами) set jLst=%jDir%\%datJ%.%nJob% :: eLst - несортированный список ПРОБЛЕМ с текстами/гостевыми set eLst=%wDir%\]%nJob%.bad :: hold - опорная дата привязки реплик set hold= :: если перезапуск - считать дату привязки if exist %jLst% ( for /F %%J in ('gawk.exe "{if(match($1,/^%mark%$/)){print($3);exit}}" %jLst%') do set hold=%%J ) else ( set hold=%jDat% if exist %jDir%\*.* rmDir /s/q %jDir% if errorlevel 1 set errInf=fail rmDir /s/q %jDir% mkDir %jDir% if errorlevel 1 set errInf=fail mkDir %jDir% ) if defined errInf goto nExit if NOT defined hold set errInf=someThing wrong with "hold" key & goto nExit :: очистим будущие списки рейтинга и ошибок echo %mark% hold %hold% > %jLst% 2> %eLst% :: tDir - папка для 1k топовых текстов "наших" 30-дней (like: 2019.08.02.text) set tDir=%dirT%\%hold%.text if NOT exist %tDir%\ mkDir %tDir%\ if NOT exist %tDir%\ set errInf=fail mkDir %tDir%\ & goto nExit :: tmpF - времянка для скачиваемых текстов set tmpF=%tDir%\siTextDL.tmp if exist %tmpF% erase %tmpF% if errorLevel 1 set errInf=FAIL erase %tmpF%& goto nExit :: ok1k - устанавливается, когда оптичена 1000 топовых текстов (+оценки +гостевые к ним) set ok1k= :: linN - счётчик текстов set linN=0 :: wGetSiz - объём файла, полученного с СИ (default 1b) set wGetSiz=1 echo req topTexts... :: gap4 - интервал работы скрипта set gap4=%time:~0,5% if "%gap4:~0,1%" == " " set gap4=0%gap4:~1% :: hitT hitP numP id_P id_T xDat "namA" "namT" for /F "tokens=*" %%A in ( %wDir%\%datJ%.cChkH ) do if NOT defined errInf if NOT defined ok1k call :reqSiText %%A rem ) do if %linN% LEQ 2 call :reqSiText %%A if defined errInf goto nExit set tmp0=%time:~0,5% if "%tmp0:~0,1%" == " " set tmp0=0"%tmp0:~1%" set gap4=%gap4%-%time:~0,5% :: оформим сводку результzатов... :: . 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 echo ; hitT numP hitP sizT.Ok aNum rNum begD endD ^ aDat "namA" "namT" id_P id_T "votT" "jnrT" gFil >> %jLst% :: сначала сводки от aHits и cChkH gawk.exe "{if(match($1,/^;[1-3].$/))print($0)}" %wDir%\%datJ%.cChkH >> %jLst% :: ;4T text nulT:1 badT:0 nulG:0 badG:0 rNot:85 zipR:253 done:2019.11.28 17:17-17:31 <- штат set tmp0=;4T text if defined noRepl set tmp0=;4T noRe :: затем собственная сводка set tmp0=%tmp0% ^ nulT:%nulT% ^ badT:%badT% ^ nulG:%nulG% ^ badG:%badG% ^ rNot:%rNot% ^ zipR:%zipR% ^ tHit:%tHit% ^ done:%jDat% gap4:%gap4% echo %tmp0% >> %jLst% echo %tmp0% >> %jRpt% echo %tmp0% :: да и результат предъявить надлежитЪ copy /b/y %jLst% %wDir% > nul if errorlevel 1 set errInf=fail copy %jLst% to %wDir% :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 if %linN% == 1000 (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" "sigP" sFil :: 4943 989: 8349 843 m/mir_i putnik "Мир..." "Путник" "потеряллогиникод..." m-mir_i set hitT=%1 set oldH=%2 set hitP=%3 set numP=%4 set id_P=%5 set id_T=%6 set namP=%7 set namT=%8 set sigP=%9 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 :: глянем, может этот текст уже у нас... set tmp0= for %%J in ( %tFil% ) do set tmp0=%%~zJ :: пусто == нужно тащить с СИ if NOT defined tmp0 goto getTxt :: есть, но нулевой - нужно горхнуть и тащить с СИ if %tmp0% == 0 erase %tFil% & goto getTxt :: есть и ненулевой, разберёмся... echo. %linR% = %curT%.Text: %gFil% set fOut= for /F "tokens=*" %%J in ('gawk.exe -f %awkT% %tFil%') do call :chkTxt %%J :: если OK - займёмся оформлением этого текста if NOT "%begD%" == "]" goto txtInOK :: если битый, то только подудеть set /a badT+=1 erase %tFil% goto fixErr :getTxt тащим топовый текст на склад-с set wUrl=%siUrl%/%id_P%/%id_T%.shtml if exist %tDir%\siTextDL.tmp erase %tDir%\siTextDL.tmp echo. %linR% ? %curT%.Text: %gFil% call wGetUrl2fil.cmd %wUrl% %tDir%\siTextDL.tmp if defined errInf goto :eof if NOT %wGetSiz% == 0 goto mark0 :: если файл текста недоступен... set errT=] err:T nulT: %curT% %gFil%.text erase %tDir%\siTextDL.tmp set /a nulT+=1 goto fixErr :mark0 смотрим атрибуты (в т.ч. дату создания, точно название и автор[а/ов]) текста... set fOut=%tFil% for /F "tokens=*" %%J in ('gawk.exe -f %awkT% %tDir%\siTextDL.tmp') 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 :: если с текстом проблемы, ставим на нём крест erase %tFil% set /a badT+=1 goto fixErr :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 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}" >> %jLst% echo. %begD% %endD% %aDat% %namA% %namT% %id_P% %id_T% %votT% %jnrT% %oldH% %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 :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

Имя файла скрипта: "siTop-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 ) "&quot;"; j1 = substr( j1, n+1 ) } j1=j2 j1 j2="" # "••" -> "•" while(j0=index(j1,"%")) { j2 = j2 substr( j1, 1, j0-1 ) "&#x25;"; 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>&nbsp;()</small></h2> #<center><h2>Комментарии: <a href="/f/fedorochew_a/2018.shtml">Лось</a><br><small>&nbsp; #(Оценка:<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>&nbsp;(Оценка:<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) }

Имя файла скрипта: "siTop-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 } }

Имя файла скрипта: "siTop-fHtml.awk" V-текст скрипта-V
BEGIN{ # siTop-fHtml.awk - оформление в HTML рейтинга "siTop1000text" if(ARGV[1]=="")exit # защита от случайного пуска #hMin=696 # 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 =Вс= nHit:20223.630 <- т.е. 20223 разделов с хитами "12мес" НЕ ниже 630 # ergo -> в списке тексты с хитами "30дн." НЕ меньше 630. rTyp="<b>si&#x54;op&#x54;exts</b>" # siTopTexts ancT="t" # общий признак типа рейтинга в якорях, комментах и т.п. ancN=":" # частный признак якоря места (в формате: "ггммвв:NNN" flag=0 # флаг для чередующейся раскраски строк таблиц tGap=100 # строк в одной таблице tMax=1000 # строк в списке всего maxH=0 # максимальные хиты текста (1-й в рейтингше) minH=0 # минимальные хиты текста (1000-й) totH=0 # сумма хитов всех текстов nAv1=0 # новый автор oldT=0 # размещено более года назад curT=0 # размещено в границах обсчитываемого интервала ficT=0 # фикция (за верхней границы интервала) nTx1=0 # вверх nTx2=0 # новинки nTx3=0 # вниз nSz1=0 # объём+ nSz2=0 # объём- nUs1=0 # успех+ nUs2=0 # успех- updH=0 # поправленные хиты за "30 дн." dOld="" # "/" == общий префикс урлов СИ: samlib.ru budclub.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(hDir!="")hDir=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\"" # светло-сиреневый - размещено "давно" больше года назад jr=split(ARGV[1],aq,"\\") # U:\Jobs\#qMonths\ +2020.06.03.vText dEnd=substr(aq[jr],1,10) fOut=hDir dEnd ".siTop.html" # U:\Stor\Html\ +2020.06.08.siTop.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",systime())"{ -->" #mark HTML print "--- " strftime("%H:%M:%S",systime()) " Begs..." # начали работу (оживляж;) } 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() { # сборка всей страницы рейтинга/приложения (тип, строк, куда-с) print "<blockquote>" > fOut print info > fOut #служебная отметка (для порядку) ## информационная вставка --> •¦ # print "<table align=center border=0 cellspacing=0 cellpadding=2>" > fOut # print "<tr align=center bgcolor=navy><td><font size=+2 color=aqua>"> fOut # print "<b>&nbsp;&#x2744; С новым годом! <font color=white>&#x2744;"> fOut # print "<font size=+2 color=lime>Happy New Year! &#x2744;&nbsp;</b></td>"> fOut # print "</tr></table>" > fOut # print "<br>" > fOut # print "<table align=center border=1 cellspacing=0 cellpadding=2>" > fOut # print "<tr align=center bgcolor=LightYellow><td><font size=+1><b>&nbsp;NB."> fOut # print "В <a href=/comment/"nUrl"/si_top500look-curr>гостевой</a>"> fOut # print "(реплика #58.) - <font color=brown>ОПРОС..."> fOut # <font color=brown> # print "</font>Мне интересно ваше мнение. :-!&nbsp;</b></td>"> fOut # print "</tr></table>" > fOut # print "<hr>" > fOut ## <!-- информационная вставка (справка в шапке) print "См. <i>также</i>:" > fOut print "<br>?" > fOut print "<a href=/"nUrl"/si_pop-brief.shtml>Как узнать<b>" > fOut print "популярность произведения</b> в \"Самиздате\"</a>" > fOut print "(\"<b>где/что смотреть</b>\" - основное, вкратце)."> fOut print "<br>\\\\" > fOut print "<a href=/"nUrl"/si_top500look-prev.shtml>" > fOut print "<b>Предыдущий</b> рейтинг "rTyp"</a>" > fOut print "(недавнее \"<i>самое</i> популярное\")" > fOut # print "<br>+" > fOut # print "<a href=/"nUrl"/si_topq6m-curr.shtml>" > fOut # print "Дополнение <b>si6months</b></a> (к "rTyp"," > fOut # print "ещё 6 месяцев недавнего прошлого)." > fOut print "<br>=" > fOut print "<a href=/"nUrl"/si_top100repls-current.shtml>" > fOut print "Сборка "rTyp"</a> (среда," > fOut print "<i>скрипты</i>, обстоятельства и рекомендации)." > fOut print "<br>*" > fOut print "<a href=/"nUrl"/si_top-history_list.shtml>История-<b>Р</b>," > fOut print "\"<i>прикопанное</i>\" <b>прошлое</b></a>" > fOut print "(ссылки на подборки старых рейтингов по полугодиям)." > fOut print "<hr>" > fOut print "<b>NB.</b> <i>Названия</i> произведений и <i>псевдонимы</i>" > fOut print "авторов (как и прочие <i>сведения</i> в таблицах) приведены" > fOut print "<i>\"<u>as-is</u>\", по состоянию на момент</i> сбора" > fOut print "данных. <i>Текущее</i> состояние можно узнать, пройдя" > fOut print "<i>по ссылкам</i> (в ячейках таблиц)." > fOut print "<br><b>(!)</b> <i><u>Если</u></i> на месте некоторых букв" > fOut print "(символов) в <i>названии</i> произведения или в <i>псевдониме</i>" > fOut print "автора вы видите \"<i><u>пустоту</u></i>\", то <i><u>у" > fOut print "вас</u></i>,скорей всего, <i><u>отсутствует</u></i>" > fOut print "шрифт с такими символами (иероглифы, руны, etc.)." > fOut print "<hr>" > fOut print "" > fOut print "<table align=center border=1 cellspacing=0 cellpadding=2>" > fOut print "<tr align=center>" > fOut print "<td bgcolor="color[1]" colspan=\"14\">Краткая сводка + цвет некоторых" > fOut print "ячеек таблиц (<i>предыдущий рейтинг -" > fOut print "<a href=/"nUrl"/si_top500look-prev.shtml><b>"dOld"</b></a></i>)</td></tr>" > fOut print "<tr align=center><td bgcolor="color[0]" colspan=\"1\"><b>N</b>," > fOut print "сдвиг места</td></td>" > fOut print "<td rowspan=\"4\"></td>" > fOut print "<td bgcolor="color[0]"><b>Произведения</b></td>" > fOut print "<td rowspan=\"4\"></td>" > fOut print "<td bgcolor="color[0]"><b>Авторы</b></td>" > fOut print "<td rowspan=\"4\"></td>" > fOut print "<td bgcolor="color[0]"><b>Размещено</b></td>" > fOut print "<td rowspan=\"4\"></td>" > fOut print "<td bgcolor="color[0]"><b>Объём</b> стал</td>" > fOut print "<td rowspan=\"4\"></td>" > fOut print "<td bgcolor="color[0]"><b>Оценки</b></td>" > fOut print "<td rowspan=\"4\"></td>" > fOut print "<td bgcolor="color[0]"><b>Отклик</b></td>" > fOut print "</tr><tr align=center>" > fOut print "<td bgcolor="color[4]">вверх.<b>" nTx1"</b></td>" > fOut print "<td bgcolor="color[5]"rowspan=\"2\">новые.<b>"newN"</b></td>" > fOut print "<td bgcolor="color[5]"rowspan=\"2\">новые.<b>"nAv1"</b></td>" > fOut print "<td bgcolor="color[4]">"qGap"<b>"curT"</b></td>" > fOut print "<td bgcolor="color[4]">больше.<b>"nSz1"</b></td>" > fOut print "<td bgcolor="color[4]">хорошие.<b>"nUs1"</b></td>" > fOut print "<td bgcolor="color[3]"rowspan=\"2\">нет.<b>"rNot"</b></td>" > fOut print "</tr><tr align=center>" > fOut print "<td bgcolor="color[3]">вниз.<b>" nTx3"</b></td>" > fOut print "<td bgcolor="color[11]">давно.<b>"oldT"</b></td>" > fOut print "<td bgcolor="color[3]">меньше.<b>"nSz2"</b></td>" > fOut print "<td bgcolor="color[3]">плохие.<b>"nUs2"</b></td>" > fOut print "</tr></table>" > fOut print "<table align=center border=0 cellspacing=0 cellpadding=2><tr>" > fOut print "<td>(</td>" > fOut print "<td bgcolor="color[11]"><b><i>давно</i></b> –" > fOut print "больше <b>"tOld"</b> назад</td>" > fOut print "<td>)</td>" > fOut print "</tr></table>" > fOut # print "<table align=center border=0 cellspacing=0 cellpadding=2><tr>" > fOut # print "<td bgcolor="color[4]"><b>NB.</b> Хиты" > fOut # print "произведений, опубликованных <b>после</b>" > fOut # print dat_str(dBeg)", учтены <u>по факту</u>" > fOut # print "(„<b>¦</b>“ - с даты размещения)" > fOut # print "</tr></table>" > fOut print "<hr>" > fOut print "" > fOut print "<font size=\"-2\" face=monospace color="color[8]">"> fOut print "&nbsp;&nbsp;&nbsp;"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"&nbsp;&nbsp;&nbsp;<br>" > fOut print "&nbsp;&nbsp;/&nbsp;\\&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/&nbsp;\\&nbsp;&nbsp;<br>" > fOut print "&nbsp;"---"---"---"&nbsp;<br>" > fOut print "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\\&nbsp;/&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>" > fOut print "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>" > fOut print "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/&nbsp;\\&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>" > fOut print "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"---"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</font>" > fOut print "<center><font size=\"+2\">" > fOut # заголовок страницы print "Рейтинг "rTyp"-"ancD"</font>" > fOut print "<br>\"Самиздат\", самые популярные произведения" > fOut print "<table align=center border=0 cellspacing=0 cellpadding=2>" > fOut print "<tr bgcolor="color[4]">" > fOut j0="с "dat_str(dBeg) if(yBeg!=rYea)j0=j0" "yBeg" г." j0=j0" по "dat_str(dEnd,1)"&nbsp;" print "<td>&nbsp;за 30 дней: "j0"</td>" > fOut # if(dOff!="0.0")print "<td bgcolor="color[3]">(<i><u>нет данных</u> за: "dOff"</i>)</td>" > fOut print "</tr></table></center></blockquote>" > fOut bLin=mkCap() # шапка - первая (нулевая-с) строка таблиц lMax=tMax # всего строк в таблице for ( tIni=1; tIni<lMax; tIni=tIni+tGap ) { print "<blockquote>" > fOut # начало очередной таблицы print "<table align=center border=1 cellspacing=0 cellpadding=2>" > fOut # навигация в print "<caption><a id=\""ancD ancT tIni"\"></a>"mkGoTo(tIni)"</caption>" > fOut # заголовке print bLin > fOut # шапка таблицы tEnd=tIni+tGap for (tBeg=tIni;tBeg<tEnd;tBeg++) { if(tBeg<=lMax) print mkTabLn(tBeg,ordr[tBeg]) > fOut # строка данных в таблице } if ((tBeg-tMax)>=0) print bLin > fOut print "</table>" > fOut # таблица готова print "</blockquote>" > fOut # закрытие блока } print "<blockquote>" > fOut # подвал страницы print "<center>" mkGoTo(0) "</center>" > fOut # заголовке print "<ul>" > fOut print "<table border=0 cellspacing=0 cellpadding=2><tr>" > fOut # навигация в print "<td><b>Попутные сведения</b> (к "rTyp"-"ancD")" > fOut print "<td></tr></table>" > fOut print "<li>Справочник ИСС-СИ" > fOut print "\"<a href=/rating/hits/index.shtml><i><b>Рейтинг по количеству" > fOut print "посетителей</b></i></a>\" за <b>"hDat"</b>." > fOut print "<br>(от "dat_str(donH)", всего страниц: "hPag")" > fOut print "<br>Интервал хитов (<u>за 12мес</u>) у отобранных разделов:" > fOut print "<ul>" > fOut print "<li><i>Лидер</i> (1-е место): <b>"hMax"</b>." > fOut print "<li><i>Замыкающий</i> ("endP"-е): <b>"nHit"</b>." > fOut print "</ul>" > fOut print "<li><i>Прочие</i> данные - по состоянию на "dat_str(hold)"." > fOut print "<li>Произведения с хитами <i>по факту</i> „<b>¦</b>“: <b>"updH"</b>." > fOut print "<li>Среди гостевых (у 1.000 топовых произведений):"> fOut print "<ul>" > fOut if(nulG)print "<li><i>недоступные</i>: <b>"nulG"</b>;" > fOut if(badG)print "<li><i>повреждёные</i>: <b>"badG"</b>;" > fOut if(rNot)print "<li><i>пустые</i> (кулуары•\"<i>антимат</i>\"•без реплик): <b>"rNot"</b>;" > fOut if(zipR)print "<li><i>с архивами</i>: <b>"zipR"</b>." > fOut print "</ul>" > fOut print "</ul>" > fOut print "<table align=center border=0 cellspacing=0 cellpadding=2>" > fOut # навигация в print "<tr><td>(copyleft "rYea"</td>" > fOut print "<td bgcolor="color[6]"><b>/\\/.\\/.\\/.</b></td><td>)</td></tr></table>" > fOut print info > fOut #служебная отметка (для порядку) printf("%s","</blockquote>") > fOut } 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 (строка siTop1000text за номером tLn) flag=!flag # чередующаяся раскраска строк hLin="<tr align=center bgcolor="color[flag]">" # собираем очередную строку... hLin=hLin"<td "a00[tLn]" title=\""a02[tLn]"\"><a id=\""ancD ancN 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>" a21[tLn] "</a></td>" # <- text -^ hLin=hLin "<td align=left" # <- автор-v if(a10[tLn]==nUrl) hLin=hLin " bgcolor=" color[10] # nvv line ;) else hLin=hLin a77[tLn] hLin=hLin "><a href=/"a10[tLn]"/ title=\"Хиты:"a13[tLn] hLin=hLin ", место:"a12[tLn]a78[tLn]"\">" 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] "k</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><small><a href=/comment/"a10[tLn]"/"a20[tLn] # отклик +v hLin=hLin " title=\"Реплик в сутки (шт./дни): "a63[tLn]"\">"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 ancT 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]+$/)){ # признак - "строка основных данных" jj=NR-1 # 1-st line - info a00[jj]=0 # пока неизвестная позиция текста в предыдущем bStat.20??.??.# a01[jj]=jj # позиция текста в siTop1000text a02[$12"/"$13]=jj # обратная ссылка на позицию по урлу текста a10[jj]=$12 # автор, id_P - урл раздела (мой - n/nosow_w_w;) a11[jj]=unpack($10) # автор, namA - ФИО a12[jj]=$2 # автор, numP - позиция раздела в рейтинге посещаемости a13[jj]=$3 # автор, hitP - хиты раздела (в рейтинге посещаемости) a20[jj]=$13 # текст, id_T - имя файла (без расширения .shtml) 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"=="доступ ... ограничен" 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-й в рейтингше) minH=$1 # минимальные хиты текста (1000-й) 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 if(match($0,/^;1A .+ hDat:20..\.(.+)\.(.+) hGap:([0-9]+)\..+ hPag:([0-9]+) .+ done:(20[\.0-9]+) /,aj)){ #;1A hits xNam:1 xNum:62 xPas:19937 hDat:2020.06.07 hGap:899839.527 hTot:41141405 hPag:1003 pGet:200 done:2020.06.08 10:00 hDat=aj[2]"/"aj[1] hMax=aj[3] # хиты раздела-лидера aHits hPag=aj[4] # страниц aHits donH=aj[5] }else if(match($0,/^;2D .+ nHit:([0-9]+)\.([0-9]+) /,aj)){ #;2D stat nHit:13363.651 ht1k:656 done:2020.06.08/10:27 eNul:0 dL:224 gapT:10:21-10:27 endP=aj[1] # номер последнего отсканированного раздела в списке aHits nHit=aj[2] # его хиты за "12мес" }else if(match($0,/^;.. .+ nulG:([0-9]+) badG:([0-9]+) rNot:([0-9]+) zipR:([0-9]+) /,aj)){ #;4T text nulT:0 badT:0 nulG:0 badG:0 rNot:87 zipR:253 tHit:2735909 done:2020.01.09 10:29-11:42 nulG=aj[1] # гостевая недоступна badG=aj[2] # гостевая повреждена rNot=aj[3] # гостевая пуста zipR=aj[4] # гостевая с арховом } } 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 ) "&quot;"; j1 = substr( j1, n+1 ) } j1=j2 j1 return( j1 ) } function unquot(j1) { # восстановление литерала "жанр(ы), свёрнутого при сборе сведений с СИ j2="" # '&quot;' -> '"' while(n=index(j1,"&quot;")) { 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 } 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] # 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(nHit-a22[tMax]>0)tMax-- print("tMax:"tMax) # siTop1000text - оформление заготовок строк (для основного рейтинга) 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++ } } } # Жанр(ы) if(a40[jj]==0) a40[jj]="--" # два дефиса подряд смотрятся красивше (jnrT;) # Оценки текста (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]"•" # архивов нет } # выявим "свежак", влетевший в рейтинг менее чем за 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]="" } # собственно сборка файла с таблицами... mkPage() print "--- " strftime("%H:%M:%S",systime()) " Ends..." # закончили работу (оживляж;) }

Имя файла скрипта: "siTop-fHtml.cmd" V-текст скрипта-V
@if not defined nJob @echo off echo %date% %time:~0,8% %~nx0 Begs :: siTop-fHtml..cmd - оформление в HTML списка 1k топовых текстов прошедшего месяца :: + 20??.??.??.dText (like 2018.12.30.dText) - оформляемый ПРОШЕДШИЙ месяц :: + 20??.??.??.dText (like 2018.11.29.dText) - опорный ПРЕД прошедший месяц :: %time% - HH:MM:SS,tt HH<=9 -> "HH" == " H" лидирующий пробел для часа меньше 10 :: %date% - YYYY.mm.dd :: 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 set nJob=fHtml if NOT defined jDat set jDat=%date% set noUp=%1 :: wDir - общее рабочее место set wDir=%~d0\Jobs :: sDir - общее складское хранилище set sDir=%~d0\Stor :: dDir - склад для отработанных списков 20??.??.??.?.#.dText set dDir=%sDir%\Text\zOld.dTexts :: hDir - склад под выходные файлы с таблицами *.html set hDir=%sDir%\Html if NOT exist %hDir% mkDir %hDir% if NOT exist %hDir% set errInf=fail mkDir %hDir% & goto nExit :: fOld - прошлый опорный список "siTop1000m" set fOld= for %%Z in (%wDir%\20??.??.??.#.dText) do (set fOld=%%Z & set dOld=%%~nZ) rem echo fOld=[%fOld%] rem exit if NOT defined fOld set errInf=!? NO baseList (20??.??.??.#.dText) found & goto nExit :: dOld - дата в имени файла опорного списка set dOld=%dOld:~0,-2% if exist %wDir%\%dOld%.eAddT set aLst=%wDir%\%dOld%.eAddT :: fLst - свежий список "siTop1000m" - 1k популярных текстов (со всеми атрибутами) set fLst= for %%Z in (%wDir%\20??.??.??.dText) do call :chkMtxt %%Z if NOT defined fLst set errInf=!? NO 20??.??.??.dText found & goto nExit echo curr:%fLst% echo last:%fOld% if defined aLst echo addT:%aLst% :: собственно оформлялка ("от и до";) gawk.exe -f %~dpn0.awk %fLst% if NOT %errorLevel% == 0 set errInf=!!! X someThing's wrong with %~n0.awk & goto nExit :: блокируется оптичивание преобразованного в HTML if defined noUp goto nExit :: уберём уже ненужные старые списки рейтингов на склад Text\zOld.dTexts move /Y %wDir%\20??.??.??.#.dText %dDir% if NOT %errorLevel% == 0 set errInf=!! fail to move old *.#.dText to %dDir% & goto nExit :: пометим свежий список как "обработанный" move /Y %fLst% %wDir%\%dLst%.#.dText if NOT %errorLevel% == 0 set errInf=! fail to move %fLst% to *.#.* & goto nExit if NOT defined aLst goto nExit move /Y %aLst% %dDir% if NOT %errorLevel% == 0 set errInf=! fail to move %aLst% to %dDir% :nExit if defined errInf echo !!! %errInf% echo %date% %time:~0,8% Job:%nJob% Ends goto :eof :chkMtxt if %~n1 LEQ %dOld% goto :eof set fLst=%1 set dLst=%~n1 goto :eof

Имя файла скрипта: "wGetUrl2fil.cmd" V-текст скрипта-V
@if not defined nJob @echo off :: установленная переменная nJob (вызов из "моего" батника) блокирует команду echo off set nReV=2.12, 2020.03.22 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%% код ошибки, если проблемы с DL_файлом, иначе - пусто 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% 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/) :nStart if NOT defined siUrl set siUrl=samlib.ru if NOT defined wKey set wKey=-U "Mozilla/5.0" 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= set wGetErr= goto :eof :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- ) :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 ( if defined wGetLog echo x is gone=%1 set errInf= goto :eof ) 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 2020 /\/.\/.\/.)

 Ваша оценка:

Связаться с программистом сайта.

Новые книги авторов СИ, вышедшие из печати:
О.Болдырева "Крадуш. Чужие души" М.Николаев "Вторжение на Землю"

Как попасть в этoт список
Сайт - "Художники" .. || .. Доска об'явлений "Книги"