wget: Trawl образец пространства 100000000, максимальное 100 результатов возвращено

59
6

Не уверен, что это проверка стека или кода, так как я открыт для совершенно разных подходов к проблеме и, хотя я начал с PowerShell, не привязан к определенному языку или стилю.

В настоящее время я работаю с веб-сервером, на котором у нас нет доступа к заднему концу.

Он возвращает список сгенерированных сертификатов на основе фильтра с левым выравниванием, например, если вы наберете 100 в поле поиска и нажмите "Отправить", он будет искать все сертификаты, начинающиеся со 100 *, или диапазон 10000000 - 10099999

Все наши сертификаты - это восьмизначные числа, дающие пробел в 00000000-99999999. Я пытаюсь найти, какие сертификаты в этом пространстве образца действительно существуют, поскольку имена сертификатов должны быть уникальными.

Основная оговорка заключается в том, что сервер будет возвращать только первые 100 результатов, если ваш запрос возвращает больше, чем многие результаты из-за наличия более 100 существующих сертификатов в этом диапазоне, дополнительные функции отбрасываются.

Мой первый подход состоял в том, чтобы просто использовать wget (технически PowerShell Invoke-WebRequest) и перебирать диапазон запросов от 000000 до 999999 (100 за раз), который работал, и я был на пути к середине сентября.

К сожалению, есть люди, которые хотят получить эти данные раньше, поэтому мне пришлось написать рекурсивную функцию, которая (с моим вводом по умолчанию) запрашивает сразу несколько пробных мест с десятью миллионами сертификатов и ищет постепенно меньшую площадь до тех пор, пока не вернется <99 сертификатов для каждого подпространства, затем переместимся на следующие десять миллионов.

Данные не равномерно распределены или очень предсказуемы, а большинство "(90%?)) Объединяют около 10000000-19999999 и 30000000-39999999, но мне все они нужны.

Здесь функция, которую я сейчас использую, кажется, работает (результаты записываются в файл и быстрее, чем раньше), но она по-прежнему продолжается. Есть ли:

Глядя на ошибки с помощью функции Лучший выбор входных данных (для повышения эффективности) Совершенно разные подходы, которые были бы лучше

Переменная "$ certsession" устанавливается вне этого фрагмента и представляет сеанс веб-сервера (информация для входа, файлы cookie и т.д.).

function RecurseCerts ($min,$max,$step,$level) {
for ($certSpace = $min; $certSpace -le $max; $certSpace += $step) {
$levelMultiplier = "0" * $level
#Assuming a level of 3, these ToString arguments would turn a '5' into 005, a '50' into 050, and so on. Three or more digit numbers are unchanged.
$query = ($certSpace).ToString($levelMultiplier)
$resultsArray = New-Object System.Collections.ArrayList
"Query is $query"
#Get webpage, split content by newline, search for lines with a certificate common name and add them to the results array
Invoke-WebRequest -uri "https://webserver.com/app?service=direct%2F1%2FSearchPage%2F%24Form&sp=S0&Form0=%24TextField%2C%24Submit&%24TextField=$query&%24Submit=Search" -websession $certsession | %{$_.content -split "'n" | %{if ($_ -match "cn=(.*?),ou") {$resultsArray = $resultsArray + $matches[1]}}}
#If we got more than 98 results for our query, make the search more specific, until we don't get more than 98 (else condition).
if ($resultsArray.count -gt 98) {"Recursing at $certSpace"; $subLevel = $level + 1; $subSpace = $certSpace * 10; RecurseCerts -min $subSpace -max ($subSpace + 9) -step 1 -level $subLevel}
#This is the most specific 0-98 for this range, write it out to the file
else {"Completed range $certspace"; $resultsArray | out-file c:\temp\certlist.txt -encoding utf8 -append}
}
}

#Level 3 means include rightmost 3 digits eg. search 101 for range 10100000 - 10199999
#Level 4 would be the subspace 1010-1019 (so a search for 1015 returns 10150000 - 10159999)
RecurseCerts -min 0 -max 9 -step 1 -level 1

