我试图使用PowerShell组建一个网站抓取工具,它将返回页面上的所有链接,但我收到了一些意想不到的错误,这似乎与我处理递归的方式有关。 / p>
代码如何工作的简要说明如下:
获取特定网页上的所有链接。
比较在搜索到的所有链接中找到的所有链接,只返回尚未搜索过的链接,并过滤掉指定域外的所有链接。
如果还有一个或多个尚未搜索的有效链接,请从列表中返回第一个搜索链接。如果没有更多有效的搜索链接,请返回“NoMoreLinks”。
如果'NoMoreLinks'然后返回最终结果,否则使用新的搜索URL递归到第1步。
主要问题似乎与存储结果的使用方式有关。我将要分享相当多的代码,所以我不希望有一个人解决这个问题,但任何与设计/实现改进相关的建议都会受到欢迎。
当前代码:
Clear-Host
$finalres = @()
Function Get-WebsiteObject {
param (
[Parameter(Mandatory)]
[string] $searchedUrl,
[Parameter(Mandatory)]
[string] $outerText,
[Parameter(Mandatory)]
[string] $href
)
$WebsiteObject = New-Object System.Object
$WebsiteObject | Add-Member -MemberType NoteProperty -Name searchedUrl -Value $searchedUrl
$WebsiteObject | Add-Member -MemberType NoteProperty -Name outerText -Value $outerText
$WebsiteObject | Add-Member -MemberType NoteProperty -Name href -Value $href
$WebsiteObject
}
Function Get-WebsiteLinks {
param (
[Parameter(Mandatory)]
[string] $inputUrlString
)
begin {
$returnUrlArray = @()
}
process {
(Invoke-WebRequest -Uri $inputUrlString).Links | % {
$outerText = $_.outerText
$href = if ( $_.href.Substring(0,1) -eq '/' ) { ($inputUrlString + $_.href).ToLower() } else { $_.href.ToLower() }
#$innerText = $_.innerText
#$outerHTML = (($_.outerHTML) -replace "`t", '') -replace "`n", ''
#$tagName = $_.tagName
$returnUrlArray += (Get-WebsiteObject -searchedUrl $inputUrlString -outerText $outerText -href $href)
}
}
end {
$returnUrlArray
}
}
Function Get-SearchLinks {
# Input: All found links, all previously searched links
# Output: A link that hasn't been searched yet, or an empty string if no further URLs to search
param (
[Parameter(Mandatory)]
[string[]] $allLinks,
[Parameter(Mandatory)]
[string[]] $allSearchedLinks,
[Parameter(Mandatory)]
[string] $linkFilter
)
begin {
$returnUrlString = 'NoMoreURLs'
}
process {
#N.B. PassThru used to get values from Compare-Object rather than a comparison table
$firstUnsearchedUrl = ((Compare-Object -ReferenceObject $allLinks -DifferenceObject $allLinks -PassThru) | ? { $_ -like "*" + linkFilter + "*" } | Select -First 1 )
if ($firstUnsearchedUrl.Length -ne 0) {
$returnUrlString = $firstUnsearchedUrl.ToLower()
}
}
end {
$returnUrlString
}
}
Function Get-AllWebsiteLinks {
params (
[Parameter(Mandatory)]
[string] $startUrl,
[Parameter(Mandatory)]
[string] $domainFilter #Only search for links in this domain, to stop searching the whole web!
)
#Initial
if ($finalres.Length -eq 0) {
$finalres += (Get-WebsiteObject -searchedUrl $startUrl.ToLower() -outerText '[Homepage]' -href $startUrl.ToLower())
$finalres = Get-WebsiteLinks -inputUrlString $startUrl.ToLower()
}
$allLinks = $finalres.href.ToLower() | Sort-Object | Get-Unique
$allSearchLinks = $finalres.searchedUrl | Sort-Object | Get-Unique
$searchUrl = Get-SearchLinks -allLinks $allLinks -allSearchedLinks $allSearchLinks -linkFilter $domainFilter
Write-Output $searchUrl
if ($searchUrl -eq 'NoMoreURLs') {
$finalres | Out-GridView
}
else {
$finalres += Get-WebsiteLinks -inputUrlString $searchUrl
Get-AllWebsiteLinks -startUrl $searchUrl -domainFilter $domainFilter
}
}
Get-AllWebsiteLinks -startUrl 'http://webscraper.io/test-sites/e-commerce/allinone' -domainFilter 'webscraper.io'
感谢。