Lấy dữ liệu trên web (1 người xem)

  • Thread starter Thread starter Hanh.nt
  • Ngày gửi Ngày gửi
Liên hệ QC

Người dùng đang xem chủ đề này

Hanh.nt

Thành viên mới
Tham gia
4/1/20
Bài viết
11
Được thích
1
Xin chào các anh chị,
Em muốn lấy dữ liệu từ web "http://data.7m.com.cn/team_history_odds_data/2019/m92/200/total/index_vn.htm" bằng vba. Em dùng "Set hTable = .getElementById("team_odds_away_tb")" để lấy dữ liệu bảng, tiếp đó là "Set trs = hTable.getElementsByTagName("tr")" để lấy dữ liệu các dòng, trên web là có tổng cộng 40 dòng nhưng em chỉ lấy được 2 dòng đầu, em chưa biết nguyên nhân vì sao. Các anh chị xem file đính kèm và giúp em với ạ
 

File đính kèm

Bạn xài tới cái "getElementById" này thì chắc mình phải mang bánh chưng nhân thịt lợn tới bái sư rồi. :D
Bạn mở cái link ở bài 2 xem trong ấy có cái gì.

Cái này là em học vẹt chứ ko hiểu bản chất lắm: "getElementById" là lấy phần nội dung có chứa Id (ấn f12 khi đang trên web). Còn cái link của bác gửi thì em ko hiểu gì
 
Upvote 0
Tỉ lệ: f_tod_rq, với Thắng là âm, Thua và hòa thì dương.
f_tod_rq là Tỉ lệ chấp


-------------------------------------------------------
Vì sao phải là dữ liệu "Bóng Đá" vậy?

Dữ liệu kia đã được lưu vào một file Javascript, chính vì vậy mà không thể dùng Request để lấy dữ liệu mà phải đi trực tiếp vào file index_vn.js kia. Hoặc phải dùng một Webrowser trung gian để cạo (Thư viện MS Internet Control).

Để chuyển dữ liệu từ file js kia thành mảng, sử dụng ScriptControl với ngôn ngữ "JScript".

JavaScript:
Sub test_SoccerScore()
  Dim sYear$, id$, Tournaments$
  sYear = 2019
  id = 200
  Tournaments = "m92"
  Call SoccerScore(sYear$, id$, Tournaments$, [A3])
End Sub
Sub SoccerScore(sYear$, id$, Tournaments$, Optional ByVal Rng As Range)
  Dim Link$
  Static Http As Object, RE As Object
  Link = "http://data.7m.com.cn/team_history_odds_data/" & sYear & "/" & Tournaments & "/" & id & "/index_vn.js"
  If Http Is Nothing Then
    Set Http = VBA.Interaction.CreateObject("WinHttp.WinHttpRequest.5.1")
    Set RE = VBA.Interaction.CreateObject("VBScript.RegExp")
        RE.Global = 1
        RE.IgnoreCase = 1
        RE.MultiLine = 1
        RE.Pattern = "var ([A-z]{1}[A-z\d_]{0,255}) = \["
  End If
  With Http
    .Open "GET", Link, False
    .Send ""
    If .Status = 200 Then
      Dim sc As Object, Text$, s$, Ss, I%, j%, C%, R%
      Set sc = VBA.Interaction.CreateObject("MSScriptControl.ScriptControl")
      Text = VBA.Replace(.responseText, "", "")
      With RE
        If .test(Text) Then
          Dim Ms, M: Set Ms = .Execute(Text)
          C = Ms.Count - 1
'          For I = 0 To C
'            s = s & VBA.IIf(s = "", "", ", ") & Ms(I).SubMatches(0)
'          Next
'          s = "var arr = [" & s & "];"
          's = "var arr = [f_tod_stm, f_tod_bh, f_tod_mn, f_tod_rq, f_tod_rql, f_tod_asc, f_tod_bsc, f_tod_ar, f_tod_br, f_tod_ati, f_tod_atn, f_tod_bti, f_tod_btn, f_tod_worl, f_tod_ha, f_rank_h, f_rank_a];"
          s = "var arr = [f_tod_mn, f_tod_stm, f_tod_atn, f_tod_asc, f_tod_btn, f_tod_rq, f_tod_worl,f_rank_h,  f_tod_bsc, f_rank_a ];"
          With sc
                .Language = "JScript"
                .AddCode Text & vbNewLine & s & " function setArray(index){" & _
                    "var dict = new ActiveXObject('Scripting.Dictionary');" & _
                    "for (var i=0; i < arr[index].length; i++ ){" & _
                       "var s;" & _
                       "if (index==3){s=arr[index][i].toString() + ' - ' + arr[index+5][i].toString()}" & _
                       "else if (index==2 || index==4){s=arr[index][i].toString() + '[' + arr[index+5][i].toString() + ']'}" & _
                       "else{s=arr[index][i] };" & _
                       "dict.add(i, s)};" & _
                       "return dict.items();" & _
                    "}"

            For I = 0 To 6
              Ss = .Run("setArray", I)
              If R = 0 Then
                R = UBound(Ss)
                ReDim Total(1 To R + 1, 1 To C + 1)
              End If
              For j = 0 To R
                If I = 6 Then
                  Total(j + 1, I + 1) = VBA.IIf(Ss(j) = 0, "Win", VBA.IIf(Ss(j) = 3, "Lose", "Draw"))
                Else
                  Total(j + 1, I + 1) = Ss(j)
                End If
              Next
            Next
            If Not Rng Is Nothing Then _
               Rng(1, 1).Resize(R + 1, C + 1).Value = Total
          End With
        End If
      End With
      Set sc = Nothing
    End If
  End With
