2013-05-19 127 views
0

我在Powershell中有一个函数,它可以获取文件的内容并将其分解为要放入CSV文件的字段。我想知道是否有方法从链接获取值并将其添加到发送到C​​SV文件的列中,同时保持链接列不变。从Powershell中的链接中提取值

function Convert2CSV { 
(Get-Content $input_path) -match "href" | % { 
$data = ($_ -replace '(?:.*)href="(.*?)">Date:\s*([\w\.]+)\s*([\w\:]+)\s*Item:\s*(.*)</a>(?:.*)' , '$1;$2;$3;$4').Split(";") 
New-Object psobject -Property @{ 
    "Link" = $data[0] 
    "Date" = $data[1] 
    "Time" = $data[2] 
    "Item" = $data[3] 
    } 
} #| Export-Csv $output_file -NoTypeInformation 
} 

我在寻找的值是

FeedDefault_.*?(&) or _Feed.*?(&) 

我是在想,我可以添加某种if语句的“链接” = $数据[0]部分正确吗?

根据要求输出样本。

Value in Link | Link                 | Date  | Time | Item   | 
--------------------------------------------------------------------------------------------------------------------------------------------| 
bluepebbles  | http://www.domain.com/page.html?FeedDefault_bluepebbles&something  | 2013-05-19 | 13:30 | Blue Pebbles  | 
--------------------------------------------------------------------------------------------------------------------------------------------| 
redpebbles  | http://www.domain.com/page.html?Feed_redpebbles&something    | 2013-05-19 | 13:31 | Red Pebbles  | 
--------------------------------------------------------------------------------------------------------------------------------------------| 

CSV格式化

Value in Link,Link,Date,Time,Item 
"bluepebbles","http://www.domain.com/page.html?FeedDefault_bluepebbles&something","2013-05-19","13:30","Blue Pebbles" 
"redpebbles","http://www.domain.com/page.html?Feed_redpebbles&something","2013-05-19","13:31","Red Pebbles" 

所以在

$input_path = 'f:\mockup\area51\files\link.html' 
$output_file = 'f:\mockup\area51\files\db_csv.csv' 

$tstampCulture = [Globalization.cultureinfo]::GetCultureInfo("en-GB") 

$ie = New-Object -COM "InternetExplorer.Application" 
$ie.Visible = $false 

$ie.Navigate("file:///$input_path") 

$ie.document.getElementsByTagName("a") | % { 
    $_.innerText -match 'Date:\s*([\w\.]+)\s*([\w\:]+)\s*Item:\s*(.*)' 
    $obj = New-Object psobject -Property @{ 
    "Link" = $_.href 
    "Date" = $matches[1] 
    "Time" = $matches[2] 
    "Item" = $matches[3] 
    } 
    if ($obj.Link -match '\?Feed(?:Default)?_(.*?)&') { 
    $obj | Add-Member –Type "NoteProperty" –Name "LinkValue" –Value $matches[1] 
    } 
    $obj 
} #| Export-Csv $output_file -NoTypeInformation 

进入返回一个错误:

You cannot call a method on a null-valued expression. 
At line:12 char:38 
+  $ie.document.getElementsByTagName <<<< ("a") | % { 
+ CategoryInfo   : InvalidOperation: (getElementsByTagName:String) [], RuntimeException 
+ FullyQualifiedErrorId : InvokeMethodOnNull 

所以我敢肯定,我可能搞砸的东西了。 :)

+0

你需要更具体。这两个值是否是针灸?因为它们由正则表达式等组成,所以很难理解你想要什么。你想查看url是否包含'FeedDefault _。*?(&)'或'_Feed。*?(&)',如果匹配,将它们添加到名为ex的列中。 '匹配'?包含一些示例输出结果应该看起来像 –

+0

我想提取'FeedDefault_和'之间的内容'如果它在链接中,或者'_Feed和链接中的内容'之间有什么内容。然后将该值添加到一个列,该列可以在保持链接列不变的情况下吐出到CSV文件中。 – gjettison

回答

1

首先,我会建议使用-match而不是-replace。由此产生的$matches数组已包含您感兴趣的子匹配,因此不需要手动创建此数组。

Get-Content $input_path | ? { $_.contains("href") } | % { 
    $_ -match 'href="(.*?)">Date:\s*([\w\.]+)\s*([\w\:]+)\s*Item:\s*(.*)</a>' 
    $obj = New-Object psobject -Property @{ 
    "Link" = $matches[1] 
    "Date" = $matches[2] 
    "Time" = $matches[3] 
    "Item" = $matches[4] 
    } 
    $obj 
} #| Export-Csv $output_file -NoTypeInformation 

的附加信息可以从$obj.Link提取与第二-match,然后通过Add-Member添加到自定义对象:

if ($obj.Link -match '\?Feed(?:Default)?_(.*?)&') { 
    $obj | Add-Member –Type "NoteProperty" –Name "LinkValue" –Value $matches[1] 
} 

此外,由于你的输入文件可能是HTML文件,你应该考虑使用COM对象,这将使您更好地控制提取的标签,而不是逐行处理文件。

$ie = New-Object -COM "InternetExplorer.Application" 
$ie.Visible = $false 

$ie.Navigate("file:///$input_path") 
while ($ie.Busy) { Start-Sleep -Milliseconds 100 } 

$ie.document.getElementsByTagName("a") | % { 
    $_.innerText -match 'Date:\s*([\w\.]+)\s*([\w\:]+)\s*Item:\s*(.*)' 
    $obj = New-Object psobject -Property @{ 
    "Link" = $_.href 
    "Date" = $matches[1] 
    "Time" = $matches[2] 
    "Item" = $matches[3] 
    } 
    if ($obj.Link -match '\?Feed(?:Default)?_(.*?)&') { 
    $obj | Add-Member –Type "NoteProperty" –Name "LinkValue" –Value $matches[1] 
    } 
    $obj 
} 
+0

感谢您的美妙想法!唯一的问题是当我输入代码时,我得到错误。 '你不能在一个空值表达式上调用一个方法。 在线:12 char:38 + $ ie.document.getElementsByTagName <<<<(“a”)| %{ + CategoryInfo:InvalidOperation:(getElementsByTagName:String)[],RuntimeException + FullyQualifiedErrorId:InvokeMethodOnNull' – gjettison

+0

我的不好。 'Navigate()'立即返回,但你仍然需要等待IE浏览器完成加载页面。当我写回答时,我忘了添加一个等待循环,所以你的测试可能试图在页面完全加载之前访问'document'对象。固定。 –

+0

这将是有道理的,但即使使用新代码,我仍然收到错误消息。我会玩弄东西,看看我能不能做些事情。再次感谢指针在正确的方向! – gjettison