如何使用 XmlSlurper 解析格式不正确的 HTML
How to parse non-well formatted HTML with XmlSlurper
我正在尝试使用 XmlSlurper 解析格式不正确的 HTML 页面,the Eclipse download site The W3C validator 在页面中显示了几个错误。
我尝试了 this post
的容错解析器
@Grab(group='net.sourceforge.nekohtml', module='nekohtml', version='1.9.14')
import org.cyberneko.html.parsers.SAXParser
import groovy.util.XmlSlurper
// Getting the xhtml page thanks to Neko SAX parser
def mirrors = new XmlSlurper(new SAXParser()).parse("http://www.eclipse.org/downloads/download.php?file=/technology/epp/downloads/release/luna/SR1a/eclipse-jee-luna-SR1a-linux-gtk-x86_64.tar.gz")
mirrors.'**'
不幸的是,似乎并非所有内容都被解析到 XML 对象中。错误的子树被简单地忽略了。
例如page.depthFirst().find { it.text() == 'North America'}
returns null
而不是页面中的 H4 元素。
是否有一些可靠的方法来解析 groovy 中的任何 HTML 内容?
使用以下代码可以很好地解析(没有错误):
@Grab(group='net.sourceforge.nekohtml', module='nekohtml', version='1.9.14')
import org.cyberneko.html.parsers.SAXParser
import groovy.util.XmlSlurper
def parser = new SAXParser()
def page = new XmlSlurper(parser).parse('http://www.eclipse.org/downloads/download.php?file=/technology/epp/downloads/release/luna/SR1a/eclipse-jee-luna-SR1a-linux-gtk-x86_64.tar.gz')
但是我不知道你到底想找到哪些元素。
这里 All mirrors
被发现:
page.depthFirst().find {
it.text() == 'All mirrors'
}.@href
编辑
两个输出都是null
.
println page.depthFirst().find { it.text() == 'North America'}
println page.depthFirst().find { it.text().contains('North America')}
编辑 2
您可以在下面找到一个下载文件并正确解析文件的工作示例。我使用 wget
下载文件(使用 groovy 下载文件有问题 - 不知道是什么)
@Grab(group='net.sourceforge.nekohtml', module='nekohtml', version='1.9.14')
import org.cyberneko.html.parsers.SAXParser
import groovy.util.XmlSlurper
def host = 'http://www.eclipse.org/downloads/download.php?file=/technology/epp/downloads/release/luna/SR1a/eclipse-jee-luna-SR1a-linux-gtk-x86_64.tar.gz'
def temp = File.createTempFile('eclipse', 'tmp')
temp.deleteOnExit()
def cmd = ['wget', host, '-O', temp.absolutePath].execute()
cmd.waitFor()
cmd.exitValue()
def parser = new SAXParser()
def page = new XmlSlurper(parser).parseText(temp.text)
println page.depthFirst().find { it.text() == 'North America'}
println page.depthFirst().find { it.text().contains('North America')}
编辑 3
终于问题解决了。当没有指定 User-Agent
header 时,使用 groovy 的 url.toURL().text
会导致问题。现在它可以正常工作并找到元素 - 没有使用外部工具。
@Grab(group='net.sourceforge.nekohtml', module='nekohtml', version='1.9.14')
import org.cyberneko.html.parsers.SAXParser
import groovy.util.XmlSlurper
def host = 'http://www.eclipse.org/downloads/download.php?file=/technology/epp/downloads/release/luna/SR1a/eclipse-jee-luna-SR1a-linux-gtk-x86_64.tar.gz'
def parser = new SAXParser()
def page = new XmlSlurper(parser).parseText(host.toURL().getText(requestProperties: ['User-Agent': 'Non empty']))
assert page.depthFirst().find { it.text() == 'North America'}
assert page.depthFirst().find { it.text().contains('North America')}
我喜欢 tagsoup SAX 解析器,它说它是为解析 "poor, nasty and brutish" HTML 而设计的。
它可以很容易地与XmlSlurper
结合使用:
@Grab(group='org.ccil.cowan.tagsoup', module='tagsoup', version='1.2')
def parser = new XmlSlurper(new org.ccil.cowan.tagsoup.Parser())
def page = parser.parse('http://www.eclipse.org/downloads/download.php?file=/technology/epp/downloads/release/luna/SR1a/eclipse-jee-luna-SR1a-linux-gtk-x86_64.tar.gz')
println page.depthFirst().find { it.text() == 'North America'}
println page.depthFirst().find { it.text().contains('North America')}
这导致非空输出。
我正在尝试使用 XmlSlurper 解析格式不正确的 HTML 页面,the Eclipse download site The W3C validator 在页面中显示了几个错误。
我尝试了 this post
的容错解析器@Grab(group='net.sourceforge.nekohtml', module='nekohtml', version='1.9.14')
import org.cyberneko.html.parsers.SAXParser
import groovy.util.XmlSlurper
// Getting the xhtml page thanks to Neko SAX parser
def mirrors = new XmlSlurper(new SAXParser()).parse("http://www.eclipse.org/downloads/download.php?file=/technology/epp/downloads/release/luna/SR1a/eclipse-jee-luna-SR1a-linux-gtk-x86_64.tar.gz")
mirrors.'**'
不幸的是,似乎并非所有内容都被解析到 XML 对象中。错误的子树被简单地忽略了。
例如page.depthFirst().find { it.text() == 'North America'}
returns null
而不是页面中的 H4 元素。
是否有一些可靠的方法来解析 groovy 中的任何 HTML 内容?
使用以下代码可以很好地解析(没有错误):
@Grab(group='net.sourceforge.nekohtml', module='nekohtml', version='1.9.14')
import org.cyberneko.html.parsers.SAXParser
import groovy.util.XmlSlurper
def parser = new SAXParser()
def page = new XmlSlurper(parser).parse('http://www.eclipse.org/downloads/download.php?file=/technology/epp/downloads/release/luna/SR1a/eclipse-jee-luna-SR1a-linux-gtk-x86_64.tar.gz')
但是我不知道你到底想找到哪些元素。
这里 All mirrors
被发现:
page.depthFirst().find {
it.text() == 'All mirrors'
}.@href
编辑
两个输出都是null
.
println page.depthFirst().find { it.text() == 'North America'}
println page.depthFirst().find { it.text().contains('North America')}
编辑 2
您可以在下面找到一个下载文件并正确解析文件的工作示例。我使用 wget
下载文件(使用 groovy 下载文件有问题 - 不知道是什么)
@Grab(group='net.sourceforge.nekohtml', module='nekohtml', version='1.9.14')
import org.cyberneko.html.parsers.SAXParser
import groovy.util.XmlSlurper
def host = 'http://www.eclipse.org/downloads/download.php?file=/technology/epp/downloads/release/luna/SR1a/eclipse-jee-luna-SR1a-linux-gtk-x86_64.tar.gz'
def temp = File.createTempFile('eclipse', 'tmp')
temp.deleteOnExit()
def cmd = ['wget', host, '-O', temp.absolutePath].execute()
cmd.waitFor()
cmd.exitValue()
def parser = new SAXParser()
def page = new XmlSlurper(parser).parseText(temp.text)
println page.depthFirst().find { it.text() == 'North America'}
println page.depthFirst().find { it.text().contains('North America')}
编辑 3
终于问题解决了。当没有指定 User-Agent
header 时,使用 groovy 的 url.toURL().text
会导致问题。现在它可以正常工作并找到元素 - 没有使用外部工具。
@Grab(group='net.sourceforge.nekohtml', module='nekohtml', version='1.9.14')
import org.cyberneko.html.parsers.SAXParser
import groovy.util.XmlSlurper
def host = 'http://www.eclipse.org/downloads/download.php?file=/technology/epp/downloads/release/luna/SR1a/eclipse-jee-luna-SR1a-linux-gtk-x86_64.tar.gz'
def parser = new SAXParser()
def page = new XmlSlurper(parser).parseText(host.toURL().getText(requestProperties: ['User-Agent': 'Non empty']))
assert page.depthFirst().find { it.text() == 'North America'}
assert page.depthFirst().find { it.text().contains('North America')}
我喜欢 tagsoup SAX 解析器,它说它是为解析 "poor, nasty and brutish" HTML 而设计的。
它可以很容易地与XmlSlurper
结合使用:
@Grab(group='org.ccil.cowan.tagsoup', module='tagsoup', version='1.2')
def parser = new XmlSlurper(new org.ccil.cowan.tagsoup.Parser())
def page = parser.parse('http://www.eclipse.org/downloads/download.php?file=/technology/epp/downloads/release/luna/SR1a/eclipse-jee-luna-SR1a-linux-gtk-x86_64.tar.gz')
println page.depthFirst().find { it.text() == 'North America'}
println page.depthFirst().find { it.text().contains('North America')}
这导致非空输出。