Поскольку я добавил "языковой агностик", не стесняйтесь запрашивать все необходимые разъяснения PowerShell. Я также мог бы попытаться переписать его в псевдокоде, если это необходимо.

Я думаю, что тот факт, что диапазоны уже итерации должны предотвращать дублирование, когда это делается с подпространством и возвращается к более высокому уровню (повторное захват вещей, которые он уже захватил на более низком уровне, должен быть предотвращен), но я буду лгать, если Я сказал, что полностью понял поток программы здесь.

Если окажется, что есть дублирование, я могу просто фильтровать текстовый файл для дубликатов. Однако меня все равно интересуют подходы, которые устраняют эту проблему, если она существует.

* Я обновил код, чтобы отобразить индикатор прогресса на консоли, и на основе предложений также изменился тип массива, используемый для arraylist. Сервер довольно хрупок, поэтому на данный момент я избегал многопоточности, но обычно это была бы полезная функция таких задач - вот резюме некоторых способов сделать это в PowerShell.

Вот пример поведения в настоящее время. Примечательно, что весь десятимиллионный диапазон 00000000 - 09999999 имел менее 98 сертификатов и, таким образом, обрабатывался без необходимости рекурсии.

Поведение RecurseCerts

спросил(а) 2016-09-08T05:34:00+03:00 4 года, 2 месяца назад
1
Решение
109

Перемещение моих комментариев к ответу:

    Первое предложение: иметь право доступа к заднему концу.

    Большая комната для повышения производительности - это многопоточность/разделение на несколько клиентов. Поскольку это просто большое количество чисел, вы можете легко:

      работают два процесса PowerShell, поиск 00000000-49999999 в одном и 50000000-99999999 в другом (или столько процессов, сколько вы хотите). у вас есть два компьютера, если у вас есть другие пользователи используйте многопроцессорность PowerShell (потоки, задания, рабочие процессы), хотя они более сложны в использовании. Так как это в основном будет медлительность между серверами и сетью, возможно, это не стоит более сложных методов, но сценарий с номерами начала и конца и запускать его дважды будет довольно простым.

    Код $resultsArray = $resultsArray + $matches[1] очень медленный; массивы неизменяемы (фиксированный размер), поэтому PowerShell создает новый массив и копирует в него массив. В цикле, добавив много тысяч вещей, у него будет много накладных расходов. Вместо этого используйте $a = [System.Collections.ArrayList]@() и $a.Add($thing).

    Как быстро сервер может ответить (это в локальной сети или в Интернете)? Если по WAN-соединению существует ограничение на латентность, насколько быстро вы можете пойти, но если он ищет большую базу данных и занимает некоторое время, чтобы вернуть страницу, это ограничивает то, что вы можете ускорить с клиентской стороны.

    Насколько велика страница ответов? Invoke-WebRequest анализирует HTML в полной DOM, и он очень медленный, и вы не используете DOM, поэтому вам это не нужно. Вы можете использовать [System.Net.WebClient] для загрузки содержимого в виде строки:

например

$web = New-Object System.Net.WebClient
$web.DownloadString($url)
    С точки зрения дизайна, сколько сертификатов вы ожидаете в пространстве поиска 100M? 10k? 50М? Ваша рекурсивная функция подвергает риску поиск и вытягивание и игнорирование одних и тех же сертификатов снова и снова, пытаясь опуститься ниже 100. В зависимости от дистрибутива у меня возникнет соблазн искать и блокировать самые большие куски с помощью 0 сертификатов. Если вы можете исключить диапазон 1M в одном запросе, который чрезвычайно полезен. Поиск 1M, нахождение слишком большого количества сертификатов, поиск 500K, слишком много, [...] поиск 10K нахождение слишком много, кажется расточительным и медленным.

ответил(а) 2016-09-10T08:40:00+03:00 4 года, 2 месяца назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема