具有 xpath 支持的抓取框架
Scraping framework with xpath support
我正在寻找一个网络抓取框架,让我
- 命中给定端点并加载 html 响应
- 通过一些 css 选择器搜索元素
- 恢复该元素的 xpath
有什么建议吗?我见过很多让我通过 xpath 搜索的,但是 none 实际上为元素生成 xpath。
似乎没有多少人通过 CSS 选择器搜索但希望结果作为 XPath,但有一些选择可以实现。
首先,我用 JQuery 加上一个附加功能完成了这项工作。这是因为 JQuery 有很好的选择并且很容易找到支持。您可以 use JQuery in Node.js,因此您应该能够在该域(在服务器上)而不是在客户端(如我的简单示例所示)中实现我的代码。如果这不是一个选项,您可以在下面使用 Python 或在底部查找 C# 入门程序来查找我的其他潜在解决方案。
对于 JQuery 方法,纯 JavaScript 函数返回 XPath 非常简单。在下面的示例 (also on JSFiddle) 中,我使用 JQuery 选择器检索了示例锚元素,得到了剥离的 DOM 元素,并将其发送到我的 getXPath
函数:
<html>
<head>
<title>The jQuery Example</title>
<script type="text/javascript"
src="http://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script type="text/javascript">
function getXPath( element )
{
var xpath = '';
for ( ; element && element.nodeType == 1; element = element.parentNode )
{
var id = $(element.parentNode).children(element.tagName).index(element) + 1;
id > 1 ? (id = '[' + id + ']') : (id = '');
xpath = '/' + element.tagName.toLowerCase() + id + xpath;
}
return xpath;
}
$(document).ready(function() {
$("#example").click(function() {
alert("Link Xpath: " + getXPath($("#example")[0]));
});
});
</script>
</head>
<body>
<p id="p1">This is an example paragraph.</p>
<p id="p2">This is an example paragraph with a <a id="example" href="#">link inside.</a></p>
</body>
</html>
如果您需要比我提供的更复杂的功能,可以使用名为 css2xpath 的更强大的 CSS 选择器到 XPath 转换的完整库。
Python (lxml):
对于 Python,您需要使用 lxml 的 CSS 选择器 class (see link for full tutorial and docs) 来获取 xml 节点。
The CSSSelector class
The most important class in the lxml.cssselect module is CSSSelector.
It provides the same interface as the XPath class, but accepts a CSS
selector expression as input:
>>> from lxml.cssselect import CSSSelector
>>> sel = CSSSelector('div.content')
>>> sel #doctest: +ELLIPSIS <CSSSelector ... for 'div.content'>
>>> sel.css
'div.content'
The selector actually compiles to XPath, and you can see the
expression by inspecting the object:
>>> sel.path
"descendant-or-self::div[@class and contains(concat(' ', normalize-space(@class), ' '), ' content ')]"
To use the selector, simply call it with a document or element object:
>>> from lxml.etree import fromstring
>>> h = fromstring('''<div id="outer">
... <div id="inner" class="content body">
... text
... </div></div>''')
>>> [e.get('id') for e in sel(h)]
['inner']
Using CSSSelector is equivalent to translating with cssselect and
using the XPath class:
>>> from cssselect import GenericTranslator
>>> from lxml.etree import XPath
>>> sel = XPath(GenericTranslator().css_to_xpath('div.content'))
CSSSelector takes a translator parameter to let you choose which
translator to use. It can be 'xml' (the default), 'xhtml', 'html' or a
Translator object.
如果您希望从 url 加载,您可以在构建 etree 时直接执行此操作:root = etree.fromstring(xml, base_url="http://where.it/is/from.xml")
C#
有一个名为 css2xpath-reloaded 的库,它只做 CSS 到 XPath 的转换。
String css = "div#test .note span:first-child";
String xpath = css2xpath.Transform(css);
// 'xpath' will contain:
// //div[@id='test']//*[contains(concat(' ',normalize-space(@class),' '),' note ')]*[1]/self::span
当然,使用 C# 实用程序 classes 从 url 获取字符串非常容易,几乎不需要讨论:
using(WebClient client = new WebClient()) {
string s = client.DownloadString(url);
}
至于CSS选择器的选择,可以试试Fizzler,很强大。这是首页示例,但您可以做更多的事情:
// Load the document using HTMLAgilityPack as normal
var html = new HtmlDocument();
html.LoadHtml(@"
<html>
<head></head>
<body>
<div>
<p class='content'>Fizzler</p>
<p>CSS Selector Engine</p></div>
</body>
</html>");
// Fizzler for HtmlAgilityPack is implemented as the
// QuerySelectorAll extension method on HtmlNode
var document = html.DocumentNode;
// yields: [<p class="content">Fizzler</p>]
document.QuerySelectorAll(".content");
// yields: [<p class="content">Fizzler</p>,<p>CSS Selector Engine</p>]
document.QuerySelectorAll("p");
// yields empty sequence
document.QuerySelectorAll("body>p");
// yields [<p class="content">Fizzler</p>,<p>CSS Selector Engine</p>]
document.QuerySelectorAll("body p");
// yields [<p class="content">Fizzler</p>]
document.QuerySelectorAll("p:first-child");
我正在寻找一个网络抓取框架,让我
- 命中给定端点并加载 html 响应
- 通过一些 css 选择器搜索元素
- 恢复该元素的 xpath
有什么建议吗?我见过很多让我通过 xpath 搜索的,但是 none 实际上为元素生成 xpath。
似乎没有多少人通过 CSS 选择器搜索但希望结果作为 XPath,但有一些选择可以实现。
首先,我用 JQuery 加上一个附加功能完成了这项工作。这是因为 JQuery 有很好的选择并且很容易找到支持。您可以 use JQuery in Node.js,因此您应该能够在该域(在服务器上)而不是在客户端(如我的简单示例所示)中实现我的代码。如果这不是一个选项,您可以在下面使用 Python 或在底部查找 C# 入门程序来查找我的其他潜在解决方案。
对于 JQuery 方法,纯 JavaScript 函数返回 XPath 非常简单。在下面的示例 (also on JSFiddle) 中,我使用 JQuery 选择器检索了示例锚元素,得到了剥离的 DOM 元素,并将其发送到我的 getXPath
函数:
<html>
<head>
<title>The jQuery Example</title>
<script type="text/javascript"
src="http://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script type="text/javascript">
function getXPath( element )
{
var xpath = '';
for ( ; element && element.nodeType == 1; element = element.parentNode )
{
var id = $(element.parentNode).children(element.tagName).index(element) + 1;
id > 1 ? (id = '[' + id + ']') : (id = '');
xpath = '/' + element.tagName.toLowerCase() + id + xpath;
}
return xpath;
}
$(document).ready(function() {
$("#example").click(function() {
alert("Link Xpath: " + getXPath($("#example")[0]));
});
});
</script>
</head>
<body>
<p id="p1">This is an example paragraph.</p>
<p id="p2">This is an example paragraph with a <a id="example" href="#">link inside.</a></p>
</body>
</html>
如果您需要比我提供的更复杂的功能,可以使用名为 css2xpath 的更强大的 CSS 选择器到 XPath 转换的完整库。
Python (lxml): 对于 Python,您需要使用 lxml 的 CSS 选择器 class (see link for full tutorial and docs) 来获取 xml 节点。
The CSSSelector class
The most important class in the lxml.cssselect module is CSSSelector. It provides the same interface as the XPath class, but accepts a CSS selector expression as input:
>>> from lxml.cssselect import CSSSelector
>>> sel = CSSSelector('div.content')
>>> sel #doctest: +ELLIPSIS <CSSSelector ... for 'div.content'>
>>> sel.css
'div.content'
The selector actually compiles to XPath, and you can see the expression by inspecting the object:
>>> sel.path
"descendant-or-self::div[@class and contains(concat(' ', normalize-space(@class), ' '), ' content ')]"
To use the selector, simply call it with a document or element object:
>>> from lxml.etree import fromstring
>>> h = fromstring('''<div id="outer">
... <div id="inner" class="content body">
... text
... </div></div>''')
>>> [e.get('id') for e in sel(h)]
['inner']
Using CSSSelector is equivalent to translating with cssselect and using the XPath class:
>>> from cssselect import GenericTranslator
>>> from lxml.etree import XPath
>>> sel = XPath(GenericTranslator().css_to_xpath('div.content'))
CSSSelector takes a translator parameter to let you choose which translator to use. It can be 'xml' (the default), 'xhtml', 'html' or a Translator object.
如果您希望从 url 加载,您可以在构建 etree 时直接执行此操作:root = etree.fromstring(xml, base_url="http://where.it/is/from.xml")
C# 有一个名为 css2xpath-reloaded 的库,它只做 CSS 到 XPath 的转换。
String css = "div#test .note span:first-child";
String xpath = css2xpath.Transform(css);
// 'xpath' will contain:
// //div[@id='test']//*[contains(concat(' ',normalize-space(@class),' '),' note ')]*[1]/self::span
当然,使用 C# 实用程序 classes 从 url 获取字符串非常容易,几乎不需要讨论:
using(WebClient client = new WebClient()) {
string s = client.DownloadString(url);
}
至于CSS选择器的选择,可以试试Fizzler,很强大。这是首页示例,但您可以做更多的事情:
// Load the document using HTMLAgilityPack as normal
var html = new HtmlDocument();
html.LoadHtml(@"
<html>
<head></head>
<body>
<div>
<p class='content'>Fizzler</p>
<p>CSS Selector Engine</p></div>
</body>
</html>");
// Fizzler for HtmlAgilityPack is implemented as the
// QuerySelectorAll extension method on HtmlNode
var document = html.DocumentNode;
// yields: [<p class="content">Fizzler</p>]
document.QuerySelectorAll(".content");
// yields: [<p class="content">Fizzler</p>,<p>CSS Selector Engine</p>]
document.QuerySelectorAll("p");
// yields empty sequence
document.QuerySelectorAll("body>p");
// yields [<p class="content">Fizzler</p>,<p>CSS Selector Engine</p>]
document.QuerySelectorAll("body p");
// yields [<p class="content">Fizzler</p>]
document.QuerySelectorAll("p:first-child");