Flink_ 页面广告点击量统计(黑名单过滤)

这篇博客介绍了电商网站广告点击量的统计分析,通过页面广告点击量作为市场营销的重要指标,结合用户地理位置进行广告精准投放。同时,文章提出了针对同一用户短时间内频繁点击同一广告的异常行为进行黑名单过滤,通过设定阈值限制用户的点击次数,超过阈值则触发黑名单报警。整个过程利用Flink进行数据处理,包括数据读取、过滤、时间窗口聚合等操作,实现了广告点击量的实时统计和异常检测。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

页面广告分析_ 页面广告点击量统计
        电商网站的市场营销商业指标中,除了自身的 APP 推广,还会考虑到页面上的
广告投放(包括自己经营的产品和其它网站的广告)。所以广告相关的统计分析,
也是市场营销的重要指标。
        对于广告的统计,最简单也最重要的就是页面广告的点击量,网站往往需要根
据广告点击量来制定定价策略和调整推广方式,而且也可以借此收集用户的偏好信
。更加具体的应用是,我们可以根据用户的地理位置进行划分,从而总结出不同
省份用户对不同广告的偏好,这样更有助于广告的精准投放。 
province 进行 keyBy,然后开一小时的时间窗口, 滑动距离为 5 秒,统计窗口内的点击事件数量

       

 黑名单过滤

        同一用户的重复点击是会叠加计算的。在实际场 景中,同一用户确实可能反复点开同一个广告,这也说明了用户对广告更大的兴趣; 但是如果用户在一段时间非常频繁地点击广告,这显然不是一个正常行为,有刷点击量的嫌疑。所以我们可以对一段时间内(比如一天内)的用户点击行为进行约束, 如果对同一个广告点击超过一定限额(比如 100 次),应该把该用户加入黑名单并报警,此后其点击行为不应该再统计

输入数据:userId adId 省 城市 时间戳

 561558 3611281  guangdong  shenzhen 1511658120
package UserBehaviorAnalysis.MarketAnalysis

import java.sql.Timestamp

import org.apache.flink.api.common.functions.AggregateFunction
import org.apache.flink.api.common.state.{ValueState, ValueStateDescriptor}
import org.apache.flink.streaming.api.TimeCharacteristic
import org.apache.flink.streaming.api.functions.KeyedProcessFunction
import org.apache.flink.streaming.api.scala._
import org.apache.flink.streaming.api.scala.function.WindowFunction
import org.apache.flink.streaming.api.windowing.time.Time
import org.apache.flink.streaming.api.windowing.windows.TimeWindow
import org.apache.flink.util.Collector


// 定义输入样例类
case class AdClickLog(userId: Long, adId: Long, province: String, city: String, timestamp: Long)
// 定义输出样例类
case class AdClickCountByProvince(windowEnd: String, province: String, count: Long)
// 侧输出流黑名单报警信息样例类
case class BlackListUserWarning(userId: Long, adId: Long, msg: String)

object AdClickAnalysis {
  def main(args: Array[String]): Unit = {
    val env = StreamExecutionEnvironment.getExecutionEnvironment
    env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime)
    env.setParallelism(1)

    val inputStream = env.readTextFile("D:\\Mywork\\workspace\\Project_idea\\flink-2021\\src\\main\\resources\\AdClickLog.csv")
    val adLogStream = inputStream.map { data =>
      val arr = data.split(",")
      AdClickLog(arr(0).toLong, arr(1).toLong, arr(2), arr(3), arr(4).toInt)
    }.assignAscendingTimestamps(_.timestamp * 1000L)

    // 插入一步过滤操作,并将有刷单行为的用户输出到侧输出流(黑名单报警)
    val filterBlackListUserStream = adLogStream
      .keyBy(data => (data.userId, data.adId))
      .process(new FliterBlackListUserResult(100))


    val adCountResultStream = filterBlackListUserStream
      .keyBy(_.province)
      .timeWindow(Time.hours(1), Time.seconds(5))
      .aggregate(new AdCountAgg(), new AdCountWindowResult())

    filterBlackListUserStream.getSideOutput(new OutputTag[BlackListUserWarning]("warning")).print("warning")
    adCountResultStream.print("count result")
    env.execute()

  }
}

class AdCountAgg() extends AggregateFunction[AdClickLog, Long, Long]{
  override def createAccumulator(): Long = 0L

  override def add(value: AdClickLog, accumulator: Long): Long = accumulator + 1

  override def getResult(accumulator: Long): Long = accumulator

  override def merge(a: Long, b: Long): Long = a + b
}

class AdCountWindowResult() extends WindowFunction[Long, AdClickCountByProvince, String, TimeWindow]{
  
  override def apply(key: String, window: TimeWindow, input: Iterable[Long], out: Collector[AdClickCountByProvince]): Unit = {
    val end = new Timestamp(window.getEnd).toString
    out.collect(AdClickCountByProvince(end, key, input.head))
  }
}

// 自定义KeyedProcessFunction,黑名单过滤
class FliterBlackListUserResult(maxCount: Long) extends KeyedProcessFunction[(Long, Long), AdClickLog, AdClickLog]{
  // 定义状态,保存用户对广告的点击量,每天0点定时清空状态的时间戳,标记当前用户是否已经进入黑名单
  lazy val countState: ValueState[Long] = getRuntimeContext.getState(new ValueStateDescriptor[Long]("Adcount", classOf[Long]))
  lazy val resetTimerTsState: ValueState[Long] = getRuntimeContext.getState(new ValueStateDescriptor[Long]("reset-ts", classOf[Long]))
  lazy val isBlackState: ValueState[Boolean] = getRuntimeContext.getState(new ValueStateDescriptor[Boolean]("is-back", classOf[Boolean]))



