carmolim / olx-monitor

Script que monitora novos anúncios feitos no OLX, alteração de preços em anúncios existentes e envia notificações para seu Telegram.
MIT License
76 stars 29 forks source link

feat: better ad filtering #27

Open Luisotee opened 2 months ago

Luisotee commented 2 months ago

Fiz algumas modificações para ajudar a filtrar os spams e de outras coisas, as modificações são:

config.js :

config.minPrice = undefined; // Minimum price to filter ads, if undefined it will not filter
config.maxPrice = undefined; // Maximum price to filter ads, if undefined it will not filter
config.titleExcludes = ["", ""]; // Exclude ads with these words in the title, word are case insensitive
config.titleContains = []; // Only show ads with these words in the title (if empty it will not filter) Example: ["iphone", "samsung"], words are case insensitive

Ad.js :

isValidAd = () => {
    // Destructure properties from this, providing default values where necessary
    const { title = "", price, url, id } = this;

    const titleLower = title.toLowerCase();
    const titleContainsLower = config.titleContains.map((keyword) =>
      keyword.toLowerCase()
    );
    const titleExcludesLower = config.titleExcludes.map((keyword) =>
      keyword.toLowerCase()
    );

    // Check if the price is within the specified range
    const isPriceWithinRange =
      (config.minPrice === undefined || price > config.minPrice) &&
      (config.maxPrice === undefined || price < config.maxPrice);

    // Check if the title contains required keywords
    const titleContainsRequired =
      titleContainsLower.length === 0 ||
      titleContainsLower.some((keyword) => titleLower.includes(keyword));

    // Check if the title excludes specified keywords
    const titleExcludesRequired = !titleExcludesLower.some((keyword) =>
      titleLower.includes(keyword)
    );

    // Determine if the ad is valid based on all conditions
    const isValid =
      !isNaN(price) &&
      url &&
      id &&
      isPriceWithinRange &&
      titleExcludesRequired &&
      titleContainsRequired;

    this.valid = isValid;

    if (isValid) {
      console.log("Ad is valid");
    } else {
      // Log reasons for invalid ad
      console.log(
        "Ad is not valid due to:\n" +
          [
            { condition: isNaN(price), message: "Price is not a number" },
            { condition: !url, message: "URL is not defined" },
            { condition: !id, message: "ID is not defined" },
            {
              condition: !isPriceWithinRange,
              message: "Price is not within range",
            },
            {
              condition: !titleExcludesRequired,
              message: "Title includes excluded words",
            },
            {
              condition: !titleContainsRequired,
              message: "Title does not contain required words",
            },
          ]
            .filter(({ condition }) => condition)
            .map(({ message }) => `- ${message}`)
            .join("\n")
      );
    }

    return isValid;
  };

Essas configurações me ajudam a evitar a maioria dos spams já que a maioria dos spams da minha região deixam sem valor do anuncio ou incluem o nome da loja no titulo.

Os filtros também ajudam a filtrar melhor o que você está procurando, caso você esteja procurando um Iphone 15 por exemplo, não faz sentido receber notificação de um anúncio de menos de R$1000

carmolim commented 2 months ago

Obrigado pela PR @Luisotee! Tem alguns pontos que gostaria trazer para a discussão:

O que você acha?

Luisotee commented 2 months ago

O filtro de valor máximo e valor mínimo de uma busca pode ser feito no próprio olx, esses parâmetros ficam na URL a ser monitorada, ao meu ver não teria necessidade de fazer esse filtro no código.

Eles tinham tirado o filtro de preço do site, achei eles tinham desativado o filtro pela URL ou algo assim, mas como ainda tem é melhor filtrar pela URL mesmo.

O filtro por título pode ser interessante para filtrar possíveis spams, porém como é possível monitorar várias URLs, cada uma com produtos diferentes minha sugestão seria permitir especificar esse filtro por URL ao invés de aplicar para todos os resultados encontrados para não perder a versatilidade.

Sim, é o melhor mesmo. Eu tinha feito umas modificações pra mim e como eu só uso pra uma URL acabei nem pensando nesse caso.

Se der tempo mais tarde eu modifico pra adequar a multiplas URLs e tirar a parte do preço.