[英]wget: Trawl sample space of 100000000, max 100 results returned
不确定这是堆栈还是代码审查,因为我对这个问题的方法完全不同,虽然我已经开始使用PowerShell,但我并不喜欢特定的语言或风格。
我目前正在使用我们无权访问后端的Web服务器。
它返回基于左对齐过滤器生成的证书列表,例如,如果您在搜索框中键入100并单击提交,它将搜索以100 *开头的所有证书,或者范围10000000 - 10099999
我们所有的证书都是八位数字,样本空间为00000000-99999999。 我试图在这个示例空间中找到哪些证书确实存在,因为证书名称必须是唯一的。
主要的警告是服务器将只返回前100个结果,如果由于在该范围内存在超过100个现有证书而导致查询返回的结果超过许多结果,则会丢弃附加内容。
我的第一种方法是使用wget(技术上是PowerShell的Invoke-WebRequest)并遍历查询范围000000到999999(每次100个),这是有效的,我正在进行9月中旬完成。
不幸的是,有些人希望更快地获得这些数据,所以我不得不编写一个递归函数(使用我的默认输入)一次查询一个1000万个证书的大样本空间并搜索逐渐变小的空间,直到返回<99个证书对于每个子空间,然后进入下一个千万。
数据不是均匀分布或非常可预测的,“大多数”(~90%?)证书聚集在10000000-19999999和30000000-39999999附近,但我需要它们。
这是我正在使用的功能,它似乎正在工作(结果写入文件,比以前更快),但它仍在进行中。 有没有:
变量'$ certsession'在此代码段之外建立,代表Web服务器会话(登录信息,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中执行此操作的一些方法的摘要。
这是当前行为的一个例子。 值得注意的是,整个1000万范围的00000000-09999999具有少于98个证书,因此无需递归即可进行处理。
将我的评论转到答案:
第一个建议:获得授权访问后端。
性能提升的最大空间是多个客户端的线程/拆分工作。 因为它只是一个很大的数字空间你可以轻松地:
代码$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)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.