powershellとxpathを使用してhtmlを解析する問題

html html-agility-pack html-parsing powershell xpath

質問

これは私が先週に尋ねた質問に続く質問です 。私は元の問題を過ぎてしまったが、今は若干異なる問題にぶつかっている。

私は、GetAttributeValueメソッドを使ってhtmlタグがネストされていない場合、私が興味を持っているアイテムの属性を取得できるようになりました。ここではデータ -pidですが、今はアイテムの属性を取得するのに問題があります。ネストされたタグでは、私のコードスニペットでは日付です。私はxpathとHtmlAgilityパックを使ってHTMLを解析していますが、下の例では同じ日付が繰り返し返されます。

$ itemオブジェクトの外観を以下に示します。

Attributes           : {class, data-pid}
ChildNodes           : {#text, a, #text, span...}
Closed               : True
ClosingAttributes    : {}
FirstChild           : HtmlAgilityPack.HtmlTextNode
HasAttributes        : True
HasChildNodes        : True
HasClosingAttributes : False
Id                   : 
InnerHtml            :  <a href="/mod/4175126893.html" class="i"><span class="price">$20</span></a> <span class="star"></span> <span class="pl"> <span class="date">Nov 
                       30</span>  <a href="/mod/4175126893.html">Unlock Any GSM Cell Phone Today!</a> </span> <span class="l2"> <span class="price">$20</span>  <span 
                       class="pnr"> <small> (Des Moines)</small> <span class="px"> <span class="p"> </span></span> </span>  <a class="gc" href="/mod/" 
                       data-cat="mod">cell phones - by dealer</a> </span> 
InnerText            :  $20   Nov 30  Unlock Any GSM Cell Phone Today!   $20    (Des Moines)      cell phones - by dealer  
LastChild            : HtmlAgilityPack.HtmlTextNode
Line                 : 305
LinePosition         : 5408
Name                 : p
NextSibling          : HtmlAgilityPack.HtmlTextNode
NodeType             : Element
OriginalName         : p
OuterHtml            : <p class="row" data-pid="4175126893"> <a href="/mod/4175126893.html" class="i"><span class="price">$20</span></a> <span class="star"></span> 
                       <span class="pl"> <span class="date">Nov 30</span>  <a href="/mod/4175126893.html">Unlock Any GSM Cell Phone Today!</a> </span> <span class="l2"> 
                       <span class="price">$20</span>  <span class="pnr"> <small> (Des Moines)</small> <span class="px"> <span class="p"> </span></span> </span>  <a 
                       class="gc" href="/mod/" data-cat="mod">cell phones - by dealer</a> </span> </p>
OwnerDocument        : HtmlAgilityPack.HtmlDocument
ParentNode           : HtmlAgilityPack.HtmlNode
PreviousSibling      : HtmlAgilityPack.HtmlTextNode
StreamPosition       : 18733
XPath                : /html[1]/body[1]/article[1]/section[1]/div[1]/div[2]/p[11]

Attributes           : {class, data-pid}
ChildNodes           : {#text, a, #text, span...}
Closed               : True
ClosingAttributes    : {}

私はouterhtml値からデータを取り出したいと思います。

Attributes           : {class, data-pid}
ChildNodes           : {#text, a, #text, span...}
Closed               : True
ClosingAttributes    : {}
FirstChild           : HtmlAgilityPack.HtmlTextNode
HasAttributes        : True
HasChildNodes        : True
HasClosingAttributes : False
Id                   : 
InnerHtml            :  <a href="/mod/4175126893.html" class="i"><span class="price">$20</span></a> <span class="star"></span> <span class="pl"> <span class="date">Nov 
                       30</span>  <a href="/mod/4175126893.html">Unlock Any GSM Cell Phone Today!</a> </span> <span class="l2"> <span class="price">$20</span>  <span 
                       class="pnr"> <small> (Des Moines)</small> <span class="px"> <span class="p"> </span></span> </span>  <a class="gc" href="/mod/" 
                       data-cat="mod">cell phones - by dealer</a> </span> 
InnerText            :  $20   Nov 30  Unlock Any GSM Cell Phone Today!   $20    (Des Moines)      cell phones - by dealer  
LastChild            : HtmlAgilityPack.HtmlTextNode
Line                 : 305
LinePosition         : 5408
Name                 : p
NextSibling          : HtmlAgilityPack.HtmlTextNode
NodeType             : Element
OriginalName         : p
OuterHtml            : <p class="row" data-pid="4175126893"> <a href="/mod/4175126893.html" class="i"><span class="price">$20</span></a> <span class="star"></span> 
                       <span class="pl"> <span class="date">Nov 30</span>  <a href="/mod/4175126893.html">Unlock Any GSM Cell Phone Today!</a> </span> <span class="l2"> 
                       <span class="price">$20</span>  <span class="pnr"> <small> (Des Moines)</small> <span class="px"> <span class="p"> </span></span> </span>  <a 
                       class="gc" href="/mod/" data-cat="mod">cell phones - by dealer</a> </span> </p>
OwnerDocument        : HtmlAgilityPack.HtmlDocument
ParentNode           : HtmlAgilityPack.HtmlNode
PreviousSibling      : HtmlAgilityPack.HtmlTextNode
StreamPosition       : 18733
XPath                : /html[1]/body[1]/article[1]/section[1]/div[1]/div[2]/p[11]

Attributes           : {class, data-pid}
ChildNodes           : {#text, a, #text, span...}
Closed               : True
ClosingAttributes    : {}

データピッドをつかむことができます。現在のコードは次のようになります。

Attributes           : {class, data-pid}
ChildNodes           : {#text, a, #text, span...}
Closed               : True
ClosingAttributes    : {}
FirstChild           : HtmlAgilityPack.HtmlTextNode
HasAttributes        : True
HasChildNodes        : True
HasClosingAttributes : False
Id                   : 
InnerHtml            :  <a href="/mod/4175126893.html" class="i"><span class="price">$20</span></a> <span class="star"></span> <span class="pl"> <span class="date">Nov 
                       30</span>  <a href="/mod/4175126893.html">Unlock Any GSM Cell Phone Today!</a> </span> <span class="l2"> <span class="price">$20</span>  <span 
                       class="pnr"> <small> (Des Moines)</small> <span class="px"> <span class="p"> </span></span> </span>  <a class="gc" href="/mod/" 
                       data-cat="mod">cell phones - by dealer</a> </span> 
InnerText            :  $20   Nov 30  Unlock Any GSM Cell Phone Today!   $20    (Des Moines)      cell phones - by dealer  
LastChild            : HtmlAgilityPack.HtmlTextNode
Line                 : 305
LinePosition         : 5408
Name                 : p
NextSibling          : HtmlAgilityPack.HtmlTextNode
NodeType             : Element
OriginalName         : p
OuterHtml            : <p class="row" data-pid="4175126893"> <a href="/mod/4175126893.html" class="i"><span class="price">$20</span></a> <span class="star"></span> 
                       <span class="pl"> <span class="date">Nov 30</span>  <a href="/mod/4175126893.html">Unlock Any GSM Cell Phone Today!</a> </span> <span class="l2"> 
                       <span class="price">$20</span>  <span class="pnr"> <small> (Des Moines)</small> <span class="px"> <span class="p"> </span></span> </span>  <a 
                       class="gc" href="/mod/" data-cat="mod">cell phones - by dealer</a> </span> </p>
OwnerDocument        : HtmlAgilityPack.HtmlDocument
ParentNode           : HtmlAgilityPack.HtmlNode
PreviousSibling      : HtmlAgilityPack.HtmlTextNode
StreamPosition       : 18733
XPath                : /html[1]/body[1]/article[1]/section[1]/div[1]/div[2]/p[11]

Attributes           : {class, data-pid}
ChildNodes           : {#text, a, #text, span...}
Closed               : True
ClosingAttributes    : {}

私がしたいのは、xpathステートメントを使ってouterhtmlオブジェクトに含まれているさまざまなタグから属性を取得できるようにすることですが、その方法を理解することはできません。それは問題を取り上げる最善の方法ですか、私はちょうど私が望む価値を得るために正規表現を使うべきですか?

私が投稿する必要がある他の詳細を教えてください。

受け入れられた回答

私はHTMLアジリティパックを使用していませんが、AFAICSビルトインツールで十分です。

$url = 'http://www.example.com/path/to/some.html'

$html = (Invoke-Webrequest $url).ParsedHTML

$html.getElementsByTagName('p') | ? { $_.className -eq 'row' } | % {
  $ID   = $_.getAttributeNode('data-pid').value
  $Date = $_.getElementsByTagName('span') | ? { $_.className -eq 'date' } |
          % { $_.innerText }

  # do stuff with $ID and $Date
  "{0}: {1}" -f $ID, $Date
}

Invoke-WebrequestはPowerShell v3が必要です。制限されたPowerShell v2の場合は、Internet ExplorerのCOMオブジェクトを使用します。

$url = 'http://www.example.com/path/to/some.html'

$html = (Invoke-Webrequest $url).ParsedHTML

$html.getElementsByTagName('p') | ? { $_.className -eq 'row' } | % {
  $ID   = $_.getAttributeNode('data-pid').value
  $Date = $_.getElementsByTagName('span') | ? { $_.className -eq 'date' } |
          % { $_.innerText }

  # do stuff with $ID and $Date
  "{0}: {1}" -f $ID, $Date
}

HTMLファイルがローカルファイルの場合は、 Invoke-Webrequest行を次のように置き換えます。

$url = 'http://www.example.com/path/to/some.html'

$html = (Invoke-Webrequest $url).ParsedHTML

$html.getElementsByTagName('p') | ? { $_.className -eq 'row' } | % {
  $ID   = $_.getAttributeNode('data-pid').value
  $Date = $_.getElementsByTagName('span') | ? { $_.className -eq 'date' } |
          % { $_.innerText }

  # do stuff with $ID and $Date
  "{0}: {1}" -f $ID, $Date
}

人気のある回答

私は遅すぎるが、ここにあなたの間違いがある。あなたは絶対パスを使用しています。

ForEach ($item in $results) {

    # This is working
    $ID = $item.GetAttributeValue("data-pid", "")

    # This is looping over the same item
    $Date = $item.SelectSingleNode("//span[@class='date']").InnerText

    # This is looping over the different items (i.e. this is what what you want)
    $Date = $item.SelectSingleNode(".//span[@class='date']").InnerText
}



ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ
ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