нечеткая реализация для захвата определенных строк - PullRequest
1 голос
/ 24 марта 2010

Я собираюсь разработать веб-сканер, использующий java, для сбора цен на номера в отелях с веб-сайтов отелей.
В этом случае я хочу определить цену номера по типу номера и типу питания, поэтому мой алгоритм должен быть разумным, чтобысправиться с этим.

Например:

Room type: Deluxe
Meal type: HalfBoad
price : $20.00

Основная проблема в том, что цены на номера могут быть по-разному в разных отелях.Так что мой алгоритм должен быть независимым от сайтов отелей.

Я планирую использовать вышеуказанные типы номеров и типы питания в качестве нечетких наборов и сравнивать слова на веб-странице с вышеуказанными нечеткими наборами, используя подходящую функцию членства.

Кто-нибудь сталкивался с этим?или есть идеи по моей проблеме?

Ответы [ 2 ]

3 голосов
/ 24 марта 2010

Существует два способа решения этой проблемы:

  1. Вы можете настроить сканер, чтобы понимать форматы, используемые различными веб-сайтами; или

  2. Вы можете придумать общее («нечеткое») решение.

(1), безусловно, будет самым простым. В идеале вы хотите создать некоторые инструменты, которые упростят эту задачу, и вы сможете создать фильтр для любого нового сайта за минимальное время. ИМХО, ваше время будет лучше всего проводить с таким подходом.

(2) имеет много проблем. Во-первых, это будет ненадежно. Вы столкнетесь с форматами, которые вы не понимаете или (что еще хуже) ошибаетесь. Во-вторых, для того, чтобы что-то заработало, потребуется значительное развитие. Это то, что вы используете, когда имеете дело с тысячами или миллионами сайтов.

С сотнями сайтов вы получите лучшие и более предсказуемые результаты с (1).

0 голосов
/ 24 марта 2010

Как и в случае со всеми проблемами, дизайн может помочь вам адаптироваться к ситуациям, которые вы не рассматривали намного быстрее, чем общее решение.

Начните с написания чего-то, что анализирует данные одного провайдера - того, который имеет самый простой формат для обработки Найдите способ адаптировать этот обработчик к вашему сканеру. Обязательно инкапсулируйте конструкцию - вы всегда должны это делать ...

public class RoomTypeExtractor
{
  private RoomTypeExtractor() { }

  public static RoomTypeExtractor GetInstance()
  {
    return new RoomTypeExtractor();
  }

  public string GetRoomType(string content)
  {
    // BEHAVIOR #1
  }
}

Метод GetInstance() позволяет вам перейти к шаблону Стратегии практически бесплатно.

Затем добавьте ваш второй тип провайдера. Скажем, например, что у вас есть немного более сложный формат данных, который немного более распространен, чем первый формат. Начните с рефакторинга того, что было вашим конкретным классом экстрактора типа комнаты, в абстракцию с единственным вариантом позади него, и пусть метод 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 Object ...

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 . Начните с высокого качества. Держите качество высоким. Гоняй с тестами. Сделайте эти три вещи, и вы сможете использовать механизм нечеткой логики между вашими ушами, чтобы преодолеть практически любую проблему ...

EDIT

Переведено на Java. Надеюсь, я сделал это правильно; Я немного ржавый.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...