我正试图使用此代码在PowerShell中使用正则表达式抓取网页:
$webClient = New-Object System.Net.WebClient
$data = $webClient.downloadstring($url)
$h1Tag = [regex] '(?i)(?<=<h1 class="mb-0 mb-lg-1 svelte-jcq9ad">)([Ss]*?)(?=</h1>)'
$h1 = $h1Tag.Match($data).value.trim()
要搜索的示例文本:
<div>
<h1 class="mb-0 mb-lg-1 svelte-jcq9ad">AdBlock — best ad blocker</h1>
<h2 class="mb-2 svelte-jcq9ad">Block ads and pop-ups on YouTube, Facebook, Twitch, and your favorite websites.</h2>
</div>
</div>
它正确返回AdBlock -最佳广告拦截器当我在几个正则表达式测试站点上测试正则表达式时,但在PowerShell中$h1总是空的。我错过了什么?
编辑:我在我的问题中将$title更新为$h1。$title是我打错了——$h1才是我应该写的。试试这个:
$data = '<div>
<h1 class="mb-0 mb-lg-1 svelte-jcq9ad">AdBlock — best ad blocker</h1>
<h2 class="mb-2 svelte-jcq9ad">Block ads and pop-ups on YouTube, Facebook, Twitch, and your favorite websites.</h2>
</div>
</div>'
$null = $data -match("AdBlock — best ad blocker")
$h1 = $Matches.Values
重要的事情先说:
- 如果可能的话,最好使用专用的HTML解析器,这样可以实现比基于正则表达式的解析器更健壮的解决方案,因为基于正则表达式的解析器总是很脆弱——参见iRon对这个问题的评论。
如前所述,您的regex不能处理示例输入,这意味着示例输入不能代表您的实际问题。
下面的可以解决您的问题,因为它使用了更灵活的regex的重新表述还展示了在PowerShell中执行单个正则表达式匹配的惯用方法。,使用-match
操作符:
$data = '<div>
<h1 class="mb-0 mb-lg-1 svelte-jcq9ad">AdBlock — best ad blocker</h1>
<h2 class="mb-2 svelte-jcq9ad">Block ads and pop-ups on YouTube, Facebook, Twitch, and your favorite websites.</h2>
</div>
</div>'
$h1 =
if ($data -match '(?s)(?<=<h1s+class=[''"]mb-0s+mb-lg-1s+svelte-jcq9ad[''"]s*>)(.*?)(?=</s*h1>)') {
# Output the trimmed form of the match, which is stored in entry 0
# of the automatic $Matches variable.
$Matches[0].Trim()
}
# Output the result.
$h1
注意:
-match
默认是大小写不敏感的(所有与文本相关的PowerShell操作符也是如此),因此不需要(?i)
内联选项。然而,添加了内联选项
(?s)
,以便允许.
也匹配换行,从而避免了[sS]
解决方案的需要。/
在PowerShell中从不需要转义(如/
),因为正则表达式被指定为普通的字符串字量(其中/
没有特殊含义)。regex在空格方面变得更加灵活(强制空格表示为
s+
,可选空格表示为s*
,以及引号字符('
和"
都是匹配的)。有关详细解释和使用正则表达式进行实验的能力,请参阅regex101.com页面。
注意:链接页面使用c#字符串语法,但字符串内容与上面的相同(PowerShell和c#都使用。net正则表达式引擎)。