如何从博彩网站中提取div_class表

时间:2019-09-28 02:53:35

标签: html vba web-scraping

我一直在搜索,但运气不佳。我试图获取https://www.sportsinteraction.com/football/nfl-betting-lines/上正在玩的游戏的文字。因此,最后我希望像下面这样吐出一些东西(不一定是干净的)。

Carolina Panthers 休斯顿德州人 点差 +4.0 1.90 -4.0 1.92

MONEYLINE 2.69 1.49

上方/下方 Ø +47.0 1.91 ü +47.0 1.91

下面的代码显然是错误的:

    Sub Pulldata2()

 Dim ieObj As InternetExplorer
 Dim appIE As Object
 Dim htmlEle As IHTMLElement
 Dim i As Integer
 Dim strSheet As String

    strSheet = Sheet2.Range("P2")
    i = 1

    Set ieObj = New InternetExplorer
    ieObj.Visible = False
    ieObj.navigate Sheet2.Range("P2").Value


    Application.ScreenUpdating = False
    Application.DisplayStatusBar = False
    Application.Wait Now + TimeValue("00:00:03")
    Sheet13.Activate

    For Each htmlEle In ieObj.document.getElementsByClassName("game")(0)
        With ActiveSheet
            .Range("A1").Value

    End With
    i = i + 1
    On Error Resume Next
Next htmlEle



End Sub



1 个答案:

答案 0 :(得分:1)

为什么?

这是一个有趣的练习技巧,值得花时间尝试。有趣的是,没有一种立即明显的方法可以用关联的元数据来``阻止''每个事件,例如日期,时间,比赛标题;并且下注内容在水平分组和垂直分组之间切换,使您的选择节点识别节点的策略特别重要。


策略:

我决定采用的策略如下:使用css类选择器获取包含所有所需信息的长节点列表。 date, time and title是节点,我需要为每个gameBettingContent块中的每个团队在两行中重复其信息。

注意:内容是静态的,因此可以使用XHR来避免打开浏览器和呈现不必要内容的开销。这种方法要快很多。


逻辑块的剖析:

enter image description here

请注意,每个类别为gameBettingContent的父节点包含3个类别为betTypeContent的子节点。这些孩子与PointSpread, MoneyLine and Over/Under相对应。这些将需要在输出中占据自己的列,包括将pricehandicap分开。对于每个逻辑块,如上所示,将有两行,在输出的前几列中重复一些信息。


nodeList:

因此,最初,我们在nodeList上有className个匹配的所有感兴趣的元素。这些节点中有一些子节点,然后我们需要访问这些子节点。为避免复杂的访问器语法,当我们到达需要访问其子节点(或更深节点)的节点时,我们将该节点的html加载到“代理”中,即new HTMLDocument变量中,因此我们可以利用再次使用querySelectorAll的{​​{1}}方法。这使我们的语法易于阅读,并且成本最低。

enter image description here

我们循环显示HTMLDocument(如左上方所示),并测试每个当前节点的nodeList,然后使用className语句确定要做什么。如果当前的className为Select Case,我们将存储该节点的date, time or title供以后使用(请记住,我们需要在流道1和流道2上重复此值)。如果.innerTextclassName,我们将该节点的gameBettingContent加载到代理outerHTML中,即HTMLDocument。然后,我们可以收集html2并开始填充输出数组runners。首先,我们在变量resultsTable中添加+2(行计数器),因此我们准备好进行下一个逻辑块(即匹配),然后使用rr-2


使用替代HTMLDocument变量在DOM较深的节点上利用r-1

由于我们将querySelectorAllMSXML2.XMLHTTP一起使用,因此无法访问nth-of-type pseudo class css选择器语法(在使用MSHTML.HTMLDocument时要与ie.document一起使用)区分SHDocVw.InternetExplorer中的下注类型的3个div(列);而我们可以将类选择器和adjacent sibling combinators链接起来,使其在div(列)中从左向右移动,例如

PointSpread:

gameBettingContent

MoneyLine:

.gameBettingContent #runnerNames + .betTypeContent

上方/下方:

.gameBettingContent #runnerNames + .betTypeContent + .betTypeContent

我发现将这些div收集到nodeList中更干净

.gameBettingContent #runnerNames + .betTypeContent + .betTypeContent + .betTypeContent

然后将每个div(列)Set contentDivs = html2.querySelectorAll(".betTypeContent") 加载到新的outerHTML代理HTMLDocument中,并再次利用querySelectorAll从每一列的索引中收集两行信息。

例如,html3将是PointsSpread中的第一个节点,我们将其读入contentDivs

html3

enter image description here

然后我们选择差点和价格

html3.body.innerHTML = contentDivs.item(0).outerHTML

并且可以使用索引来获得跑步者1与跑步者2的值:

Set pointSpreadHandicaps = html3.querySelectorAll(".handicap")
Set pointSpreadPrices = html3.querySelectorAll(".price")

这几乎是大部分逻辑。输出数组的大小基于等于的行数

resultsTable(r - 2, 5) = pointSpreadHandicaps.item(0).innerText: resultsTable(r - 1, 5) = pointSpreadHandicaps.item(1).innerText

即有多少名运动员。列数等于我们在html.querySelectorAll("#runnerNames li").Length 数组中指定的项目数(由于数组是从0开始的,所以我们在headers上加1)。然后将数组和标题一样写到表中。


VBA:

Ubound

从结果中选择示例:

enter image description here


其他阅读内容:

  1. css selectors
  2. querySelectorAll
  3. HTMLDocument