2013-07-12 4 views
12

私はPowerShellスクリプトを書いて、ウェブサイトから "newstitle"という名前のすべてのクラス内のテキストを取得しようとしています。スクリプト内でGetElementsByClassNameを使用する

これは私が持っているものです。

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コマンドを使用して出力されます。parsedhtml.bodyを使用して、クラスのnewstitle」を含むdiv要素のための

  • 検索 - > 29.6秒
  • Allelementsを使用して、クラスのnewstitle」を含む開発者のための
  • 検索 - > 10.4秒のリンクの
  • 検索その要素「hrefが」#news含まれている - > 2.4秒

は、だから私は便利なリンク方法の答えとしてマークされています。

これが私の最後のスクリプトです:あなたは仕事にのgetElementsByClassNameを取得する方法を見つけ出す場合

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 

答えて

13

、私が知っているように思います。私はちょうどので、私は回避策を思い付いた昨日、このに走ったと時間を使い果たし:

$geturl.ParsedHtml.body.getElementsByTagName('div') | 
    Where {$_.getAttributeNode('class').Value -eq 'newstitle'} 
+3

「getElementsByTagName()」のバグのように見えます。しかし、私はちょうど[この回答](http://stackoverflow.com/a/9059206/1630171)に出くわしました。これは次のように示唆しています: '$ geturl.AllElements | ? {$ _。クラス-eq 'newstitle'} | select innerText'を実行します。もう少しエレガントかもしれない。 –

+1

良いニュースはPowerShell v5で動作することです。 PowerShell v4でコードが壊れた後、このスレッドに遭遇しました。 – Robin

+0

@AnsgarWiechersを受け取った要素の1つを保存する方法はありますか?あなたが言及したように私の選択リストに5つの要素を戻したら、それを配列に「取り込み」たいのですが、どうすればいいでしょうか? – KangarooRIOT

2

は、私の人生のために、その方法は、どちらかの仕事を得ることはできません!

結果に戻って必要なものによっては、これが役立つかもしれません。

function check-krpano { 
$geturl=Invoke-WebRequest http://krpano.com/news 

$news=($geturl.Links|where href -match '\#news\d+')[0] 

$news 

} 

check-krpano 

は私に戻って与える:あなたが唯一の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 

あなたは、直接、もちろんこれらのプロパティを使用することができ、これはそれを行うだろう:

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を返します。

あなたが望むものを実現する希望は、別のやり方ではありますが。

EDIT:

これはおそらく少し速く選択オブジェクトを介して配管よりなる​​:

function check-krpano { 
$geturl=Invoke-WebRequest http://krpano.com/news 

($geturl.Links|where href -match '\#news\d+'|where class -notmatch 'moreinfo+')[0..4].outerText 

} 
+0

ありがとうございました。それは私が私が探していたものを達成するのを助けました!あなたのスクリプトは正確に私が尋ねたものではありませんが、それは情報を得るための最速の方法です。 – RafaelGP

+0

「ParsedHtml.body」の 'getElements..'メソッドは使用しませんが、ユースケースの方が効率的です。私はあなたのスクリプトを修正して自分の投稿を編集しました。これは、select-objectにパイプすることなく、最初の5つの配列項目に直接アクセスすることによって少し速くなります。私のテストでは0.5〜1秒節約されました。 –

+0

ご協力いただきありがとうございます。最初の5つの配列項目へのアクセスは、Select-Itemを使用するより少し速いようです:-) – RafaelGP

14

getElementsByClassName直接配列を返す代わりに、COMを介して結果をプロキシありません。あなたが発見したように、配列への変換は[]演算子では自動的ではありません。あなたは、個々の要素にアクセスできるようにするために、最初のアレイにそれを強制するために、@()、リストの評価構文を使用することができます。

@($body.getElementsByClassName("foo"))[0].innerText 

オブジェクトのパイプラインを使用する場合はさておき、変換が自動的に行われるので、例えば:

foreach ($element in $body.getElementsByClassName("foo")) 
{ 
    $element.innerText 
} 
+0

Worked、gettypeがcomオブジェクトを返したことがわかりました。 @($ table)[1] .outerHTML。あなたは私に多くの時間を救った。 – Ernesto

1

$body.getElementsByClassName("foo") | Select-Object -First 1 

またforeach構築物を用いて自動的に行われます

私はこれが古い質問です実現が、私は、このようなのようなCOMオブジェクトを使用してInternet Explorerを制御することによって、同じことを達成しようとするかもしれない他の誰のための答えを追加したい:

$ie = New-Object -com internetexplorer.application 
$ie.navigate($url) 
while ($ie.Busy -eq $true) { Start-Sleep -Milliseconds 100; } 

私は通常に好みます元のポスターと同じようにInvoke-WebRequestを使用しましたが、私はparsedhtml.bodyにインクルードすると期待していたにもかかわらず、JavaScriptで生成されたすべてのDOM要素を見るために本格的なIEインスタンスが必要だったようなケースを発見しましたそれら。

私は、クラス名で要素のコレクションを取得するには、このような何かを行うことが分かっ:

$titles = $ie.Document.body.getElementsByClassName('newstitle') 
foreach ($storyTitle in $titles) { 
    Write-Output $storyTitle.innerText 
} 

私はDOMを検索するためのPowerShellを使用した場合、元のポスターが指摘同じ本当にパフォーマンスの低下を観察し、 PowerShell 3.0とIE11を使用してMeasure-Commandを実行すると、クラスのコレクションは280 KBのHTML文書で280 msで検出されます。

関連する問題