См. также:
?
Как узнать
популярность произведения в "Самиздате"
("где/что смотреть" - основное, вкратце)
~
Рейтинг
siTopTexts ("Самиздат", самое популярное за 30 дней).
=
Сборка siTopTexts (среда,
скрипты, обстоятельства и рекомендации).
Disclaimer:
Я не несу никакой ответственности за последствия касаемо.
Далеко не факт, что у вас получится то, на что вы рассчитываете,
если станете использовать нижеописанное. Пользуйтесь оным
исключительно на свой страх и риск.
" "
/ \ / \
"---"---"---"
\ /
"
/ \
"---"
Комплект скриптов для сборки списка топовых
текстов
Приложение к тексту:
«Полуавтоматическая сборка
"siTopTexts"»
(среда, скрипты, обстоятельства и рекомендации; редакция: 2020.09.29)
Состав:
- Основной комплект (сборка списка топовых текстов):
- Вспомогательный комплект (наполнение и оформление siTop1000texts):
- Универсальный скрипт "качалка":
Имя файла скрипта: "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 ) """; 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>Статистика раздела "<a href=./>Влад</a>":</h3>
if (match($0,/<h3>Статистика раздела \"<a href=\.\/>(.*)<\/a>\":<\/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="" # двойные кавычки -> """
while(f1n1=index(f1s1,"\"")){f1s2=f1s2 substr(f1s1,1,f1n1-1)"""; f1s1=substr(f1s1,f1n1+1)}
f1s1=f1s2 f1s1
f1s2="" # "%" -> "%"
while(f1n1=index(f1s1,"%")){f1s2=f1s2 substr(f1s1,1,f1n1-1)"%"; f1s1=substr(f1s1,f1n1+1)}
f1s1=f1s2 f1s1
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>Статистика раздела "<a href=./>Влад</a>":</h3>
if (match($0,/<h3>Статистика раздела \"<a href=\.\/>(.*)<\/a>\":<\/h3>/,aj)) {
step++ # проверка ОК
}
}else if(step==1){ # вычленеие даты обновления статистики
if(match($0,\
/<li><i>Статистика рассчитывается .+\. \(.+ (...) +([0-9]+) (..:..:..) (20[0-9][0-9])\)<\/i>/,aj)){
if(length(aj[2])==1) aj[2]="0"aj[2] # причешем первые дни месяца "1" -> "01"
ticS=mktime(aj[4]" "mNum[aj[1]]" "aj[2]" 12 00 00") # тики на 12 часов даты статистики
datS=aj[4]"."mNum[aj[1]]"."aj[2]
step++ # дату статистики оптичили
}
}else if(step==2){ # ищем authID (!должен быть)
#[<a href=http://top.mail.ru/pages?id=77427&period=0&date=2018-10-02&filter_type=0
#&filter=n/nosow_w_w&pp=20&gender=0&agegroup=0>по дням</a>]
if (match($0,/\[<a href=http.+&filter=([0-9a-z]\/[\-0-9a-z_]+)&pp=.+>по дням<\/a>]/,aj)) {
step++ # проверка ОК
}
}else if(step==3){ # таблицы статистики, просмотр строк, сборка данных в ячейках
if($0=="<!--------- Подножие ------------------------------->"){ # разбор закончен
step++
nextfile
}
if(inTab){ # Мы ВНУТРИ таблицы, собираем строки таблицы с хитами текстов
buf0=buf0" "$0 # gain inpLines to buf0, then check contents
while((match(buf0,/<tr ?[^>]*>/))||(int0=index(buf0,"</tr"))){ # seek <tr .. </tr for tabRow
if(RSTART){ # new/next line begs
numR++
buf0=substr(buf0,RSTART+RLENGTH)
}
if(int0=index(buf0,"</tr")){ # this line ends
sel0=0 # хиты до накануне-v
sel1=0 # хиты накануне даты "Размешен:"
getSels(substr(buf0,1,int0-1)) # tabl_row -> arrow:sell_values
buf0=substr(buf0,int0+4) # убрали эту строку из буфера и окультуриваем...
id_T=aSel[0] # имя+расшир файла с текстом (или "./" для раздела)
if((numT==1)&&(numR==2)){ # хиты по разделу (спец.обслуживание)
}else{ # обычная строка статистики текста
if(id_T==t_id){
if(!sel0)hitT=hitT+sel1 # если это глюк СИ (хиты накануне размещения), учтём их
print(hitT)
exit
}
}
}
}
if(int0=index(buf0,"</table")){ # this tabl ends
buf0=substr(buf0,int0+4) # update buf0
inTab=0
}
}else{ # ищем начало таблицы
if(int0=index($0\
,"<table border=1 cellspacing=0 cellpadding=0><tr><td><td colspan=2><b>Итого</b></td>")){
numT++ # new table
numR=1 # певая строка каждой таблицы - календарь хитов статистики раздела
buf0=substr($0,int0+80)
if(numT==1){ # 1-st table 1-st row -> get col-dates & so-on
match(buf0,/<tr[^>]*>(.+)<\/tr[^>]*>/,aj) # собственно строка с календарём
getSels(aj[1]) # но самую первую такую - разберём-с
tic0=ticS # и привяжем дату к нулевому (самому левому) дню посуточных данных
while(strftime("%d",tic0)!=aSel[16])tic0=tic0-86400 # сдвинем стат.дату к нулевому дню
for(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 ) """; j1 = substr( j1, n+1 ) }
j1=j2 j1
j2="" # "••" -> "•"
while(j0=index(j1,"%")) { j2 = j2 substr( j1, 1, j0-1 ) "%"; j1 = substr( j1, j0+1 ) }
j1=j2 j1
j2="" # "••" -> "•"
while(n=index(j1,"••")) { j2 = j2 substr( j1, 1, n-1 ); j1 = substr( j1, n+1 ) }
j1=j2 j1
if(substr(j1,1,1)=="•") j1 = substr( j1, 2 ) # del "•" at beg
n=length(j1)
if(substr(j1,n,1)=="•") j1 = substr( j1, 1, n-1 ) # del "•" at end
return ("\""j1"\"")
}
{ # 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 ) """; j1 = substr( j1, n+1 ) }
j1=j2 j1
j2="" # "••" -> "•"
while(j0=index(j1,"%")) { j2 = j2 substr( j1, 1, j0-1 ) "%"; j1 = substr( j1, j0+1 ) }
j1=j2 j1
j2="" # "••" -> "•"
while(n=index(j1,"••")) { j2 = j2 substr( j1, 1, n-1 ); j1 = substr( j1, n+1 ) }
j1=j2 j1
if(substr(j1,1,1)=="•") j1 = substr( j1, 2 ) # del "•" at beg
n=length(j1)
if(substr(j1,n,1)=="•") j1 = substr( j1, 1, n-1 ) # del "•" at end
return ("\""j1"\"")
}
{
# <h3>Влад
if (!step) { # нулевой шаг - автор
if (match($0, /<h3>(.*)$/, aj)) {
if(aj[1]=="") exit # == "битая" гостевая (нет ника автора)
fErr="H eHdr:"hitT" no title"
step=1
next
}
}
# <center><h2>Комментарии: <a href=
#<h2>Комментарии: <a href="/k/koshienko_a_g/kniga3.shtml">6 Косплей Сергея Юркина (книга четвёртая)</a><br><small> ()</small></h2>
#<center><h2>Комментарии: <a href="/f/fedorochew_a/2018.shtml">Лось</a><br><small>
#(Оценка:<b><a href=/cgi-bin/vote_show?DIR=f/fedorochew_a&FILE=2018>8.26*694</a></b>,)</small></h2>
# <center><h2>Комментарии: <a href="/p/polishuk_w/zenitchic.shtml">Зенитчик</a>
#<br><small> (Оценка:<b><a href=/cgi-bin/vote_show?DIR=p/polishuk_w&FILE=zenitchic
#>5.98*169</a></b>,)</small></h2>
# {if(match($0,/:<b><a href=\/cgi-bin\/vote_show\?DIR=.+>(.+)<\/a>/,a)) print a[1];exit}
if (step==1) {
if (tmp0=index($0,"<h2>Комментарии: <a href=")) {
$0=substr($0,tmp0+30)
match($0, />(.*)<\/a><br>/, aj) # выдернуть название текста, к которому гостевая
namT=pack(aj[1])
if ((aj[1]=="")||(aj[1]=="Управление")) exit #== "битая" гостевая (нет или "левое" название)
fErr="I eInf:"hitT" bad dates/size"
step=2
next
}
}
#<li>Обновлено: 21/05/2018. 1123k. <a
#<li>Размещен: 30/04/2019, изменен: 29/06/2019. 231k. <a
if (step==2) {
if (match($0,/^<li>Размещен: [0-9]{2}\/[0-9]{2}\/(..)?[0-9]{2}\, изменен: [0-9]{2}\/[0-9]{2}\/(..)?[0-9]{2}\. [0-9]+k\. <a/,aj)){
fErr="J eJnr:"hitT" bad janr info"
step=3
next
}
}
#<li><a href=/type/index_type_15-1.shtml>Новелла</a>: <a href="/janr/index_janr_5-1.shtml">Проза</a>, <a href="/janr/index_janr_1-1.shtml">Фантастика</a>, <a href="/janr/index_janr_35-1.shtml">Фанфик</a>
#<li><a href=/type/index_type_5-1.shtml>Статья</a>: <a href="/janr/index_janr_15-1.shtml">Философия</a>, <a href="/janr/index_janr_10-1.shtml">Переводы</a>
#<li><a href=/type/index_type_4-1.shtml>Очерк</a>:
if (step==3) {
if(match($0, /<li><a href=\/type\/index_type_.+<\/a>: /, aj)){
fErr=""
step=4
next
}
if (namT=="\"Информация•о•владельце•раздела\"") { # тут жанров нет в прнципе!
fErr=""
step=4
next
}
}
#6 arcN["namA"] кол-во архивов (0..999)
#7 pagN["namT"] номер нужной/последней страницы гостевой (1..26)
#<center><small> Отсортировано по:[убыванию][<a href=/comment/k/koshienko_a_g/kniga3?ORDER=reverse>возрастанию</a>]</small></center><center><b>Страниц (8):</b> <b>1</b> <a href=/comment/k/koshienko_a_g/kniga3?PAGE=2>2</a> <a href=/comment/k/koshienko_a_g
# … <b>Страниц (2) …
# … <b>Архивы (46) …
if ((step-3)>0) { # навигация есть ТОЛЬКО если ВОЗМОЖНА пересортировка (даже невидимого-с;)
if ( index( $0, "> Отсортировано по:[" )) { # в СИ (по умолчанию) сортировка по убыванию,
if ( match($0,/<b>Страниц \(([0-9]{1,2})\)/, aj ) ) {
pagN=aj[1]
if ( match($0,/<b>Архивы \(([0-9]+)\)/, aj ) ) {
arcN=aj[1]
}
}
if ((pagN-26)>0) pagN=26
modSI=index($0," по:[убыванию") # признак сортировки: 0==прямая, >0==обратная (по умолчанию)
}
#1 aDat(11) дата нужной/последней реплики в интервале, в гостевой (2018.07.20)
#4 rNum(5) - номер нужной/последней реплики в интервале, в гостевой (0..1012, может быть пусто "-")
#"<small>91.</small> <b>Алена Николаева</b> <small><i>2018/07/03 12:23 </i> ") {
if ( match($0,/<small>([0-9]+)\.<\/small>/, aj ) ) {
step++
rNum=aj[1] # номер очередной реплики ("91")
aDat=getDat($0) # дата очередной реплики ("2018,07,03)
if(modSI) exit
else {
if (!chkN) exit
else if ((rNum-chkN)>=0) exit # первая в границах
}
}
}
}
END{
if(fErr!="") print("] err:"fErr,fNam) # у нас проблема
print(sprintf("%11s%5s%5s%3s",aDat,arcN,rNum,pagN),gFil)
}
Имя файла скрипта: "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>siTopTexts</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> ❄ С новым годом! <font color=white>❄"> fOut
# print "<font size=+2 color=lime>Happy New Year! ❄ </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> NB."> fOut
# print "В <a href=/comment/"nUrl"/si_top500look-curr>гостевой</a>"> fOut
# print "(реплика #58.) - <font color=brown>ОПРОС..."> fOut # <font color=brown>
# print "</font>Мне интересно ваше мнение. :-! </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 " " " <br>" > fOut
print " / \\ / \\ <br>" > fOut
print " "---"---"---" <br>" > fOut
print " \\ / <br>" > fOut
print " " <br>" > fOut
print " / \\ <br>" > fOut
print " "---" </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)" "
print "<td> за 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 ) """; j1 = substr( j1, n+1 ) }
j1=j2 j1
return( j1 )
}
function unquot(j1) { # восстановление литерала "жанр(ы), свёрнутого при сборе сведений с СИ
j2="" # '"' -> '"'
while(n=index(j1,""")) { j2 = j2 substr( j1, 1, n-1 ) "\""; j1 = substr( j1, n+6 ) }
j1=j2 j1
return( j1 )
}
END{ # данные загружены и разобраны, оформляем рейтинг и приложения...
if(ARGV[1]==""){
print "NO input file!" # защита от случайного пуска
exit -1
}
if(hold=="") {
print "NO date to bind guesbooks (no ';m' in 1-st line)"
exit -1
}
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 |
/\/.\/.\/. | ) |