对cricinfo记分卡的htmlparsing
目标
我正在寻找从Cricinfo网站 20/20蟋蟀记分卡数据,理想的CSV格式的数据分析在Excel中
作为一个例子,目前澳大利亚Big Bash 2011/12记分卡可以从
- 游戏1: http : //www.espncricinfo.com/big-bash-league-2011/engine/match/524915.html
- 最后一场比赛: http : //www.espncricinfo.com/big-bash-league-2011/engine/match/524935.html
背景
我精通使用VBA(自动化IE
或使用XMLHTTP
,然后使用正则expression式)从网站上刮取数据,即从HTML TD和Tr中提取数据
在同一个问题中,发布了一条意见,build议使用HTMLparsing – 我之前没有讨论过这个问题 – 所以我看了一些问题,比如RegEx匹配的开放标签,除了XHTML自包含标签
询问
虽然我可以写一个正则expression式来parsing下面的板球数据,但我希望能够通过htmlparsing来有效地检索这些结果。
请注意,我的偏好是可重复的CSV格式,其中包含:
- 比赛的date/名字
- 团队1的名字
- 输出应该倾倒最多11队的logging(空白logging的球员没有击中,即“没有蝙蝠” )
- 队2的名字
- 输出应该倾倒最多11队的logging(空白logging玩家没有击中)
Nirvana对我来说是一个解决scheme,我可以使用VBA或VBscript进行部署,这样我就可以完全自动化我的分析,但我认为我将不得不使用单独的工具进行htmlparsing。
示例站点链接和要提取的数据
有2种技术用于“VBA”。 我会一一描述他们。
1)使用FireFox / Firebug插件/提琴手
2)使用Excel的内置工具从网上获取数据
由于这篇文章将被很多人阅读,所以我甚至会涵盖这些显而易见的内容。 请随意跳过你知道的任何部分
1)使用FireFox / Firebug插件/提琴手
FireFox: http : //en.wikipedia.org/wiki/Firefox免费下载( http://www.mozilla.org/en-US/firefox/new/ )
Firebug Addon: http : //en.wikipedia.org/wiki/Firebug_%28software%29免费下载( https://addons.mozilla.org/en-US/firefox/addon/firebug/ )
小提琴手: http : //en.wikipedia.org/wiki/Fiddler_%28software%29免费下载( http://www.fiddler2.com/fiddler2/ )
一旦你安装了Firefox,安装Firebug插件。 Firebug插件让你检查网页中的不同元素。 例如,如果你想知道一个button的名称,只需右键单击它,然后单击“用Firebug检查元素”,它会给你所有你需要的button的细节。
另一个例子是find一个网站上有一个你需要报废的数据表的名称。
我只在使用XMLHTTP时才使用Fiddler。 当你点击一个button时,它可以帮助我看到正确的信息。 由于BOTS数量的增加,现在大多数站点为了防止自动报废,捕获鼠标坐标并传递这些信息,而提琴手实际上可以帮助您debugging正在传递的信息。 因为这个信息可以恶意使用,所以在这里我不会详细讨论。
现在让我们举一个简单的例子来说明如何刮取问题中发布的URL
http://www.espncricinfo.com/big-bash-league-2011/engine/match/524915.html
首先让我们find具有该信息的表的名称。 只需右键点击表格,点击“用Firebug检查元素”,它会给你下面的快照。
所以现在我们知道我们的数据存储在一个名为“inningsBat1”的表中。如果我们可以将该表的内容提取到一个Excel文件中,那么我们可以肯定地使用这些数据来进行分析。 这是示例代码将转储Sheet 1中的表
在我们继续之前,我会build议closures所有的Excel并开始一个新的实例。
启动VBA并插入一个用户窗体。 放置一个命令button和webcrowser控件。 您的Userform可能看起来像这样
将此代码粘贴到Userform代码区域中
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
现在运行您的用户窗体并单击命令button。 您会注意到数据被转储到Sheet1中。 看快照
同样,你也可以刮其他信息。
2)使用Excel的内置工具从网上获取数据
我相信你正在使用Excel 2007,所以我将以此为例来抓取上述链接。
导航到Sheet2。 现在导航到“数据”选项卡,然后单击最右侧的“从Web”button。 看快照。
在“新buildWeb查询窗口”中inputurl,然后点击“开始”
页面上传后,通过单击快照中显示的小箭头来select要导入的相关表格。 完成后,点击“导入”
然后Excel会问你想要导入数据的位置。 select相关单元格并单击确定。 你完成了! 数据将被导入到您指定的单元格中。
如果你希望你可以logging一个macros,并自动化,以及:)
这是我录制的macros。
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早期答案的代码
-
XMLHttp
比自动化IE
快得多 - 代码会为每个要下载的系列生成一个CSV文件(保存在
X
variables中) - 该代码将每场比赛转换为普通的29行(不pipe有多less玩家被击中),以便日后更便于分析
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不是parsingHTML的完整解决scheme,因为它不能保证是正常的。
您应该使用HtmlAgilityPack来查询HTML。 这将允许您使用CSSselect器查询HTML,与您如何使用jQuery进行查询相似。
- PatternSyntaxException:在Java中使用正则expression式时非法重复
- Perl中的正则expression式组:如何从正则expression式组中捕获元素,匹配来自string的未知数/多个/variables出现的元素?
- 匿名方法(C#2.0)和lambdaexpression式(C#3.0)之间有什么区别?
- 如何在正则expression式中匹配“直到这个字符序列的任何东西”?
- 捕获不在NSRegularExpression中工作的组
- 在re.search中使用start / end参数时,在正则expression式中$和^之间的不一致?
- 如何使用grep获取`name =`之后的任何内容?
- RegEx排除一个特定的string常量
- Javastring分割为“。”(点)