我的要求是下载和抓取各种HTML页面,从页面上的代码中提取对象列表,具体取决于我们在该页面上查找的对象类型。例如,一个页面可能包含嵌入的医生手术列表,另一个页面可能包含主要信任列表等。我必须逐个查看页面,最后得到适当对象类型的列表。
我选择这样做的方法是拥有一个名为HTMLParser<T> where T : IEntity, new()
IEntity
是可以删除的所有对象类型都将实现的接口,尽管我还没有弄清楚接口成员将是什么。
所以你可以有效地说出
HTMLParser<Surgery> parser = new HTMLParser<Surgery>(URL, XSD SCHEMA DOC);
IList<Surgery> results = parser.Parse();
Parse()
将验证从URL下载的HTML字符串是否包含符合所提供的XSD文档的块,然后以某种方式使用此模板提取List<Surgery>
个Surgery对象,每个对应一个到HTML字符串中的XML块。
我遇到的问题是
我不确定如何以一种很好的方式为每种对象类型指定模板,而HTMLParser<Surgery> parser = new HTMLParser<Surgery>(new URI("...."), Surgery.Template);
除了有点笨重之外。任何人都可以建议使用.NET 3.0 / 4.0的更好方法吗?
我不确定如何以通用的方式获取HTML字符串,获取XSD或XML模板文档,并返回Generic Type的构造对象的通用列表。任何人都可以建议如何做到这一点?
最后,我不相信仿制药是解决这个问题的正确方法,因为它开始变得非常复杂。你是否同意或谴责我在这里选择的解决方案,如果没有,你会做什么呢?
答案 0 :(得分:2)
我也不相信仿制药也是正确的解决方案。我使用良好的旧继承实现了与此非常类似的东西,我仍然认为这是适合这项工作的工具。
当您想要对不同类型执行相同的操作时,泛型非常有用。例如,集合是泛型非常方便的一个很好的例子。
另一方面,当您希望对象继承常用功能,然后扩展和/或修改该功能时,继承非常有用。使用泛型来做这件事很麻烦。
我的刮刀基类看起来像这样:
public class ScraperBase
{
// Common methods for making web requests, etc.
// When you want to download and scrape a page, you call this:
public List<string> DownloadAndScrape(string url)
{
// make request and download page.
// Then call Scrape ...
return Scrape(pageText);
}
// And an abstract Scrape method that returns a List<string>
// Inheritors implement this method.
public abstract List<string> Scrape(string pageText);
}
还有其他一些用于记录,错误报告等的东西,但这就是它的要点。
现在,假设我有一个Wordpress博客刮刀:
public class WordpressBlogScraper : ScraperBase
{
// just implement the Scrape method
public override List<string> Scrape(string pageText)
{
// do Wordpress-specific parsing and return data.
}
}
我可以做同样的事情来为任何页面,网站或数据类编写Blogspot刮刀或自定义刮刀。
我实际上尝试做类似的事情,但是我使用了刮刀回调函数,而不是使用继承。类似的东西:
public delegate List<string> PageScraperDelegate(string pageText);
public class PageScraper
{
public List<string> DownloadAndScrape(string url, PageScraperDelegate callback)
{
// download data to pageText;
return callback(pageText);
}
}
然后你可以写:
var myScraper = new PageScraper();
myScraper.DownloadAndScrape("http://example.com/index.html", ScrapeExample);
private List<string> ScrapeExample(string pageText)
{
// do the scraping here and return a List<string>
}
效果相当好,无需为每种刮刀类型创建新类。但是,我发现在我的情况下它太有限了。我最终需要为几乎所有类型的刮刀提供不同的类,所以我只是继续使用继承。
答案 1 :(得分:1)
我宁愿专注于你的解析器/验证器类,因为正确地设计它们对于将来使用的简易性是非常重要的。我认为这个机制将根据输入确定哪个解析器/验证器更为重要如何。
此外,如果您被告知需要解析另一种类型的网站,例如Invoice
个实体,会发生什么情况?您是否可以通过2个简单的步骤扩展您的机制以处理此类要求?