  override def processElement(i: AdClickLog, context: KeyedProcessFunction[(Long, Long), AdClickLog, AdClickLog]#Context, collector: Collector[AdClickLog]): Unit = {
    val curCount = countState.value()
    // 判断只要是第一个数据来了,直接注册0点的清空状态定时器
    if (curCount == 0){
      val ts = (context.timerService().currentProcessingTime()/(1000 * 60 * 60 * 24) + 1) * (24 * 60 * 60 * 1000) - 8 * 60 * 60 * 1000
      resetTimerTsState.update(ts)
      context.timerService().registerProcessingTimeTimer(ts)
    }

    // 判断count值是否已经达到定义的阈值,如果超过就输出到黑名单
    if (curCount >= maxCount){
      // 判断是否已经在黑名单里,没有的话才输出侧输出流
      if (!isBlackState.value()){
        isBlackState.update(true)
        context.output(new OutputTag[BlackListUserWarning]("warning"), BlackListUserWarning(i.userId, i.adId, "Click ad over " + maxCount + " times today."))
      }
      return
    }

    // 正常情况,count加1,然后将数据原样输出
    countState.update(curCount + 1)
    collector.collect(i)
  }

  override def onTimer(timestamp: Long, ctx: KeyedProcessFunction[(Long, Long), AdClickLog, AdClickLog]#OnTimerContext, out: Collector[AdClickLog]): Unit = {
    if (timestamp == resetTimerTsState.value()){
      isBlackState.clear()
      countState.clear()
    }
  }
}


//输出数据
warning> BlackListUserWarning(937166,1715,Click ad over 100 times today.)
count result> AdClickCountByProvince(2017-11-26 09:00:05.0,beijing,1)
count result> AdClickCountByProvince(2017-11-26 09:00:10.0,beijing,1)

### 商品点击量实时统计的实现方法 要通过 Apache Flink 实现商品点击量的实时统计,可以采用窗口操作来处理流数据。以下是具体的实现思路和技术细节: #### 1. 数据输入与预处理 假设原始数据是以日志形式存在的,每条记录表示一次用户的点击行为。可以通过 Kafka 或其他消息队列作为数据源接入 Flink 流处理框架。 ```java // 创建执行环境 StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); // 从Kafka读取数据 FlinkKafkaConsumer<String> kafkaSource = new FlinkKafkaConsumer<>( "click_topic", // Kafka Topic 名称 new SimpleStringSchema(), // 序列化方式 properties // Kafka连接配置 ); DataStream<String> clickStream = env.addSource(kafkaSource); ``` 上述代码片段展示了如何设置 Kafka 数据源并将其转换为 Flink 的 `DataStream` 对象[^1]。 --- #### 2. 定义商品点击事件结构 为了便于后续处理,需解析每一条日志并将之转化为统一的数据模型。例如定义一个类用于存储每次点击的相关信息。 ```java public class ClickEvent { public String userId; // 用户ID public String itemId; // 商品ID public Long timestamp; // 时间戳 // 构造函数和其他必要方法省略... } ``` 接着利用 FlatMap 函数完成字符串到对象的映射工作。 ```java DataStream<ClickEvent> eventStream = clickStream .flatMap(new RichFlatMapFunction<String, ClickEvent>() { @Override public void flatMap(String value, Collector<ClickEvent> out) throws Exception { // 解析逻辑简化版 String[] fields = value.split(","); ClickEvent event = new ClickEvent(); event.userId = fields[0]; event.itemId = fields[1]; event.timestamp = Long.parseLong(fields[2]); out.collect(event); } }); ``` 此处实现了将原始文本日志拆解成结构化的 `ClickEvent` 类型实例集合的操作[^3]。 --- #### 3. 使用窗口聚合统计数据 对于商品点击次数这样的指标来说,通常会按照固定的时间间隔或者滑动窗口来进行汇总分析。下面展示了一个基于滚动窗口的例子。 ```java KeyedStream<ClickEvent, Tuple> keyedStream = eventStream .keyBy("itemId"); // 按照商品ID分组 WindowedStream<ClickEvent, Tuple, TimeWindow> windowedStream = keyedStream .timeWindow(Time.minutes(1)); // 设置1分钟长度的窗口 windowedStream.aggregate( new AggregateFunction<ClickEvent, Integer, Integer>() { @Override public Integer createAccumulator() { return 0; } @Override public Integer add(ClickEvent value, Integer accumulator) { return accumulator + 1; } @Override public Integer getResult(Integer accumulator) { return accumulator; } @Override public Integer merge(Integer a, Integer b) { return a + b;} }) .print(); // 打印结果至控制台 ``` 以上部分完成了按商品维度计数的任务,并且设置了时间范围内的累加器机制以支持高效增量更新[^2]。 --- #### 4. 结果输出 最终的结果可以根据业务需求写入数据库、文件系统或者其他外部服务端点供下游消费使用。 ```java outputStream.addSink(new JdbcSink<>(...)); ``` 这一步骤涉及到了目标系统的对接开发,在实际部署过程中需要依据具体情况调整适配层的设计方案。 --- ### 总结 综上所述,借助 Apache Flink 提供的强大功能模块能够轻松构建起一套完整的电商场景下的商品点击热度监控体系。不仅限于此案例中的简单数量累积运算,还可以进一步扩展加入更多复杂的商业规则判断条件等高级特性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值