目的
私は Cricinfo Webサイト から20/20クリケットスコアカードデータを削り取り、理想的にはCSVフォームにExcelでデータ分析します
例として、現在のオーストラリアのビッグバッシュ2011/12スコアカードは、
背景
私はVBAを使用して(IE
を自動化するか、XMLHTTP
を使用してから正規表現を使用して)、Webサイトからデータをスクレイピングすることに熟練しています HTMLから値を抽出TDおよびTr
同じ質問で、html解析を提案するコメントが投稿されました-私はこれまでに遭遇したことがないので、 RegEx match open tags except XHTML self-contained tags などの質問を調べました。
クエリ
以下のクリケットデータを解析するための正規表現を書くことはできますが、HTML解析を使用してこれらの結果を効率的に取得する方法についてアドバイスをお願いします。
私の好みは以下を含む繰り返し可能なCSV形式であることを覚えておいてください。
私にとってNirvanaは、VBAまたはVBscriptを使用して展開できるソリューションであり、分析を完全に自動化できますが、HTML解析には別のツールを使用する必要があると思います。
サンプルサイトリンクと抽出されるデータ
「VBA」には2つのテクニックがあります。 1つずつ説明していきます。
1)FireFox/Firebug Addon/Fiddlerを使用する
2)Excelの組み込み機能を使用してWebからデータを取得する
この投稿は多くの人に読まれるので、自明のことも取り上げます。知っている部分はスキップしてください。
1)FireFox/Firebug Addon/Fiddlerを使用する
FireFox: http://en.wikipedia.org/wiki/Firefox 無料ダウンロード( http://www.mozilla.org/en-US/firefox/new/ )
Firebugアドオン: http://en.wikipedia.org/wiki/Firebug_%28software%29 無料ダウンロード( https://addons.mozilla.org/en-US/firefox/ addon/firebug / )
Fiddler: http://en.wikipedia.org/wiki/Fiddler_%28software%29 無料ダウンロード( http://www.fiddler2.com/fiddler2/ )
Firefoxをインストールしたら、Firebugアドオンをインストールします。 Firebugアドオンを使用すると、Webページのさまざまな要素を検査できます。たとえば、ボタンの名前を知りたい場合は、ボタンを右クリックして[Firebugで要素を検査]をクリックすると、そのボタンに必要なすべての詳細が表示されます。
別の例としては、スクラップする必要のあるデータがあるWebサイト上のテーブルの名前を見つける場合があります。
XMLHTTPを使用している場合にのみ、Fiddlerを使用します。ボタンをクリックしたときに渡される正確な情報を確認するのに役立ちます。サイトをスクレイピングするBOTSの数が増えたため、ほとんどのサイトでは、自動スクレイピングを防ぐために、マウスの座標をキャプチャしてその情報を渡します。フィドラーは、渡された情報のデバッグに実際に役立ちます。この情報は悪意を持って使用される可能性があるため、ここでは詳しく説明しません。
次に、質問に投稿されたURLをこする方法の簡単な例を見てみましょう
http://www.espncricinfo.com/big-bash-league-2011/engine/match/524915.html
まず、その情報を持つテーブルの名前を見つけましょう。テーブルを右クリックして、「Firebugで要素を検査」をクリックすると、以下のスナップショットが表示されます。
これで、データが「inningsBat1」というテーブルに格納されていることがわかりました。そのテーブルの内容をExcelファイルに抽出できれば、データを操作して分析を実行できます。 Sheet1にそのテーブルをダンプするサンプルコードは次のとおりです
先に進む前に、すべてのExcelを閉じて、新しいインスタンスを開始することをお勧めします。
VBAを起動し、ユーザーフォームを挿入します。コマンドボタンとWebcrowserコントロールを配置します。ユーザーフォームは次のようになります
このコードをユーザーフォームのコード領域に貼り付けます
Option Explicit
'~~> Set Reference to Microsoft HTML Object Library
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Private Sub CommandButton1_Click()
Dim URL As String
Dim oSheet As Worksheet
Set oSheet = Sheets("Sheet1")
URL = "http://www.espncricinfo.com/big-bash-league-2011/engine/match/524915.html"
PopulateDataSheets oSheet, URL
MsgBox "Data Scrapped. Please check " & oSheet.Name
End Sub
Public Sub PopulateDataSheets(wsk As Worksheet, URL As String)
Dim tbl As HTMLTable
Dim tr As HTMLTableRow
Dim insertRow As Long, Row As Long, col As Long
On Error GoTo whoa
WebBrowser1.navigate URL
WaitForWBReady
Set tbl = WebBrowser1.Document.getElementById("inningsBat1")
With wsk
.Cells.Clear
insertRow = 0
For Row = 0 To tbl.Rows.Length - 1
Set tr = tbl.Rows(Row)
If Trim(tr.innerText) <> "" Then
If tr.Cells.Length > 2 Then
If tr.Cells(1).innerText <> "Total" Then
insertRow = insertRow + 1
For col = 0 To tr.Cells.Length - 1
.Cells(insertRow, col + 1) = tr.Cells(col).innerText
Next
End If
End If
End If
Next
End With
whoa:
Unload Me
End Sub
Private Sub Wait(ByVal nSec As Long)
nSec = nSec + Timer
While Timer < nSec
DoEvents
Sleep 100
Wend
End Sub
Private Sub WaitForWBReady()
Wait 1
While WebBrowser1.ReadyState <> 4
Wait 3
Wend
End Sub
次にユーザーフォームを実行し、コマンドボタンをクリックします。データがSheet1にダンプされていることがわかります。スナップショットを見る
同様に、他の情報も削ることができます。
2)Excelの組み込み機能を使用してWebからデータを取得します
私はあなたがExcel 2007を使用していると思いますので、上記のリンクをこする例としてそれを取り上げます。
Sheet2に移動します。次に、[データ]タブに移動し、右端の[Webから]ボタンをクリックします。スナップショットを参照してください。
「新しいWebクエリウィンドウ」にURLを入力し、「移動」をクリックします。
ページがアップロードされたら、スナップショットに示されている小さな矢印をクリックして、インポートする関連テーブルを選択します。完了したら、「インポート」をクリックします
Excelは、データをインポートする場所を尋ねます。関連するセルを選択し、[OK]をクリックします。これで完了です。指定したセルにデータがインポートされます。
マクロを記録し、これを自動化することもできます。
これが私が記録したマクロです。
Sub Macro1()
With ActiveSheet.QueryTables.Add(Connection:= _
"URL;http://www.espncricinfo.com/big-bash-league-2011/engine/match/524915.html" _
, Destination:=Range("$A$1"))
.Name = "524915"
.FieldNames = True
.RowNumbers = False
.FillAdjacentFormulas = False
.PreserveFormatting = True
.RefreshOnFileOpen = False
.BackgroundQuery = True
.RefreshStyle = xlInsertDeleteCells
.SavePassword = False
.SaveData = True
.AdjustColumnWidth = True
.RefreshPeriod = 0
.WebSelectionType = xlSpecifiedTables
.WebFormatting = xlWebFormattingNone
.WebTables = """inningsBat1"""
.WebPreFormattedTextToColumns = True
.WebConsecutiveDelimitersAsOne = True
.WebSingleBlockTextImport = False
.WebDisableDateRecognition = False
.WebDisableRedirections = False
.Refresh BackgroundQuery:=False
End With
End Sub
お役に立てれば。まだクエリがある場合はお知らせください。
シド
これに興味のある他の人のために、私は Siddhart Rout's 以前の回答に基づいて以下のコードを使用することになりました
XMLHttp
は自動化よりも大幅に高速でしたIE
X
変数に保持されます) Public Sub PopulateDataSheets_XML()
Dim URL As String
Dim ws As Worksheet
Dim lngRow As Long
Dim lngRecords As Long
Dim lngWrite As Long
Dim lngSpare As Long
Dim lngInnings As Long
Dim lngRow1 As Long
Dim X(1 To 15, 1 To 4) As String
Dim objFSO As Object
Dim objTF As Object
Dim xmlHttp As Object
Dim htmldoc As HTMLDocument
Dim htmlbody As htmlbody
Dim tbl As HTMLTable
Dim tr As HTMLTableRow
Dim strInnings As String
s = Timer()
Set xmlHttp = CreateObject("MSXML2.ServerXMLHTTP")
Set objFSO = CreateObject("scripting.filesystemobject")
X(1, 1) = "http://www.espncricinfo.com/indian-premier-league-2011/engine/match/"
X(1, 2) = 501198
X(1, 3) = 501271
X(1, 4) = "indian-premier-league-2011"
X(2, 1) = "http://www.espncricinfo.com/big-bash-league-2011/engine/match/"
X(2, 2) = 524915
X(2, 3) = 524945
X(2, 4) = "big-bash-league-2011"
X(3, 1) = "http://www.espncricinfo.com/ausdomestic-2010/engine/match/"
X(3, 2) = 461028
X(3, 3) = 461047
X(3, 4) = "big-bash-league-2010"
Set htmldoc = New HTMLDocument
Set htmlbody = htmldoc.body
For lngRow = 1 To UBound(X, 1)
If Len(X(lngRow, 1)) = 0 Then Exit For
Set objTF = objFSO.createtextfile("c:\temp\" & X(lngRow, 4) & ".csv")
For lngRecords = X(lngRow, 2) To X(lngRow, 3)
URL = X(lngRow, 1) & lngRecords & ".html"
xmlHttp.Open "GET", URL
xmlHttp.send
Do While xmlHttp.Status <> 200
DoEvents
Loop
htmlbody.innerHTML = xmlHttp.responseText
objTF.writeline X(lngRow, 1) & lngRecords & ".html"
For lngInnings = 1 To 2
strInnings = "Innings " & lngInnings
objTF.writeline strInnings
Set tbl = Nothing
On Error Resume Next
Set tbl = htmlbody.Document.getElementById("inningsBat" & lngInnings)
On Error GoTo 0
If Not tbl Is Nothing Then
lngWrite = 0
For lngRow1 = 0 To tbl.Rows.Length - 1
Set tr = tbl.Rows(lngRow1)
If Trim(tr.innerText) <> vbNewLine Then
If tr.Cells.Length > 2 Then
If tr.Cells(1).innerText <> "Extras" Then
If Len(tr.Cells(1).innerText) > 0 Then
objTF.writeline strInnings & "-" & lngWrite & "," & Trim(tr.Cells(1).innerText) & "," & Trim(tr.Cells(3).innerText)
lngWrite = lngWrite + 1
End If
Else
objTF.writeline strInnings & "-" & lngWrite & "," & Trim(tr.Cells(1).innerText) & "," & Trim(tr.Cells(3).innerText)
lngWrite = lngWrite + 1
Exit For
End If
End If
End If
Next
For lngSpare = 12 To lngWrite Step -1
objTF.writeline strInnings & "-" & lngWrite + (12 - lngSpare)
Next
Else
For lngSpare = 1 To 13
objTF.writeline strInnings & "-" & lngWrite + (12 - lngSpare)
Next
End If
Next
Next
Next
'Call ConsolidateSheets
End Sub
RegExは、正規であることが保証されていないため、HTMLを解析するための完全なソリューションではありません。
HtmlAgilityPack を使用してHTMLをクエリする必要があります。これにより、CSSセレクターを使用して、jQueryで行う方法と同様にHTMLをクエリできます。