我正在尝试从HTML字符串中提取信息,但我得到了意想不到的结果。我正在使用的代码如下:
let html: NSString? = "<tbody><tr><td sortkey=\"20151003\">03 Oct 2015</td><td>8,852.61</td><td>1,383.68</td><td>Text</td></tr><tr><td sortkey=\"20151004\">04 Oct 2015</td><td>2,577.14</td><td>282.49</td><td>Text</td></tr></tbody>"
let rowPattern = "<tr>\\s*<td s.*?<\\/tr>"
let rowRegex = try! NSRegularExpression(pattern: rowPattern, options: [])
let rowMatches = rowRegex.matchesInString(String(html), options: [], range: NSMakeRange(0, html!.length))
for rowMatch in rowMatches {
let rowString: NSString = html!.substringWithRange(rowMatch.resultByAdjustingRangesWithOffset(-9).range)
print(rowString)
let valPattern = "<td>(.*?)<\\/td>|<td.*?\"(.*?)\">.*?<\\/td>"
let valRegex = try! NSRegularExpression(pattern: valPattern, options: [])
let valMatches = valRegex.matchesInString(String(rowString), options: [], range: NSMakeRange(0, rowString.length))
for valMatch in valMatches {
print(valMatch.rangeAtIndex(1))
// let value = rowString.substringWithRange(valMatch.rangeAtIndex(1))
// print(value)
}
}
输出是:
<tr><td sortkey="20151003">03 Oct 2015</td><td>8,852.61</td><td>1,383.68</td><td>Text</td></tr>
(9223372036854775807,0)
(47,8)
(64,8)
(81,4)
首先,请注意我需要将rowMatch的范围偏移-9才能获得正确的结果。我不知道为什么会这样。
其次,第一场比赛返回的范围是(9223372036854775807,0),显然不正确并引发错误。同样,我不明白这里出了什么问题,但我怀疑这可能是我的正则表达式模式的问题。其他范围是正确的。
有关信息,print(value)
的预期输出为:
20151003
8,852.61
1,383.68
Text
修改
经过进一步的实验,我发现了以下内容:
valMatches[0].rangeAtIndex(2)
为第一场比赛提供了正确的范围,但其余的则需要valMatches[0].rangeAtIndex(1)
。我不确定这是否是正确的行为,或者是否是@ t4nhpt在下面的回答中提出的错误。无论哪种方式,如果有人能够解释发生了什么,那将是件好事。
答案 0 :(得分:2)
第一个问题是let html: NSString? = "..."
是可选,
因此String(html)
评估为
Optional(...)
神秘偏移9
是“Optional(”:)
要解决此问题,您可以解开String(html!)
或声明html
作为非选择性的。无论哪种情况,都不需要resultByAdjustingRangesWithOffset(-9)
。
第二个问题是你的两个捕获组 图案:
let valPattern = "<td>(.*?)<\\/td>|<td.*?\"(.*?)\">.*?<\\/td>"
<td>8,852.61</td>
匹配第一个选项,因此
第一个捕获组匹配8,852.61
,所以
rangeAtIndex(1)
设置为该字符串的范围,并且
rangeAtIndex(2)
设置为(NSNotFound, 0)
。
<td sortkey="20151003">03 Oct 2015</td>
匹配第二个
替代方案,因此rangeAtIndex(2)
设置为
20151003
和rangeAtIndex(1)
的范围是(NSNotFound, 0)
。
NSNotFound
在64位平台上定义为Int.max
,即2^63 - 1 = 9223372036854775807
。
总而言之,这给出了预期的结果:
let html: NSString = "<tbody><tr><td sortkey=\"20151003\">03 Oct 2015</td><td>8,852.61</td><td>1,383.68</td><td>Text</td></tr><tr><td sortkey=\"20151004\">04 Oct 2015</td><td>2,577.14</td><td>282.49</td><td>Text</td></tr></tbody>"
let rowPattern = "<tr>\\s*<td s.*?<\\/tr>"
let rowRegex = try! NSRegularExpression(pattern: rowPattern, options: [])
let rowMatches = rowRegex.matchesInString(String(html), options: [], range: NSMakeRange(0, html.length))
for rowMatch in rowMatches {
let rowString: NSString = html.substringWithRange(rowMatch.range)
print("rowString=\(rowString)")
let valPattern = "<td>(.*?)<\\/td>|<td.*?\"(.*?)\">.*?<\\/td>"
let valRegex = try! NSRegularExpression(pattern: valPattern, options: [])
let valMatches = valRegex.matchesInString(String(rowString), options: [], range: NSMakeRange(0, rowString.length))
for valMatch in valMatches {
if valMatch.rangeAtIndex(1).location != NSNotFound {
let value = rowString.substringWithRange(valMatch.rangeAtIndex(1))
print(value)
}
if valMatch.rangeAtIndex(2).location != NSNotFound {
let value = rowString.substringWithRange(valMatch.rangeAtIndex(2))
print(value)
}
}
}
输出:
rowString=<tr><td sortkey="20151003">03 Oct 2015</td><td>8,852.61</td><td>1,383.68</td><td>Text</td></tr>
20151003
8,852.61
1,383.68
Text
rowString=<tr><td sortkey="20151004">04 Oct 2015</td><td>2,577.14</td><td>282.49</td><td>Text</td></tr>
20151004
2,577.14
282.49
Text
答案 1 :(得分:1)
加入两种模式似乎是一个错误。您可以将模式拆分为两部分,找到两个[NSTextCheckingResult]
然后将它们连接在一起。作弊,哈哈。
// let valPattern = "<td>(.*?)<\\/td>|<td.*?\"(.*?)\">.*?<\\/td>"
let valPattern1 = "<td.*?\"(.*?)\">.*?<\\/td>"
let valPattern2 = "<td>(.*?)<\\/td>"
var valRegex = try! NSRegularExpression(pattern: valPattern1, options: [])
var valMatches1 = valRegex.matchesInString(String(rowString), options: [], range: NSMakeRange(0, rowString.length))
valRegex = try! NSRegularExpression(pattern: valPattern2, options: [])
let valMatches2 = valRegex.matchesInString(String(rowString), options: [], range: NSMakeRange(0, rowString.length))
valMatches1 += valMatches2
for valMatch in valMatches1 {
...