我正在尝试编写PowerShell脚本,以便从网站上获取名为“newstitle”的所有类中的文本。
这就是我所拥有的:
function check-krpano {
$geturl=Invoke-WebRequest http://krpano.com/news/
$news=$geturl.parsedhtml.body.GetElementsByClassName("newstitle")[0]
Write-Host "$news"
}
check-krpano
显然需要更多调整,但到目前为止,它不起作用。
我设法使用GetElementById编写脚本,但我不知道GetElementsByClassName的语法,说实话,我还没有找到关于它的更多信息。
注意:
我已经勾选了我的问题的正确答案,但这不是我选择在我的脚本中使用的解决方案。
虽然我能够使用2种方法在包含某个类的标记中找到内容,但它们搜索链接的速度要慢得多。
以下是使用Measure-Command的输出:
所以我将Links方法的答案标记为有用。
这是我的最终剧本:
function check-krpano {
Clear-Host
$geturl=Invoke-WebRequest http://krpano.com/news
$news = ($geturl.Links |Where href -match '\#news\d+' | where class -NotMatch 'moreinfo+' )
$news.outertext | Select-Object -First 5
}
check-krpano
答案 0 :(得分:18)
如果你弄清楚如何让GetElementsByClassName起作用,我想知道。我昨天碰到了这个并没时间用完,所以我想出了一个解决方法:
$geturl.ParsedHtml.body.getElementsByTagName('div') |
Where {$_.getAttributeNode('class').Value -eq 'newstitle'}
答案 1 :(得分:18)
getElementsByClassName
不会直接返回数组,而是通过COM代理结果。如您所知,使用[]
运算符不能自动转换为数组。您可以使用列表评估语法@()
将其强制转换为数组,以便您可以访问各个元素:
@($body.getElementsByClassName("foo"))[0].innerText
另外,如果您使用对象管道,则会自动执行转换 ,例如:
$body.getElementsByClassName("foo") | Select-Object -First 1
它也是使用foreach
构造自动执行的:
foreach ($element in $body.getElementsByClassName("foo"))
{
$element.innerText
}
答案 2 :(得分:3)
在我的生活中,不能让这种方法发挥作用!
根据您在结果中需要的内容,这可能会有所帮助;
function check-krpano {
$geturl=Invoke-WebRequest http://krpano.com/news
$news=($geturl.Links|where href -match '\#news\d+')[0]
$news
}
check-krpano
给我回复:
innerHTML : krpano 1.16.5 released
innerText : krpano 1.16.5 released
outerHTML : <A href="#news1165">krpano 1.16.5 released</A>
outerText : krpano 1.16.5 released
tagName : A
href : #news1165
当然,您可以直接使用这些属性,因此如果您只想知道最近发布的krpano版本,可以这样做:
function check-krpano {
$geturl=Invoke-WebRequest http://krpano.com/news
$news=($geturl.Links|where href -match '\#news\d+')[0]
$krpano_version = $news.outerText.Split(" ")[1]
Write-Host $krpano_version
}
check-krpano
在撰写本文时会返回1.16.5
。
希望以不同的方式实现你想要的东西。
编辑:
这可能比通过select-object管道要快一点:
function check-krpano {
$geturl=Invoke-WebRequest http://krpano.com/news
($geturl.Links|where href -match '\#news\d+'|where class -notmatch 'moreinfo+')[0..4].outerText
}
答案 3 :(得分:2)
我意识到这是一个老问题,但我想通过使用COM对象控制Internet Explorer来为其他任何可能尝试实现相同目标的人添加答案:
$ie = New-Object -com internetexplorer.application
$ie.navigate($url)
while ($ie.Busy -eq $true) { Start-Sleep -Milliseconds 100; }
我通常更喜欢使用Invoke-WebRequest作为原始海报,但我发现似乎我需要一个成熟的IE实例才能看到所有JavaScript生成的DOM元素,即使我希望parsedhtml.body包含它们。
我发现我可以做类似这样的事情来通过类名来获取元素集合:
$titles = $ie.Document.body.getElementsByClassName('newstitle')
foreach ($storyTitle in $titles) {
Write-Output $storyTitle.innerText
}
我观察到原始海报在使用PowerShell搜索DOM时注意到的性能相同,但是使用PowerShell 3.0和IE11,Measure-Command显示我的类集合在280毫秒的125 KB HTML文档中找到。
答案 4 :(得分:0)
它似乎可以与PowerShell 5.1一起使用:
function check-krpano {
$geturl = Invoke-WebRequest -Uri "http://krpano.com/news/"
$news = $geturl.ParsedHtml.body.getElementsByClassName("newstitle")
Write-Host "$($news[0].innerHTML)"
}
check-krpano
输出:
<A href="#news1206">krpano 1.20.6</A><SPAN class=smallcomment style="FLOAT: right"><A href="https://krpano.co
m/forum/wbb/index.php?page=Thread&postID=81651#post81651"><IMG class=icon16m src="../design/ico-forumlink
.png"> krpano Forum Link</A></SPAN>