Авторедактирование списка url-ов на основе HTTP статус кодов
Модераторы: Avada, CaptainFlint, Nik, d-view, Моторокер
Авторедактирование списка url-ов на основе HTTP статус кодов
Хочется иметь скрипт, который будет брать список url-ов из буфера обмена, проверять их на http статус коды, отсеивать url-ы, возвращающие статусы 404, и помещать отредактированный список url-ов обратно в буфер обмена. Нужно чтобы очистить список веб-адресов от неработающих сайтов и веб-страниц. И делать это нужно будет регулярно, поэтому требуется кнопка.
Буду очень признателен за скрипт, если кто-то из скриптописателей это сможет реализовать. Спасибо.
Буду очень признателен за скрипт, если кто-то из скриптописателей это сможет реализовать. Спасибо.
Батник (внутри вызывает повершелл) фильтрует урлы в буфере по валидным кодам возврата (2хх, 3хх - другие коды вызывают исключение внутри GetResponse):
(добавлены установка метода HEAD и окошко сообщения в конце)
Код: Выделить всё
@echo off
set "ARG_0=%~dpnx0"
powershell.exe -NoProfile -STA "iex (([IO.File]::ReadAllText($Env:ARG_0)) -replace '^(.*\n)*?.*<::::>.*\n', '')" & goto :EOF
Add-Type -Assembly System.Windows.Forms;
function testUrl($url, $timeout) {
try {
$webReq = [Net.WebRequest]::Create($url);
$webReq.Method = 'HEAD';
$webReq.Timeout = $timeout;
$webRsp = $webReq.GetResponse();
$webRsp.Close();
Write-Host "``$url``: $([int]$webRsp.StatusCode)";
$true;
}
catch {
Write-Host "``$url``: $_";
}
}
$urls = [Windows.Forms.Clipboard]::GetText() -split '\r?\n';
$goodUrls = @($urls | ? { $_ -match '^\w+://' -and (testUrl $_ $timeout) });
if ([Windows.Forms.MessageBox]::Show("Please click OK to copy $($goodUrls.Length) of $($urls.Length) urls to clipboard.", 'Url Filter', 1) -eq 1) {
[Windows.Forms.Clipboard]::SetText(($goodUrls -join "`n") + "`n");
}
Последний раз редактировалось MVV Чт янв 26, 2017 23:09, всего редактировалось 2 раза.
Попробуй использовать метод HEAD, чтобы не грузить данные:
Также можно уменьшить значение $timeout, чтобы меньше ждать ответа от мертвых серверов, но при маленьком значении живые адреса могут тоже быть отсеяны.
Код: Выделить всё
$webReq = [Net.WebRequest]::Create($url);
$webReq.Method = 'HEAD';
...
Последний раз редактировалось MVV Чт янв 26, 2017 22:42, всего редактировалось 1 раз.
MVV
А где это в скрипте прописать?
Вставить нужно выше или ниже этого куска кода?
А где это в скрипте прописать?
Вставить нужно выше или ниже этого куска кода?
Код: Выделить всё
$webReq = [Net.WebRequest]::Create($url);
$webReq.Timeout = $timeout;
$webRsp = $webReq.GetResponse();
$webRsp.Close();
Write-Host "``$url``: $([int]$webRsp.StatusCode)";
$true;Вставить нужно 1 новую строку (установка метода) после 1 уже имеющейся (создание объекта).
Ещё можно перед последней строкой (копирование в буфер) добавить отображение окошка, чтобы забивать буфер после долгой операции только по команде (писать можно и по-русски, но тогда необходимо сохранить файл в кодировке UTF-8 без BOM):
В общем, отредактировал скрипт в своём посте.
Ещё можно перед последней строкой (копирование в буфер) добавить отображение окошка, чтобы забивать буфер после долгой операции только по команде (писать можно и по-русски, но тогда необходимо сохранить файл в кодировке UTF-8 без BOM):
Код: Выделить всё
$null = [Windows.Forms.MessageBox]::Show("Please click OK to copy $($goodUrls.Length) good urls to clipboard.", 'Url Filter');MVV
Сделал все это, скорость теперь примерно 1 url за одну секунду.
С таймаутом можно поэкспериментировать, но в принципе большая часть ссылок - и так живые, так что они отвечают в пределах 1-2 секунд, так что уменьшение таймаута не особо поможет.
А можно ли сделать так, чтобы батник обрабатывал ссылки в несколько проходов, то есть не по одной ссылке за один раз, а чтобы было 10 процессов и соединений, которые обрабатывают ссылки? Я не программист и не знаю как корректно это описать. Приведу пример. Есть downloader manager-ы, которым можно скормить тонну url-ов и можно там в настройках прописать количество соединений, например 10, тогда они скачивают по 10 файлов за один раз. Так и здесь нельзя применить тот же принцип?
Сделал все это, скорость теперь примерно 1 url за одну секунду.
С таймаутом можно поэкспериментировать, но в принципе большая часть ссылок - и так живые, так что они отвечают в пределах 1-2 секунд, так что уменьшение таймаута не особо поможет.
А можно ли сделать так, чтобы батник обрабатывал ссылки в несколько проходов, то есть не по одной ссылке за один раз, а чтобы было 10 процессов и соединений, которые обрабатывают ссылки? Я не программист и не знаю как корректно это описать. Приведу пример. Есть downloader manager-ы, которым можно скормить тонну url-ов и можно там в настройках прописать количество соединений, например 10, тогда они скачивают по 10 файлов за один раз. Так и здесь нельзя применить тот же принцип?
Hjkma
Этот способ пингования называется асинхронным.
Темповый файл стоит на дозаписи, по достижению лимита счётчика содержимое выбрасывается в буфер.
Этот способ пингования называется асинхронным.
Темповый файл стоит на дозаписи, по достижению лимита счётчика содержимое выбрасывается в буфер.
Автору сборки TC Image (Andrey_A) настоятельно рекомендуется не распространять на иных ресурсах любую предоставленную мной где-либо техническую информацию по автоматизации и оптимизации в работе с ТС и системой.
Может, MVV устал и ушел спать? 
С асинхронностью будет как-то так:
Таймаут и число потоков можно поменять, но если скрипт исчерпает лимит полуоткрытых соединений, могут быть проблемы.
С асинхронностью будет как-то так:
Код: Выделить всё
@echo off
set "ARG_0=%~dpnx0"
powershell.exe -NoProfile -STA "iex (([IO.File]::ReadAllText($Env:ARG_0)) -replace '^(.*\n)*?.*<::::>.*\n', '')" & goto :EOF
Add-Type -Assembly System.Windows.Forms;
function testUrls($urls, $timeout, $workerCount = 2) {
$job = @{
queue = [Collections.Queue]::Synchronized((New-Object Collections.Queue (, $urls)));
list = [Collections.ArrayList]::Synchronized((New-Object Collections.ArrayList));
timeout = $timeout;
};
Write-Host "Checking $($urls.Length) urls using $workerCount workers...";
$workerScript = {
$job = $args[0];
try {
while (1) {
$url = $job.queue.Dequeue();
try {
$webReq = [Net.WebRequest]::Create($url);
$webReq.Method = 'HEAD';
$webReq.Timeout = $job.timeout;
$webRsp = $webReq.GetResponse();
$webRsp.Close();
$null = $job.list.Add($url);
"$url`: $($webRsp.StatusCode)";
}
catch {
"$url`: $_";
}
}
}
catch {}
};
$workers = @((1 .. $workerCount) | % { $w = [PowerShell]::Create().AddScript($workerScript).AddArgument($job); @{ w = $w; r = $w.BeginInvoke() } });
$workers | % { Write-Host ($_.w.EndInvoke($_.r) -join "`n") };
$job.list;
}
$timeout = 10000;
$workerCount = 10;
$urls = @([Windows.Forms.Clipboard]::GetText() -split '\r?\n' | ? { $_ -match '^\w+://' });
$startTime = [DateTime]::Now;
$goodUrls = @(testUrls $urls $timeout $workerCount);
$workTime = [int]([DateTime]::Now - $startTime).TotalSeconds;
if ([Windows.Forms.MessageBox]::Show("Approved $($goodUrls.Length) of $($urls.Length) urls in $workTime seconds.`nPlease click OK to copy urls to clipboard.", 'Url Filter', 1) -eq 1) {
[Windows.Forms.Clipboard]::SetText(($goodUrls -join "`n") + "`n");
}MVV
Новый скрипт обработал 1925 ссылок за 6 минут. То есть, скорость получилась 1 секунда = 5 ссылок. В принципе, приемлемо.
Но есть проблема: старый вариант из тех 1925 ссылок возвращал 1217 работающих ссылок. Новый вариант вернул 1160 ссылок. Я нашел ссылки, которых вернул старый скрипт и не вернул новый скрипт, они все работающие, которые возвращают статус 200 и которые открываются в браузере. Еще раз запустил скрипт, на этот раз из тех же 1925 ссылок он вернул 1124. Что-то не так в скрипте. Могу прислать в ЛС список ссылок для тестирования.
Замечу, что и во время работы старого скрипта, и во время работы нового скрипта у меня все время работает торрент, который на полную скорость качает сериал. Может это влияет?
Upd. В третий раз запустил скрипт, на этот раз поставив число потоков на 5. Вернуло 1205 ссылок. Нормальное значение должно быть - 1217 ссылок. В четвертый раз, на 3 потоков вернуло уже 1217 ссылок. В пятый раз, на 3 потоков выдало цифру в 1215 ссылок. Как-то напрягает в работе скрипта, что не до конца уверен в конечном результате, т.к. скрипт выдает разные цифры. Может есть возможность встроить в работу скрипта какой-то механизм, который бы предотвращал такие ситуации, например в конце повторно бы перепроверял те ссылки, которых скрипт отсеял?
Новый скрипт обработал 1925 ссылок за 6 минут. То есть, скорость получилась 1 секунда = 5 ссылок. В принципе, приемлемо.
Но есть проблема: старый вариант из тех 1925 ссылок возвращал 1217 работающих ссылок. Новый вариант вернул 1160 ссылок. Я нашел ссылки, которых вернул старый скрипт и не вернул новый скрипт, они все работающие, которые возвращают статус 200 и которые открываются в браузере. Еще раз запустил скрипт, на этот раз из тех же 1925 ссылок он вернул 1124. Что-то не так в скрипте. Могу прислать в ЛС список ссылок для тестирования.
Замечу, что и во время работы старого скрипта, и во время работы нового скрипта у меня все время работает торрент, который на полную скорость качает сериал. Может это влияет?
Upd. В третий раз запустил скрипт, на этот раз поставив число потоков на 5. Вернуло 1205 ссылок. Нормальное значение должно быть - 1217 ссылок. В четвертый раз, на 3 потоков вернуло уже 1217 ссылок. В пятый раз, на 3 потоков выдало цифру в 1215 ссылок. Как-то напрягает в работе скрипта, что не до конца уверен в конечном результате, т.к. скрипт выдает разные цифры. Может есть возможность встроить в работу скрипта какой-то механизм, который бы предотвращал такие ситуации, например в конце повторно бы перепроверял те ссылки, которых скрипт отсеял?
Естественно, если возникает ошибка или таймаут, ссылка отсеивается. А что в консоль выдается по тем ссылкам, которые рабочие, но были отсеяны скриптом?
Если в фоне работает торрент, то это может влиять - особенно если он качает на скорости, близкой к тарифному лимиту.
Чтобы детект работал стабильнее, надо увеличивать таймаут, а также следить, чтобы лимит полуоткрытых соединений не превышался (иначе повершелл просто не сможет открывать новые соединения) - например, можно смотреть открытые соединения в Process Hacker.
Если в фоне работает торрент, то это может влиять - особенно если он качает на скорости, близкой к тарифному лимиту.
Чтобы детект работал стабильнее, надо увеличивать таймаут, а также следить, чтобы лимит полуоткрытых соединений не превышался (иначе повершелл просто не сможет открывать новые соединения) - например, можно смотреть открытые соединения в Process Hacker.
MVV
Так я не могу отследить процессы в консоле, в начале долго стоит надпись "Checking 1925 url using 10 workers", а потом как время работы скрипта подходит к концу, то в консоле очень быстро скопом пролистывается список урлов и их коды состояния и затем консоль завершается.
Попробую увеличить таймаут до 100000 с числом потоков на 10.
Вот про лимит полуоткрытых соединений не понял - у меня же Windows 7, вроде там нет ограничения?
Так я не могу отследить процессы в консоле, в начале долго стоит надпись "Checking 1925 url using 10 workers", а потом как время работы скрипта подходит к концу, то в консоле очень быстро скопом пролистывается список урлов и их коды состояния и затем консоль завершается.
Попробую увеличить таймаут до 100000 с числом потоков на 10.
Вот про лимит полуоткрытых соединений не понял - у меня же Windows 7, вроде там нет ограничения?
По итогам тестирования.
Второй вариант скрипта все время выдает разные результаты, то 1165 ссылок, то 1190, то 1203, сколько бы не увеличивал время таймаута и не уменьшал число потоков. Первый вариант скрипта всегда из тех 1925 ссылок выдает те же 1217 ссылок и все они рабочие. Может что-то в работе второго скрипта не так? Кстати, по консоли ошибся, это окно не исчезает, если не нажимать кнопку "ок", когда предлагают скопировать список ссылок в буфер. Но в консоли показываются не все ссылки, только 300 строк и больше ничего. Правда из тех 300 строк нашлись ссылки, которых скрипт отсеял и они рабочие. Вот их коды состояния
Второй вариант скрипта все время выдает разные результаты, то 1165 ссылок, то 1190, то 1203, сколько бы не увеличивал время таймаута и не уменьшал число потоков. Первый вариант скрипта всегда из тех 1925 ссылок выдает те же 1217 ссылок и все они рабочие. Может что-то в работе второго скрипта не так? Кстати, по консоли ошибся, это окно не исчезает, если не нажимать кнопку "ок", когда предлагают скопировать список ссылок в буфер. Но в консоли показываются не все ссылки, только 300 строк и больше ничего. Правда из тех 300 строк нашлись ссылки, которых скрипт отсеял и они рабочие. Вот их коды состояния
Можно ли что-нибудь прописать в работе скрипта, чтобы сделать его как можно стабильнее? К примеру сделать так, чтобы в конце работы скрипт еще раз обрабатывал ссылки, которые возвращают приведенный выше код ошибки. С одним потоком и увеличенным таймаутом.(ссылка): Исключение при вызове "GetResponse" с "0" арг
ументами: "Невозможно разрешить удаленное имя: '(ссылка)"