目录
- 一. 需求
- 二. 分析
- 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池等防反扒机制
- 频繁使用,在一段时间内会无法访问该网站