在 C# 中实现动态 Web Scraper 的逻辑
-
22-09-2019 - |
题
我希望在 C# 窗口窗体中开发一个 Web scraper。我想要完成的任务如下:
- 从用户处获取 URL。
- 在WINForms中的IE UI控件(嵌入式浏览器)中加载网页。
- 允许用户选择文本(连续、小(不超过 50 个字符))。从加载的网页。
- 当用户希望保留位置时(HTML DOM 位置)它必须被持久化到数据库中,以便用户在后续访问期间可以使用该位置来获取该位置中的数据。
假设加载的网站是一个价目表网站,并且报价不断变化,我们的想法是保留 DOM 层次结构,以便我下次可以遍历它。
如果所有 HTML 元素都有其 id 属性,我就能够做到这一点。在 id 为 null 的情况下,我无法完成此操作。
有人可以就此提出一个有效的想法(如果可能的话,提供最低限度的代码片段)。?
即使您可以分享一些在线资源,这也会很有帮助。
谢谢,
维杰
解决方案
一种方法是构建一堆标签/样式/id 直至您要选择的元素。
从你想要的元素开始,向上遍历到最近的id元素。这样你就可以摆脱大部分顶部标题等。然后建立一个序列来寻找。
例子:
<html>
<body>
<!-- lots of html -->
<div id="main">
<div>
<span>
<div class="pricearea">
<table> <!-- with price data -->
对于 example,您将在数据库中存储以下序列: [id=main],div,span,div,表格 也许 div[类=价格区域],表.
使用样式/类也可以用于创建您的路径。您可以选择查找标签、标签的属性或组合。您希望它尽可能准确,元素尽可能少,以使其稳健。
如果布局很少更改,这将使您每次导航到同一位置。
我还建议你也许使用 HTML 敏捷包 或者类似的 DOM 解析,因为 IE 控制很慢。
屏幕抓取很有趣,但很难 100% 覆盖所有页面。祝你好运!
其他提示
经过一番谷歌搜索后,我遇到了一个相当简单的解决方案。下面附上示例片段。
if (webBrowser.Document != null)
{
IHTMLDocument2 HtmlDoc = (IHTMLDocument2)webBrowser.Document.DomDocument;// loads the HTML DOM
IHTMLSelectionObject selection = HtmlDoc.selection;// Fetches the currently selected HTML Element.
IHTMLTxtRange range = (IHTMLTxtRange)selection.createRange();
IHTMLElement parentElement = range.parentElement();// Identifies the parent element
targetSourceIndex = parentElement.sourceIndex;
//dataLocation = range.parentElement().id;
MessageBox.Show(range.text);//range.parentElement().sourceIndex
}
我用了一个 嵌入式网络浏览器 在 Winforms 应用程序中,它加载当前网页的 HTML DOM。
这 IHTML元素 实例公开一个名为“SourceIndex”的属性,该属性为每个 html 元素分配一个唯一的 id。
人们可以将此 SourceIndex 存储到数据库并查询该位置的内容。使用以下代码。
if (webBrowser.Document != null)
{
IHTMLDocument2 HtmlDoc = (IHTMLDocument2)webBrowser.Document.DomDocument;
IHTMLElement targetElement = null;
foreach (IHTMLElement domElement in HtmlDoc.all)
{
if (domElement.sourceIndex == int.Parse(node.InnerText))// fetching the persisted data from the XML file.
{
targetElement = domElement;
break;
}
}
MessageBox.Show(targetElement.innerText); //range.parentElement().sourceIndex
}
不隶属于 StackOverflow