2013-12-02 1 views
2

Это вопрос, который я задал на прошлой неделе, posted here. Я прошел мимо оригинальной проблемы, но теперь у меня возникает несколько другая проблема.Проблема разбора html с использованием powershell и xpath

теперь я смог получить атрибут элемента Меня интересует, если HTML-теги не вложены, используя метод GetAttributeValue, здесь это данных PID, но я сейчас возникли проблемы захватывая атрибут элемента, который находится во вложенных тегах, в моем фрагменте кода это дата. Я использую xpath и HtmlAgility pack для анализа html здесь, но в примере ниже одна и та же дата возвращается снова и снова.

Вот что $ пункт объект выглядит следующим образом:

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 значения.

OuterHtml   : <p class="row" data-latitude="41.5937565437255" data-longitude="-93.6437636649079" data-pid="4184719674"> <a href="/mod/4184719674.html" class="i"></a> 
       <span class="star"></span> <span class="pl"> <span class="date">Nov 27</span> <a href="/mod/4184719674.html">iPhone and other Cell Phone Unlocks</a> 
       </span> <span class="l2"> <span class="pnr"> <small> (Des Moines)</small> <span class="px"> <span class="p"> <a href="#" class="maptag" 
       data-pid="4184719674">map</a></span></span> </span> <a class="gc" href="/mod/" data-cat="mod">cell phones - by dealer</a> </span> </p> 

Я могу захватить данных PID без проблем. Вот то, что текущий код выглядит следующим образом:

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 
} 

То, что я хочу сделать, это быть в состоянии захватить атрибуты из различных тегов, которые содержатся в outerhtml объекта, используя свои заявления XPath, но я не могу понять как это сделать. Это лучший способ решить проблему, или я должен просто использовать некоторое регулярное выражение, чтобы получить значение, которое я хочу?

Дайте мне знать, какие еще детали мне нужно разместить.

+1

> Любое копирование, агрегация, дисплей, распределение, исполнение или производное использование Craigslist или любое содержание размещены на Craigslist ли сделано непосредственно или через посредников (включая, но не ограничиваясь ими с помощью пауков, роботов, гусеничном ходу, скребки , кадрирование, iframe или RSS-каналы). ([Источник] (http://www.craigslist.org/about/terms.of.use)) – Tohuw

ответ

7

Я не использовал HTML Agility Pack, но 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. Используйте объект Internet Explorer COM, если ваш ограничивается PowerShell v2:

$ie = New-Object -COM InternetExplorer.Application 
$ie.Navigate($url) 
while ($ie.ReadyState -ne 4) { sleep 100 } 
$html = $ie.Document 

Если файл HTML является локальным файлом, замените Invoke-Webrequest строку с чем-то вроде этого:

$htmlfile = 'C:\path\to\some.html' 

$html = New-Object -COM HTMLFile 
$html.write((Get-Content $htmlfile | Out-String)) 
+0

До сих пор это работает на меня, но он вечно бежит. Знаете ли вы, что заставило бы его занять такое долгое время? – jmreicha

+2

Не зная фактических входных данных, вы запускаете это? Едва. –

2

Я слишком поздно, но вот ваша ошибка. Вы используете абсолютные пути.

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 
} 
Смежные вопросы