End Sub
 
Lần chỉnh sửa cuối:
Upvote 0
Upvote 0
Bị đoạn này nữa bác ạ.

Bác có file chứng khoán hay quá, em cũng có làm mấy file như thế để tự tính toán các chỉ tiêu tài chính cho riêng mình.
Máy tính của bạn không có thư viện đấy thì đành chịu thôi.

Thư viện Microsoft Script Control 1.0 chạy trên nền Win64 bit. (chưa kiểm thử 32bit nên chưa biết)

Hoặc học Regular Expression và thực hiện thôi. (mất 30 phút)

Vấn đề "Bóng đá" có chút lệch lạc, nên tôi không hỗ trợ thêm.
 
Upvote 0
Upvote 0
cũng có làm mấy file như thế để tự tính toán các chỉ tiêu tài chính cho riêng mình
Hic. Vậy vớ được link ở bài #2 coi như về đích rồi còn gì.
Lấy toàn bộ nội dung đó về rồi xử lý lèo cái là xong thôi. Không cần ghê gớm như trên đâu, xử lý chuỗi là quá 'ngon' rồi.
 
Upvote 0
Hic. Vậy vớ được link ở bài #2 coi như về đích rồi còn gì.
Lấy toàn bộ nội dung đó về rồi xử lý lèo cái là xong thôi. Không cần ghê gớm như trên đâu, xử lý chuỗi là quá 'ngon' rồi.
Thật sự là em chưa làm đến cái link kiểu như #2 bao giờ. Còn cái file chứng khoán thì em cũng làm gần giống code #1 để lấy Báo cáo tài chính dạng thô trên Cafef về, rồi xây dựng công thức tính toán mà thôi. Bác giúp em nhé
 
Upvote 0
Bạn ngóng đợi "Thần thánh phương khác" xem có giúp bạn tốt hơn không!

Thử sửa lại Set sc = VBA.Interaction.CreateObject("ScriptControl")

Cách khác:
---------------
JavaScript:
Sub test_SoccerScore2()
  Dim sYear$, id$, Tournaments$
  sYear = 2019
  id = 200
  Tournaments = "m92"
  Call SoccerScore2(sYear$, id$, Tournaments$, [A3])
End Sub
Sub SoccerScore2(sYear$, id$, Tournaments$, Optional ByVal Rng As Range)
  Dim Link$
  On Error Resume Next
  Dim Http As Object, RE As Object, F_
  Link = "http://data.7m.com.cn/team_history_odds_data/" & sYear & "/" & Tournaments & "/" & id & "/index_vn.js"

  Set Http = VBA.Interaction.CreateObject("WinHttp.WinHttpRequest.5.1")
  Set RE = VBA.Interaction.CreateObject("VBScript.RegExp")
      RE.Global = 1
      RE.IgnoreCase = 1
      RE.MultiLine = 1
  With Http
    .Open "GET", Link, False
    .send ""
    Dim Text$, I%, j%, R%
    Text = .responseText
    RE.Pattern = "(?:var +(?:(?:f_tod_(?:(?:stm)|(?:mn)|(?:asc)|(?:rq)|(?:worl)|(?:atn)|(?:btn)|(?:bsc)))" & _
       "|(?:f_rank_(?:h|a))) *= *\[ *)" & "((?:'?[0-9A-z\s.:%&\-_\""]*'?\s*,?)+)\]"
    If RE.test(Text) Then
      Dim Ms, Ms2, Ms3, Tmp$: Set Ms = RE.Execute(Text)
      RE.Pattern = "[0-9A-z\s.:%&\-_]+|'{2}"
      F_ = Array(1, 0, 5, 3, 6, 2, 7, 8, 4, 9)
      For I = 0 To 6
        Set Ms2 = RE.Execute(Ms(F_(I)).SubMatches(0))
        If R = 0 Then
          R = Ms2.Count
          ReDim Total(1 To R, 1 To 7)
        End If
        For j = 0 To R - 1
          If I = 2 Or I = 3 Or I = 4 Then
            Set Ms3 = RE.Execute(Ms(F_(I + 5)).SubMatches(0))
            If I = 3 Then
              Total(j + 1, I + 1) = "'" & Ms2(j) & " - " & Ms3(j)
            Else
              Total(j + 1, I + 1) = Ms2(j) & VBA.IIf(Ms3(j) = "''", "", "[" & Ms3(j) & "]")
            End If
          ElseIf I = 6 Then
            Total(j + 1, I + 1) = VBA.IIf(Ms2(j) = 0, "Win", VBA.IIf(Ms2(j) = 3, "Lose", "Draw"))
          Else
            Total(j + 1, I + 1) = Ms2(j)
          End If
        Next
      Next
      If Not Rng Is Nothing Then _
        Rng.Resize(R, 7).Value = Total
    End If
    Set sc = Nothing
  End With
