powershell parsilのWebサイトを作成するには

まえがき



まず第一に、私はプログラマーではないことに注意したい。 私は管理者です、さようなら。 もちろん、建築家と呼ばれたいのですが、目に見える空間には適切な空席がなく、適切な要件があり、最も重要なことには、これらの要件に対する給与がありません。 なんて残念。

実際、この記事のフレームワークでは、Powershellの新しいバージョンの便利な機能についてお話したいと思います。 特に、Webページを迅速かつ確実に解析し、「並行して」実行する機能について。



挑戦する



したがって、私の前に立っていたタスクは非常に簡単でした。 特定のサイトがあります。開始日と終了日を選択する必要がある初期フォームを確認すると、このページにアクセスできます。



画像



そのようなページの数は、単一の日付期間内に多くなる場合があります。 しかし、999以下です。つまり、たとえば、5年間のデータを選択する必要がある場合、それらは999ページに収まりません。 このページはディレクトリであり、Permit NOカラムのリンクを介して導かれるデータにのみ興味がありました。



画像



一般に、私はプログラマーではないので、私の知識はC#またはそのようなものの可能性を利用するのに十分ではありませんでした。 一般的に、私のお気に入りのツール-PowerShellはここで役立ちました。



解決策



私は2段階に行くことにしました。 最初に、リンクを含むディレクトリをアンロードして解析し、次にディレクトリを参照して、参照するドキュメントを選択します。 プログラマーの基本的なタスク。 約16時間かかりました。 確かに、問題を解決するためだけでなく、その瞬間に残されたコマンドとチップのPowerShell 3を新たに学ぶためにも、新しいコマンドを使用してこれを行ったという事実を考えると。

次のように、サイトがURLバーのパラメーターを直接受け入れたことは幸運でした。



  http:// [skip] / [skip]?allcount = $ allcount&allstartdate_month = $ allstartdate_month [skip] 


HTMLフォームの操作方法がわからないからです。 そのため、必要なページを単純に要求し、要求パラメーターを変更することにしました。 このために、Invoke-WebRequestコマンドレットを使用しました。 これにより、.NETクラスを直接使用せずに、またはIE COMオブジェクトを使用せずに、最も単純な形式で要求を送信し、結果を取得できます。 結果は、さらに解析できる解析済みHTMLドキュメントです。

さらに、このページの特徴は、テーブルのHTMLコードだけでなく、そのように解析されたこのテーブルのコンテンツでも返されることでした。



画像



前半の解析


この部分では、ディレクトリを選択しました。 この段階での主な問題は、システムから返されるすべてのページをソートし、最後のページを決定することです。 これを行うために、ページに[次へ]ボタンがあるかどうかを確認することにしました。

さらに、このパートの出力では、ディレクトリ自体を含むフラットなcsvファイルを取得したかったのです。 最後に、このファイルを次のステップに転送します。 このために、以下のコードが生まれました。 日付範囲のすべてのルートタブレットを選択し、上記の機能を使用して正規表現でページのコンテンツを解析し、指定されたすべての情報を含むオブジェクトを返します。



