目錄
- 一. 需求
- 二. 分析
- 2.1 思路分析
- 2.2 技術點
- 三. 代碼
- 四. 效果
一. 需求
?有網站如下所示,先要求從按照關鍵詞搜索到的網頁中,提取出所有的磁力鏈接。
二. 分析
2.1 思路分析
- 打開網頁之后,從網頁中先提取出所有的標題相關的url
- 然后再打開所有提取到的url
- 再從每一個新打開的頁面中獲取磁力鏈接所在a標簽的href屬性值
2.2 技術點
Invoke-WebRequest
:發送網絡請求workflow
- workflow 是一種特殊的語法結構,用于創建并發執行的工作流。工作流允許你定義一系列步驟,這些步驟可以同時執行或并行執行,適用于需要處理大量數據或需要在多個計算資源上執行任務的情況。
- 在 foreach -parallel 循環內并行執行多個任務,從而加快處理速度。
InlineScript { ... }
:內聯腳本塊用于在工作流中執行本地 PowerShell 腳本或命令。
Add-Type -Path ".\xxx.dll"
:用于引入第三方dllNew-Object HtmlAgilityPack.HtmlDocument
:用于創建引入的庫中的對象HtmlAgilityPack
:用于解析html文本的第三方庫- 官網:https://github.com/zzzprojects/html-agility-pack/releases/tag/v1.11.61
- 下載源碼后,手動編譯 HtmlAgilityPack.Net40,得到 HtmlAgilityPack.dll
.DocumentNode.SelectSingleNode
:用于配合XPATH語法解析html文本[System.Uri]::EscapeDataString($搜索關鍵詞)
- 搜索的關鍵字是中文,實際發送請求時,需要把中文轉換
三. 代碼
param(# 參數必須輸入[Parameter(Mandatory)]# 當未添加 -name 參數時,腳本會報錯[string]$搜索關鍵詞
)# 域名
$domain = 'http://www.kisssub.org'
# 搜索關鍵字,通過 [System.Uri]::EscapeDataString 對漢字進行編碼
$enCoded_search_keyword = [System.Uri]::EscapeDataString($搜索關鍵詞)
# 請求地址
$request_url = "$($domain)/search.php?keyword=$($enCoded_search_keyword)"# session
$session = New-Object Microsoft.PowerShell.Commands.WebRequestSession
$session.UserAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36"
$session.Cookies.Add((New-Object System.Net.Cookie("user_script_url", "%2F%2F1.acgscript.com%2Fscript%2Fmiobt%2F4.js%3F3", "/", "www.kisssub.org")))
$session.Cookies.Add((New-Object System.Net.Cookie("user_script_rev", "20181120.2", "/", "www.kisssub.org")))# 請求頭
$request_header = @{"Accept"="text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9""Accept-Encoding"="gzip, deflate""Accept-Language"="zh-CN,zh;q=0.9,ja;q=0.8,en;q=0.7,zh-TW;q=0.6""Cache-Control"="no-cache""Pragma"="no-cache""Upgrade-Insecure-Requests"="1"
}# 獲取磁力鏈接所在頁面的URL
function Get_WEB_URL {param ([string]$url, [Microsoft.PowerShell.Commands.WebRequestSession]$session, [PSCustomObject]$header)# 發送網絡請求$response = Invoke-WebRequest -UseBasicParsing `-Uri $url `-WebSession $session `-Headers $header# 若響應code不是200,則證明網絡連接失敗if ($response.StatusCode -ne 200) {Write-Host "網絡請求失敗..."return }# 提取磁力鏈接所在頁面的url$target_web_urls = $response.Links.outerHTML | ForEach-Object {# 若不是對應頁面的url,則跳過if (-not ($_ -match ".*show.*.html")) {return}# 提取出目標頁面的url$_.split(" ")[1].replace("href=`"", "$($domain)/").replace("`"", "")}return $target_web_urls
}# 指定url,session,header 發送網絡請求
$target_web_urls = Get_WEB_URL -url $request_url -session $session -header $request_header
$target_web_urls | Out-Host<#?創建一個workflow,用于并發處理多任務
#>
workflow Get-WebContent {param ([string[]] $urls)<#?foreach -parallel 是 Workflow 中用來并行處理迭代集合的語法每個 $url 都會并行處理,即同時發送多個請求以提高效率#>foreach -parallel ($url in $urls) {# 睡眠1秒# Start-Sleep -Seconds 1# ?InlineScript 塊允許在 Workflow 中執行本地的 PowerShell 腳本或命令$web_response = InlineScript {# 發送網絡請求$webRequest = Invoke-WebRequest -UseBasicParsing -Uri $using:url -Headers $my_header# 獲取頁面上的所有url連接$webRequest.Links.outerHTML}# PSCustomObject 是自定義對象的數據類型[PSCustomObject]@{Content = $web_response}}
}Write-Host "????????????提取到的磁力鏈接如下????????????" -ForegroundColor Red# 引入 HtmlAgilityPack.dll 依賴庫
Add-Type -Path ".\HtmlAgilityPack.dll"
# 創建 HtmlDocument對象 用于解析html文本
$htmlDoc = New-Object HtmlAgilityPack.HtmlDocument# 調用workflow,獲取響應
$results = Get-WebContent -urls $target_web_urls
$results.Content | ForEach-Object {# 如果不是磁力鏈接的url,就跳過if (-not ($_ -match ".*ref=`"magnet.*")) {return}# 將含有磁力鏈接的html文本放到 HtmlDocument對象 中$htmlDoc.LoadHtml($_)<#?通過xpath語法提取到a標簽對象SelectSingleNode只能提取單節點SelectNodes可以提取多個節點#>$aEelement = $htmlDoc.DocumentNode.SelectSingleNode("//a[@id='magnet']")<#?根據id獲取href屬性(磁力鏈接內容)第2個參數是默認參數#>$aEelement.GetAttributeValue("href", "")
} | Get-Unique# 暫停
Pause
四. 效果
- 只是簡易爬蟲,并未做IP代理池和cookie池等防反扒機制
- 頻繁使用,在一段時間內會無法訪問該網站