PowerShell:关于构造递归函数以返回网站上所有网址的建议

时间:2017-10-07 09:13:50

标签: powershell recursion web-scraping

我试图使用PowerShell组建一个网站抓取工具,它将返回页面上的所有链接,但我收到了一些意想不到的错误,这似乎与我处理递归的方式有关。 / p>

代码如何工作的简要说明如下:

  1. 获取特定网页上的所有链接。

  2. 比较在搜索到的所有链接中找到的所有链接,只返回尚未搜索过的链接,并过滤掉指定域外的所有链接。

  3. 如果还有一个或多个尚未搜索的有效链接,请从列表中返回第一个搜索链接。如果没有更多有效的搜索链接,请返回“NoMoreLinks”。

  4. 如果'NoMoreLinks'然后返回最终结果,否则使用新的搜索URL递归到第1步。

  5. 主要问题似乎与存储结果的使用方式有关。我将要分享相当多的代码,所以我不希望有一个人解决这个问题,但任何与设计/实现改进相关的建议都会受到欢迎。

    当前代码:

    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'
    

    感谢。

0 个答案:

没有答案
相关问题