End Sub
 
Lần chỉnh sửa cuối:
Upvote 0
Bạn ngóng đợi "Thần thánh phương khác" xem có giúp bạn tốt hơn không!

Thử sửa lại Set sc = VBA.Interaction.CreateObject("ScriptControl")

Cách khác:
---------------
JavaScript:
Sub test_SoccerScore2()
  Dim sYear$, id$, Tournaments$
  sYear = 2019
  id = 200
  Tournaments = "m92"
  Call SoccerScore2(sYear$, id$, Tournaments$, [A3])
End Sub
Sub SoccerScore2(sYear$, id$, Tournaments$, Optional ByVal Rng As Range)
  Dim Link$
  On Error Resume Next
  Dim Http As Object, RE As Object, F_
  Link = "http://data.7m.com.cn/team_history_odds_data/" & sYear & "/" & Tournaments & "/" & id & "/index_vn.js"

  Set Http = VBA.Interaction.CreateObject("WinHttp.WinHttpRequest.5.1")
  Set RE = VBA.Interaction.CreateObject("VBScript.RegExp")
      RE.Global = 1
      RE.IgnoreCase = 1
      RE.MultiLine = 1
  With Http
    .Open "GET", Link, False
    .send ""
    Dim Text$, I%, j%, R%
    Text = .responseText
    RE.Pattern = "(?:var +(?:(?:f_tod_(?:(?:stm)|(?:mn)|(?:asc)|(?:rq)|(?:worl)|(?:atn)|(?:btn)|(?:bsc)))" & _
       "|(?:f_rank_(?:h|a))) *= *\[ *)" & "((?:'?[0-9A-z\s.:%&\-_\""]*'?\s*,?)+)\]"
    If RE.test(Text) Then
      Dim Ms, Ms2, Ms3, Tmp$: Set Ms = RE.Execute(Text)
      RE.Pattern = "[0-9A-z\s.:%&\-_]+|'{2}"
      F_ = Array(1, 0, 5, 3, 6, 2, 7, 8, 4, 9)
      For I = 0 To 6
        Set Ms2 = RE.Execute(Ms(F_(I)).SubMatches(0))
        If R = 0 Then
          R = Ms2.Count
          ReDim Total(1 To R, 1 To 7)
        End If
        For j = 0 To R - 1
          If I = 2 Or I = 3 Or I = 4 Then
            Set Ms3 = RE.Execute(Ms(F_(I + 5)).SubMatches(0))
            If I = 3 Then
              Total(j + 1, I + 1) = "'" & Ms2(j) & " - " & Ms3(j)
            Else
              Total(j + 1, I + 1) = Ms2(j) & VBA.IIf(Ms3(j) = "''", "", "[" & Ms3(j) & "]")
            End If
          ElseIf I = 6 Then
            Total(j + 1, I + 1) = VBA.IIf(Ms2(j) = 0, "Win", VBA.IIf(Ms2(j) = 3, "Lose", "Draw"))
          Else
            Total(j + 1, I + 1) = Ms2(j)
          End If
        Next
      Next
      If Not Rng Is Nothing Then _
        Rng.Resize(R, 7).Value = Total
    End If
    Set sc = Nothing
  End With
End Sub

Chạy ngon rồi bác ạ. Em cảm ơn bác nhiều.

Bác có phải là dân chứng khoán không ạ?
 
Upvote 0

Bài viết mới nhất

Back
Top Bottom