【问题标题】:Saving webpage content into variables将网页内容保存到变量中
【发布时间】:2015-01-03 21:50:01
【问题描述】:

我敢肯定我的大脑每分钟都在萎缩……

我正在做的是检索网页,获取一些信息并通过电子邮件发送该信息,所有这些都来自 powershell。电子邮件部分工作正常,但网页处理部分存在一些问题。 我最初的想法是获取页面,将其下载到临时文件,进行处理然后删除文件。然后我记得大约 12 年前在 TCL 中做了一个类似的脚本,我的方法是将页面内容传递给变量,然后调用变量以使用正则表达式处理数据。

$storageDir = "C:\Users\me\Documents"
$browser=new-object system.net.webclient
$browser.UseDefaultCredentials = $true
$browser.downloadfile("http://whatever.com/cgi-bin/search_detail.cgi?num=01","$storageDir\Download1.HTML")

上面将保存我的文件以供处理,但就像我说的,我认为传递给变量更好更干净,不知道如何在 powershell 中做到这一点。

我正在搜索以下 3 个标签。所有这些字段都将在 &nbsp 中结束,我不需要在返回中使用它。 这些是我有兴趣将字符串传递给变量的字段和字段格式:

此字段将是字母数字

CAL_ID:</font><td>tt1234 &nbsp;

此字段将是字母

CAL_FIRST:</font><td>TILAHUN &nbsp;

此字段将是一个电话号码,格式可以变化,它应该如图所示,但它可以不带任何电话分隔符或通常的 () 用于区号、空格等输入。

CAL_NE:</font><td>123-456-7890 &nbsp;

通常在 TCL 中我会在调用 http 包后做这样的事情:

set posting [::http::geturl http://whateever.com/searchonly -query query]
set raw_data [::http::data $posting]

然后使用 $raw_data 中的页面内容来获取我的变量,例如:

set data [regexp -all -inline -- {CAL_ID:</font><td>([^\>]*) &nbsp;} $raw_data]

对于我需要的其他字段等等。

我的头脑无法正常工作并且感到沮丧。任何帮助将不胜感激。

【问题讨论】:

    标签: powershell


    【解决方案1】:

    需要从一个小前锋开始。所以你认为将html下载到文件效率低下?在这种情况下,可能是因为您首先要进行一些数据提取。那为什么不直接使用$browser.DownloadString呢?

    $html = $browser.DownloadString(....)
    

    好的,所以我们在变量$html 中有我们的html,我们需要提取行中的数据。出于测试目的,这是我用于$html 的内容。

    This field will be alphanumeric
    CAL_ID:</font><td>tt1234 &nbsp;
    This field will be letters
    Thivll be letters
    s field wiCAL_FIRST:</font><td>TILAHUN &nbsp;
    This field will be a phone number and the format can vary, it should be as shown but it can be input without any phone separators or the usual () for the area code, spaces and such.
    s field wiCAL_NE:</font><td>123-456-7890 &nbsp;
    

    以下是提取数据的代码。

    $html | select-string -Pattern 'CAL_(ID|FIRST|NE).*?&nbsp;' -AllMatches | 
            ForEach-Object{$_.Matches} |
            Select-Object -ExpandProperty Value |
            ForEach-Object{
                $_ -replace [regex]::escape("</font><td>") -replace " &nbsp;" -replace ":","=" | ConvertFrom-StringData
    }
    

    样本输出

    Name                           Value                                                                                                                                        
    ----                           -----                                                                                                                                        
    CAL_ID                         tt1234                                                                                                                                       
    CAL_FIRST                      TILAHUN                                                                                                                                      
    CAL_NE                         123-456-7890  
    

    使用Select-String,我们找到了所有以“CAL_”开头的数据和以下ID之一,FIRST或NE。抓取所有内容,直到下一次出现“ ”。然后我们获取看起来像这样的数据(基于上述样本。)

    CAL_ID:</font><td>tt1234 &nbsp;
    CAL_FIRST:</font><td>TILAHUN &nbsp;
    CAL_ID:</font><td>tt1234 &nbsp;
    CAL_FIRST:</font><td>TILAHUN &nbsp;
    CAL_NE:</font><td>123-456-7890 &nbsp;
    

    修剪我们删除“”,尾随“ ”并将冒号转换为等号的脂肪。等号的最后一部分只是为了我们可以使用ConvertFrom-StringData,它以“key=value”的形式接受字符串输入,这样我们就可以输出一个不错的对象。

    自我批评

    我选择使用select-string,因为我认为它可能更容易接受,但我觉得带有 PowerShell 命名捕获的简单正则表达式可能会更好。

    __从评论更新_

    您提到您希望标题和评论中都包含变量中的数据。您忽略提及的部分是您希望在 变量 中使用它。从技术上讲,您只需将输出保存为变量,您要查找的数据将保存为参数。所以上面的代码会在第一行使用这个

    $result = $html | select-string -Pattern 'CAL_(ID|FIRST|NE).*?&nbsp;' -AllMatches |
    

    然后你可以像这样访问数据,因为它是一个数组。

    $result.CAL_NE
    

    注意:如果这些条目只在数据中出现一次,这种方法效果最好。最初我让他们多次出现以便能够解释这一点。

    如果您真的想要变量中的结果,这就是New-Variable 发挥作用的地方。

    $html | select-string -Pattern 'CAL_(ID|FIRST|NE).*?&nbsp;' -AllMatches | 
            ForEach-Object{$_.Matches} |
            Select-Object -ExpandProperty Value |
            ForEach-Object{
                $text = $_ -replace [regex]::escape("</font><td>") -replace " &nbsp;"
                New-Variable -Name $text.split(":")[0] -Value $text.split(":")[1]
    }
    

    你可以访问$CAL_ID

    PS C:\users\Cameron\Downloads> $CAL_ID
    tt1234
    

    【讨论】:

    • 感谢您的回复。它当然有效,但我很难将值分配给变量。该变量可以设置为名称。我查看了 convertfrom-stringdata,它确实有一个 -OutVariable 参数,但此时我不确定这是否适用于我想要的,将每个值分配给一个变量。再次感谢您的帮助。
    • 现在我在做: $test = $_ -replace "CAL_(ID|FIRST|NE)" -replace [regex]::escape("") -替换“  ” -replace ":" 当然,测试被分配了每个值,最终结果是我理解的最后一次交互的最后一个值。我可能可以使用 $i++ 循环类型来更改名称,但我认为如果变量采用名称本身会更优雅,这意味着 $CAL_ID=tt1234 $CAL_FIRST=TILAHUN $CAL_NE=123-456-7890
    • 马特,感谢您的帮助。再一次,我不说我的意思,我的意思是我不说的......这很有趣,我使用 $i $i++ 循环在我的脚本中使用新变量,并没有想到只使用你的名字用过。答案就在我的脸上,天哪!再次感谢。
    猜你喜欢
    相关资源
    最近更新 更多
    热门标签