html - 如何从 tvdb 中抓取剧集编号
问题描述
我正在尝试从 tvdb 中分离和处理总季集数。就像我与 show LEGION ( https://www.thetvdb.com/series/legion ) 一起工作的一个简单示例。此主页将显示该节目有多少季,并且在该行的末尾,有一个徽章指示每个季节的剧集数。我想要一个节目的“绝对数量”剧集,所以我需要将所有这些数字加在一起。这是我能够做到的,但是我想排除“特价”季节剧集编号,这是困难的部分。特别是因为这些元素的内部文本将在指示它所引用的季节之前显示徽章值。
我经历了几个阶段。首先,我能够获得父标签的内部文本,它给了我一个信息块,说明表中的所有内容如下(似乎有 2 个标签具有相同的类名,这就是为什么我得到双重结果。任何帮助这也将不胜感激)
特价 2018 年 4 月 - 2018 年 4 月 8
季节 2017 年 2 月 1 日 - 2017 年 3 月 11
第 2 季 2018 年 4 月 - 2018 年 6 月 8
第 3 季 2019 年 6 月 - 2019 年 8 月
四季
1 特价 2018 年 4 月 - 2018 年 4 月
8 季 2017 年 2 月 1 日 - 2017 年 3 月
11 季 2018 年 4 月 2 日 - 2018 年 6 月
8 季 2019 年 6 月 3 日 - 2019 年 8 月
四季
其次,我能够通过循环遍历父标签中的所有元素来一次隔离一个块,如下所示
1 特价 2018 年 4 月 - 2018 年 4 月
第三,我已经到了可以再次循环并仅隔离徽章中的数字的阶段(我说徽章,因为它是在 html 代码中引用的方式)
我还回溯并使用了第 2 阶段,并在其中放置了一个正则表达式函数来识别单词“specials”,但无法弄清楚如何跳过它并继续运行 for 循环。
我相信我可能需要与父母、孩子、兄弟姐妹一起编码才能实现我想要的。
提前致谢
Sub()
Dim XML_05 As New MSXML2.XMLHTTP60
Dim HTML_05 As New MSHTML.HTMLDocument
XML_05.Open "GET", "https://www.thetvdb.com/series/legion", False
XML_05.send
HTML_05.body.innerHTML = XML_05.responseText
Dim NETC_05 As MSHTML.IHTMLElementCollection
Dim NET_05 As MSHTML.IHTMLElement
Dim REO_05 As VBScript_RegExp_55.RegExp
Dim MO_05 As Object
Dim SeasonsList As MSHTML.IHTMLElementCollection
Dim SeasonsInfo As MSHTML.IHTMLElement
Dim SI_05 As MSHTML.IHTMLElement
Dim Badge As MSHTML.IHTMLElement
Set SeasonsList = HTML_05.getElementsByClassName("hidden-sm hidden-md hidden-lg")
For Each SeasonsInfo In SeasonsList
Debug.Print SeasonsList.Length
For Each SI_05 In SeasonsInfo.getElementsByTagName("li")
For Each Badge In SI_05.Children
Debug.Print Badge.innerText
Next Badge
Next SI_05
Next SeasonsInfo
End Sub
解决方案
Specials
is first and All Seasons
is last 所以你可以循环一个nodeList
from 1
tonodeList.Length-2
来避免这两个节点,并简单地将它们之间的数字相加。我使用一个代理 HTMLDocument 变量来保存每个节点的 html,这样我就可以再次利用并避免通过等querySelector
长链。我不确定你是否在某个时候也想要其他信息,所以我存储了每个季节的名称、日期和数组中的情节计数(不包括所描述的节点)。这种方法还意味着代码复杂性降低到单个循环。getElements
nextSibling
results
Option Explicit
Public Sub GetTotalEpisodes()
Dim i As Long, html As MSHTML.HTMLDocument, html2 As MSHTML.HTMLDocument, seasons As Object, results(), r As Long
Set html = New HTMLDocument: Set html2 = New HTMLDocument
With CreateObject("MSXML2.XMLHTTP")
.Open "GET", "https://www.thetvdb.com/series/legion", False
.send
html.body.innerHTML = .responseText
End With
Set seasons = html.querySelectorAll(".hidden-xs .list-group-item")
ReDim results(1 To seasons.Length - 2, 1 To 3)
For i = 1 To seasons.Length - 2
html2.body.innerHTML = seasons.item(i).outerHTML
results(i, 1) = Trim$(html2.querySelector(".list-group-item-heading").innerText)
results(i, 2) = Trim$(html2.querySelector(".list-group-item-text").innerText)
results(i, 3) = 1 * html2.querySelector(".badge").innerText
Next
Debug.Print Application.Sum(Application.index(results, 0, 3))
End Sub
如果您想存储所有信息,包括第一个和最后一个节点,但仍执行条件求和,您可以将标题排除在数组中并在循环期间检查该标题;仅当当前标头不在排除数组中时求和
Option Explicit
Public Sub GetTotalEpisodes()
Dim i As Long, html As MSHTML.HTMLDocument, html2 As MSHTML.HTMLDocument, seasons As Object, results(), r As Long
Dim exclusions(), heading As String, badge As Long, total As Long
Set html = New HTMLDocument: Set html2 = New HTMLDocument
exclusions = Array("Specials", "All Seasons")
With CreateObject("MSXML2.XMLHTTP")
.Open "GET", "https://www.thetvdb.com/series/legion", False
.send
html.body.innerHTML = .responseText
End With
Set seasons = html.querySelectorAll(".hidden-xs .list-group-item")
ReDim results(1 To seasons.Length, 1 To 3)
On Error Resume Next
For i = 0 To seasons.Length - 1
html2.body.innerHTML = seasons.item(i).outerHTML
heading = Trim$(html2.querySelector(".list-group-item-heading").innerText)
badge = 1 * html2.querySelector(".badge").innerText
results(i + 1, 1) = html2.querySelector(".list-group-item-heading").innerText
results(i + 1, 2) = Trim$(html2.querySelector(".list-group-item-text").innerText)
results(i + 1, 3) = badge
If IsError(Application.match(heading, exclusions, 0)) Then
total = total + badge
End If
Next
On Error GoTo 0
Debug.Print total
End Sub
操作问题:
- Option Explicit - 强制变量声明。
当 Option Explicit On 或 Option Explicit 出现在文件中时,您必须使用 Dim 或 ReDim 语句显式声明所有变量。如果您尝试使用未声明的变量名,则会在编译时发生错误。Option Explicit Off 语句允许隐式声明变量。
这是最佳实践,对于捕获拼写错误也很有用。
results()
- 我正在声明一个动态数组,这意味着我还不知道所需的尺寸,但稍后会在我知道时重新调整。它实际上是 results() As Variant(隐式)。另请参见此处。我可以稍后再调整,因为此时设置季节 = html.querySelectorAll(".hidden-xs .list-group-item")
seasons.Length
会给我第一个维度的行数results()
。
- querySelectorAll - 类似于
getElementsBy
. 它将CSS 选择器(或组合)应用于HTMLDocument(例如ie.Document
)。
Document 方法 querySelectorAll() 返回一个静态(非实时)NodeList,表示与指定选择器组匹配的文档元素列表
现代浏览器针对 css 进行了优化,因此这通常是一种快速灵活的查找节点的方法。
Trim$
- 是Trim
. 它用于从node.innerText
.底部版本应该适用于单季。只需更改数组
exclusions
以说明您希望包含/排除的内容。如果没有,请给我一个例子,我会为你更新。
推荐阅读
- flex-lexer - flex 的条件
- javascript - 如何将 ajax 成功数据中的值显示到 html 表中?
- javascript - 无法在 firebase 中使用数据 - 错误:FIREBASE 致命错误:无法解析 Firebase url。请使用 https://
.firebaseio.com - node.js - 不能在模块外使用 import 语句
- r - R中是否有一种快速的方法来预测来自RANN的最近邻模型的观察的类结果?
- wordpress - Wordpress 自定义字段 - 嵌套 foreach
- firebase - 使用哈希算法将用户迁移到新的 Firebase 数据库的问题
- double - GLSL:平滑双输入
- php - 合并数组 / foreach 中的重复条目
- javascript - 更好地使用对象列表的转换,而不是使用 2 个减速器