function Get-AppList { [CmdletBinding()] param( [datetime] $startDate = '01.01.2012', [datetime] $endDate = '01.01.2012', [string] $allpermittype = "SG", [string] $allcount = "0000", [string] $requestid= "1" ) begin{ [string] $allstartdate_month = "{0:d2}" -f $startDate.Month [string] $allstartdate_day= "{0:d2}" -f $startDate.Day [string] $allstartdate_year= $startDate.Year [string] $allenddate_month = "{0:d2}" -f $endDate.Month [string] $allenddate_day = "{0:d2}" -f $endDate.Day [string] $allenddate_year = $endDate.Year $fields = @{Regex="\[0:PtAppFirstName\]\{(?<PtAppFirstName>.+)\}";Column="PtAppFirstName"}, @{Regex="\[1:PtAppLastName\]\{(?<PtAppLastName>.+)\}";Column="PtAppLastName"}, @{Regex="\[2:PtAppMI\]\{(?<PtAppMI>.+)\}";Column="PtAppMI"}, @{Regex="\[3:PtJobNum\]\{(?<PtJobNum>.+)\}";Column="PtJobNum"}, @{Regex="\[4:PtJobDocNum\]\{(?<PtJobDocNum>.+)\}";Column="PtJobDocNum"}, @{Regex="\[5:PtJobType\]\{(?<PtJobType>.+)\}";Column="PtJobType"}, @{Regex="\[6:PtPermitType\]\{(?<PtPermitType>.+)\}";Column="PtPermitType"}, @{Regex="\[7:PtPermitSubtype\]\{(?<PtPermitSubtype>.+)\}";Column="PtPermitSubtype"}, @{Regex="\[8:PtPermitSeqNum\]\{(?<PtPermitSeqNum>.+)\}";Column="PtPermitSeqNum"}, @{Regex="\[9:PtIssuanceDate\]\{(?<PtIssuanceDate>.+)\}";Column="PtIssuanceDate"}, @{Regex="\[10:PtFilingDate\]\{(?<PtFilingDate>.+)\}";Column="PtFilingDate"}, @{Regex="\[11:PtExpirationDate\]\{(?<PtExpirationDate>.+)\}";Column="PtExpirationDate"}, @{Regex="\[12:PtBin\]\{(?<PtBin>.+)\}";Column="PtBin"}, @{Regex="\[13:JHouseNumber\]\{(?<JHouseNumber>.+)\}";Column="JHouseNumber"}, @{Regex="\[14:JStreetName\]\{(?<JStreetName>.+)\}";Column="JStreetName"}, @{Regex="\[15:PermitIsn\]\{(?<PermitIsn>.+)\}";Column="PermitIsn"} $uri = "http://[skip]/bisweb/[skip]?allcount=$allcount&allstartdate_month=$allstartdate_month&allstartdate_day=$allstartdate_day&allstartdate_year=$allstartdate_year&allenddate_month=$allenddate_month&allenddate_day=$allenddate_day&allenddate_year=$allenddate_year&allpermittype=$allpermittype&go13=+GO+&requestid=0&navflag=T&requestid=$requestid" } process{ do { #   .   $a = Invoke-WebRequest -Uri $uri -SessionVariable sv $s = $a.ParsedHtml.childNodes| % data $s2 = ($s[3] -split "\[\d+\]") $obj = @{} $s2 | % { $item = $_ if ($item) { $fields | % { $res = $item -match $_.regex if ($res) { $obj[$_.Column] = $matches[$_.Column] } else { $obj[$_.Column]= $null } } if (($obj.PtPermitType -ne $null) -and ($obj.PtPermitType -ne " ")) { new-object psobject -Property $obj } } } # ,    .     $form = $a.Forms | where id -EQ "frmnext" if ($form) { $allstartdate_month=$form.Fields["allstartdate_month"] $allstartdate_day=$form.Fields["allstartdate_day"] $allstartdate_year=$form.Fields["allstartdate_year"] $allenddate_month = $form.Fields["allenddate_month"] $allenddate_day = $form.Fields["allenddate_day"] $allenddate_year = $form.Fields["allenddate_year"] $allpermittype = $form.Fields["allpermittype"] $allcount = $form.Fields["allcount"] $requestid = $form.Fields["requestid"] $uri = "http://[skip]/skip?allcount=$allcount&allstartdate_month=$allstartdate_month&allstartdate_day=$allstartdate_day&allstartdate_year=$allstartdate_year&allenddate_month=$allenddate_month&allenddate_day=$allenddate_day&allenddate_year=$allenddate_year&allpermittype=$allpermittype&go13=+GO+&requestid=0&navflag=T&requestid=$requestid" } } while ($form) } }
      
      





後半の解析


第二部では、別の問題が発生しました。 リクエストするページ数がもう少し多くなりました。 約30回です。したがって、最初の段階の結果を並べ替え、ページを1つずつ選択するのに長い時間がかかりました。 そのため、別のpowershell v3機能であるpowershellワークフローを使用することにしました。 まあ、というか、foreach –parallel演算子です。 実際、ワークフローはまったく異なる目的のために設計されていますが、この場合、それは最終的に達成されました。 これは、生産性を向上させるためにタスクを並列化するツールではないため、すぐに言う必要があります。 そのため、この場合、この機会を利用して、ディレクトリの各行に対してクエリを「並行して」起動することが考えられました。 実際、このコマンドは別のプロセスを開始し、その数は制限されています。 最大数を変更できるかどうかは疑問ではありませんでした。 このメカニズムにより、コードを単純化して「並列性」を得ることができます。 引用符で囲まれています。平行ではないからです。 これらは並列であり、単純なスレッドではなく、.NETワークフローのフレームワーク内の重いプロセスで実行され、結果はプロセスの境界を越えて送信される必要があります。 したがって、これはあまり生産的ではありませんが、「私たちのお気に入りのシェフが言うように、安くて便利で実用的です」、そして最も重要なのは管理者にとってコードが2行しかないことです。 別のタスクでの数秒の損失は、タスク全体に関連した役割を果たしません。 一般的に、良いことです。

コードは次のようになりました。



 workflow Get-AppDetails2 ($list) { $webList = @() foreach -parallel ($i in $list){ $PermitIsn = $i.PermitIsn $queryUri = "http://[skip]/bisweb/[skip]?allisn=$PermitIsn&allbin=&requestid=1" Invoke-WebRequest -Uri $queryUri } }
      
      





結論



一般に、これはすべて、powershellが強力で有用なものであり、あらゆる種類の重要かつ有用なものに適していることを証明しています。



All Articles