我将使用java开发一个网络爬虫来从酒店网站获取酒店房间价格 在这种情况下,我想用房间类型和用餐类型来捕捉房间价格,所以我的算法应该是智能的来处理它。
例如:
Room type: Deluxe
Meal type: HalfBoad
price : $20.00
主要问题是房价可能在不同的酒店网站有不同的方式。所以我的算法应该独立于酒店网站。
我计划将上述房型和膳食类型用作模糊集,并使用合适的隶属函数将网页中的单词与上述模糊集进行比较。
有经验的人吗?或者对我的问题有所了解?
答案 0 :(得分:3)
有两种方法可以解决这个问题:
您可以自定义抓取工具,以了解不同网站使用的格式;或
您可以提出一般(“模糊”)解决方案。
(2)有很多问题。首先它将是不可靠的。你会遇到你不理解或(更糟)出错的格式。其次,需要大量的开发才能让工作变得有效。这是您在处理数千或数百万个站点时使用的那种东西。
通过数百个网站,您将获得更好,更可预测的结果(1)。
答案 1 :(得分:0)
与所有问题一样,设计可以让您提供适应您没有比一般解决方案更快考虑的情况的价值。
首先编写一些解析来自一个提供程序的数据 - 一个具有最简单格式的提供程序。找到一种方法使该处理程序适应您的爬虫。一定要封装构造 - 无论如何你应该总是这样做......
public class RoomTypeExtractor
{
private RoomTypeExtractor() { }
public static RoomTypeExtractor GetInstance()
{
return new RoomTypeExtractor();
}
public string GetRoomType(string content)
{
// BEHAVIOR #1
}
}
GetInstance()
,ethod让您可以实现免费的策略模式。
然后添加您的第二个提供者类型。比如说,你有一个稍微复杂的数据格式,比第一种格式更普遍。首先将您具体的房间类型提取器类重构为一个抽象,后面有一个变体,让GetInstance()
方法返回一个具体类型的实例:
public abstract class RoomTypeExtractor
{
public static RoomTypeExtractor GetInstance()
{
return SimpleRoomTypeExtractor.GetInstance();
}
public abstract string GetRoomType(string content);
}
public final class SimpleRoomTypeExtractor extends RoomTypeExtractor
{
private SimpleRoomTypeExtractor() { }
public static SimpleRoomTypeExtractor GetInstance()
{
return new SimpleRoomTypeExtractor();
}
public string GetRoomType(string content)
{
// BEHAVIOR #1
}
}
创建另一个实现Null对象模式的变体......
public class NullRoomTypeExtractor extends RoomTypeExtractor
{
private NullRoomTypeExtractor() { }
public static NullRoomTypeExtractor GetInstance()
{
return new NullRoomTypeExtractor();
}
public string GetRoomType(string content)
{
// whatever "no content" behavior you want... I chose returning null
return null;
}
}
添加一个基类,以便更轻松地使用此问题中的责任链模式:
public abstract class ChainLinkRoomTypeExtractor extends RoomTypeExtractor
{
private final RoomTypeExtractor next_;
protected ChainLinkRoomTypeExtractor(RoomTypeExtractor next)
{
next_ = next;
}
public final string GetRoomType(string content)
{
if (CanHandleContent(content))
{
return GetRoomTypeFromUnderstoodFormat(content);
}
else
{
return next_.GetRoomType(content);
}
}
protected abstract bool CanHandleContent(string content);
protected abstract string GetRoomTypeFromUnderstoodFormat(string content);
}
现在,重构原始实现以获得一个将其连接到责任链的基类......
public final class SimpleRoomTypeExtractor extends ChainLinkRoomTypeExtractor
{
private SimpleRoomTypeExtractor(RoomTypeExtractor next)
{
super(next);
}
public static SimpleRoomTypeExtractor GetInstance(RoomTypeExtractor next)
{
return new SimpleRoomTypeExtractor(next);
}
protected string CanHandleContent(string content)
{
// return whether or not content contains the right format
}
protected string GetRoomTypeFromUnderstoodFormat(string content)
{
// BEHAVIOR #1
}
}
请务必更新RoomTypeExtractor.GetInstance()
:
public static RoomTypeExtractor GetInstance()
{
RoomTypeExtractor extractor = NullRoomTypeExtractor.GetInstance();
extractor = SimpleRoomTypeExtractor.GetInstance(extractor);
return extractor;
}
完成后,为责任链创建一个新链接......
public final class MoreComplexRoomTypeExtractor extends ChainLinkRoomTypeExtractor
{
private MoreComplexRoomTypeExtractor(RoomTypeExtractor next)
{
super(next);
}
public static MoreComplexRoomTypeExtractor GetInstance(RoomTypeExtractor next)
{
return new MoreComplexRoomTypeExtractor(next);
}
protected string CanHandleContent(string content)
{
// Check for presence of format #2
}
protected string GetRoomTypeFromUnderstoodFormat(string content)
{
// BEHAVIOR #2
}
}
最后,将新链接添加到链中,如果这是一种更常见的格式,您可能希望通过将其放在链中更高的位置来赋予它更高的优先级(控制链的顺序的真正力量将变得明显当你这样做时):
public static RoomTypeExtractor GetInstance()
{
RoomTypeExtractor extractor = NullRoomTypeExtractor.GetInstance();
extractor = SimpleRoomTypeExtractor.GetInstance(extractor);
extractor = MoreComplexRoomTypeExtractor.GetInstance(extractor);
return extractor;
}
随着时间的推移,您可能希望添加动态添加新链接到责任链的方法,正如Cletus所指出的那样,但这里的基本原则是 Emergent Design 。从高品质开始。保持高品质。通过测试驾驶。做这三件事,你就可以在你的耳朵之间使用模糊逻辑引擎来克服几乎任何问题......
修改强>
翻译为Java。希望我做得对;我有点生气。