故事背景:

京东作为中国最大的自营式电商,在保持高速发展的同时,沉淀了数亿的忠实用户,积累了海量的真实数据。如何从历史数据中找出规律,去预测用户未来的购买需求,让最合适的商品遇见最需要的人,是大数据应用在精准营销中的关键问题,也是所有电商平台在做智能化升级时所需要的核心技术。
以京东商城真实的用户、商品和行为数据(脱敏后)为基础,通过数据挖掘的技术和机器学习的算法,构建用户购买商品的预测模型,输出高潜用户和目标商品的匹配结果,为精准营销提供高质量的目标群体。
目标:使用京东多个品类下商品的历史销售数据,构建算法模型,预测用户在未来5天内,对某个目标品类下商品的购买意向。

数据集:

这里涉及到的数据集是京东最新的数据集:

  • JData_User.csv 用户数据集 105,321个用户
  • JData_Comment.csv 商品评论 558,552条记录
  • JData_Product.csv 预测商品集合 24,187条记录
  • JData_Action_201602.csv 2月份行为交互记录 11,485,424条记录
  • JData_Action_201603.csv 3月份行为交互记录 25,916,378条记录
  • JData_Action_201604.csv 4月份行为交互记录 13,199,934条记录

1.用户数据

2.商品数据

cate取值:4,5,6,7,8,9,10,11。

3.评论数据

4.行为数据

数据挖掘流程:

(一).数据清洗
1. 数据集完整性验证
2. 数据集中是否存在缺失值
3. 数据集中各特征数值应该如何处理
4. 哪些数据是我们想要的,哪些是可以过滤掉的
5. 将有价值数据信息做成新的数据源
6. 去除无行为交互的商品和用户
7. 去掉浏览量很大而购买量很少的用户(惰性用户或爬虫用户)
(二).数据理解与分析
1. 掌握各个特征的含义
2. 观察数据有哪些特点,是否可利用来建模
3. 可视化展示便于分析
4. 用户的购买意向是否随着时间等因素变化
(三).特征提取
1. 基于清洗后的数据集哪些特征是有价值
2. 分别对用户与商品以及其之间构成的行为进行特征提取
3. 行为因素中哪些是核心?如何提取?
4. 瞬时行为特征or累计行为特征?

(四).模型建立
1. 使用机器学习算法进行预测
2. 参数设置与调节
3. 数据集切分

数据集验证

导包以及数据源定义

# 导入相关包
import pandas as pd
import numpy as np
from collections import Counter# 定义文件名
ACTION_201602_FILE = "data/JData_Action_201602.csv"  # 11M条
ACTION_201603_FILE = "data/JData_Action_201603.csv"   #26M 条
ACTION_201604_FILE = "data/JData_Action_201604.csv"   #13M条
COMMENT_FILE = "data/JData_Comment.csv"      #560K条
PRODUCT_FILE = "data/JData_Product.csv"      #24k
USER_FILE = "data/JData_User.csv"          # 105K 条USER_TABLE_FILE = "data/user_table.csv"
ITEM_TABLE_FILE = "data/item_table.csv"

首先检查JData_User中的用户和JData_Action中的用户是否一致

因为数据量很大所以每次读取的时间有点长,所以很着急看结果的话,可以选择分块进行读取。
保证行为数据中的所产生的行为均由用户数据中的用户产生(但是可能存在用户在行为数据中无行为)

思路:利用pd.Merge连接sku 和 Action中的sku, 观察Action中的数据是否减少

#数据集验证
def user_action_check():df_user = pd.read_csv('data/JData_User.csv',encoding='gbk')df_sku = df_user.loc[:,'user_id'].to_frame()df_month2 = pd.read_csv('data/JData_Action_201602.csv',encoding='gbk')# pd.merge(df_sku,df_month2) 会以user_id字段为基准取两个df的交集 不是取并集,这样才能证明 action中的userid 都在df_user里面print ('Is action of Feb. from User file? ', len(df_month2) == len(pd.merge(df_sku,df_month2))) df_month3 = pd.read_csv('data/JData_Action_201603.csv',encoding='gbk')print ('Is action of Mar. from User file? ', len(df_month3) == len(pd.merge(df_sku,df_month3)))df_month4 = pd.read_csv('data/JData_Action_201604.csv',encoding='gbk')print ('Is action of Apr. from User file? ', len(df_month4) == len(pd.merge(df_sku,df_month4)))user_action_check()  

output:

Is action of Feb. from User file?  True
Is action of Mar. from User file?  True
Is action of Apr. from User file?  True

检查是否有重复记录

除去各个数据文件中完全重复的记录,可能解释是重复数据是有意义的,比如用户同时购买多件商品,同时添加多个数量的商品到购物车等…

#重复数据
def deduplicate(filepath, filename, newpath):df_file = pd.read_csv(filepath,encoding='gbk')       before = df_file.shape[0]# https://blog.csdn.net/u010665216/article/details/78559091/  默认是keep='first' 保留第一个重复项,其他的删除 df_file.drop_duplicates(inplace=True) # 所有列相同才认为是重复 inplace=True表示直接在原来的DataFrame上删除重复项,而默认值False表示生成一个副本。after = df_file.shape[0]n_dup = before-afterprint ('Number of duplicate records for ' + filename + ' is: ' + str(n_dup))if n_dup != 0:df_file.to_csv(newpath, index=None)else:print ('Number duplicate records in ' + filename)deduplicate('data/JData_Action_201602.csv', 'Feb. action', 'data/JData_Action_201602_dedup.csv')
deduplicate('data/JData_Action_201603.csv', 'Mar. action', 'data/JData_Action_201603_dedup.csv')
deduplicate('data/JData_Action_201604.csv', 'Feb. action', 'data/JData_Action_201604_dedup.csv')
deduplicate('data/JData_Comment.csv', 'Comment', 'data/JData_Comment_dedup.csv')
deduplicate('data/JData_Product.csv', 'Product', 'data/JData_Product_dedup.csv')
deduplicate('data/JData_User.csv', 'User', 'data/JData_User_dedup.csv')

output:

Number of duplicate records for Feb. action is: 2756093 # 重复的数量很多,
Number of duplicate records for Mar. action is: 7085038
Number of duplicate records for Feb. action is: 3672710
Number of duplicate records for Comment is: 0
Number duplicate records in Comment
Number of duplicate records for Product is: 0
Number duplicate records in Product
Number of duplicate records for User is: 0
Number duplicate records in User# action为什么会有这么多的重复数据(每个字段都相同)
# 1.可能是爬虫在操作
# 2.是否可能日志系统在上报时出现重复,业务代码有bug
# 3.也可能是用户在同一秒内点击同一个商品多次(可能性比较小)
# 查看重复数据
df_action_2 = pd.read_csv('data/JData_Action_201602.csv',encoding='gbk')
df_dup=df_action_2[df_action_2.duplicated()] # A,B,C,A,B,重复项只是后面的 A,B 不包含首次出现的
df_dup.groupby('type').count() #发现重复数据大多数都是由于浏览(1),或者点击(6)产生

output:

注:针对重复数据目前不做处理,仅将重复项保存到 data/***_dedup.csv文件中,以备使用。

检查是否存在注册时间在2016年-4月-15号之后的用户

# check user who’s user_reg_tm  >= '2016-4-15'
import pandas as pd
df_user = pd.read_csv('./data/JData_User.csv',encoding='gbk')print(df_user['user_reg_tm'][0],type(df_user['user_reg_tm'][0]))
df_user['user_reg_tm']=pd.to_datetime(df_user['user_reg_tm'])  # 为啥非得要这句呐??,以后默认还是转成Timestamp形式吧
print(df_user['user_reg_tm'][0],type(df_user['user_reg_tm'][0]))df_user.loc[df_user.user_reg_tm>= '2016-4-15']

这是啥情况?怎么还会有在给定时间之外的注册用户???看看这些用户是否有交互数据。发现没有交互,估计是后台系统出错了吧。反正也没有交互,数据就不用删除了。

行为数据中的user_id为浮点型,进行INT类型转换

这次的数据转换其实转不转换都可以,但是我还是选择了转换。

import pandas as pd
df_month = pd.read_csv('data/JData_Action_201602.csv',encoding='gbk')
df_month['user_id'] = df_month['user_id'].astype('int')    # 方式一
print (df_month['user_id'].dtype)
df_month.to_csv('data/JData_Action_201602.csv',index=None)df_month = pd.read_csv('data/JData_Action_201603.csv',encoding='gbk')
df_month['user_id'] = df_month['user_id'].apply(lambda x:int(x)) # 方式二
print (df_month['user_id'].dtype)
df_month.to_csv('data/JData_Action_201603.csv',index=None)df_month = pd.read_csv('data/JData_Action_201604.csv',encoding='gbk')
df_month['user_id'] = df_month['user_id'].astype('int')
print (df_month['user_id'].dtype)
df_month.to_csv('data/JData_Action_201604.csv',index=None)

转换之后并没有丢失数据

import numpy as np
a=[0.1,2,3,5.5,6]
print(type(a)) # <class 'list'>
b=np.array(a)
print(type(b)) #<class 'numpy.ndarray'>
print(b.dtype) # float64
c=b.astype(np.int)
print(c)     #[0 2 3 5]
print(c.dtype) #int64
'''
总结:type(a) 是查看a的类型b.dtype 是查看b中元素的类型b.astype(np.int) 改变b中元素的类型
'''

年龄区间的处理

查看用户年龄分布,并做特征编码

age_mapping = {  '15岁以下': 1,  '16-25岁': 2,  '26-35岁': 3,'36-45岁': 4,'46-55岁': 5,'56岁以上': 6,'-1' :-1}
df_user['age'] = df_user['age'].map(age_mapping)
print(df_user.age.value_counts())
df_user.to_csv('data\JData_User.csv',index=None)

为了能够进行上述清洗,在此首先构造了简单的用户(user)行为特征和商品(item)行为特征,对应于两张表user_table和item_table.

user_table

  • user_table特征包括:
  • user_id(用户id),age(年龄),sex(性别),
  • user_lv_cd(用户级别),browse_num(浏览数),
  • addcart_num(加购数),delcart_num(删购数),
  • buy_num(购买数),favor_num(收藏数),
  • click_num(点击数),buy_addcart_ratio(购买加购转化率),
  • buy_browse_ratio(购买浏览转化率),
  • buy_click_ratio(购买点击转化率),
  • buy_favor_ratio(购买收藏转化率)

item_table特征包括:

  • sku_id(商品id),attr1,attr2,
  • attr3,cate,brand,browse_num,
  • addcart_num,delcart_num,
  • buy_num,favor_num,click_num,
  • buy_addcart_ratio,buy_browse_ratio,
  • buy_click_ratio,buy_favor_ratio,
  • comment_num(评论数),
  • has_bad_comment(是否有差评),
  • bad_comment_rate(差评率)

构建User_table

# user.csv age to int
df_user = pd.read_csv(USER_FILE,encoding='gbk')
print(df_user.age.value_counts())age_mapping = {  '15岁以下': 1,  '16-25岁': 2,  '26-35岁': 3,'36-45岁': 4,'46-55岁': 5,'56岁以上': 6,'-1' :-1}
df_user['age'] = df_user['age'].map(age_mapping)
print(df_user.age.value_counts())
df_user.to_csv(USER_FILE,index=None)

# 从FJData_User表中抽取需要的字段
def get_from_jdata_user():df_usr = pd.read_csv(USER_FILE, header=0,encoding='gbk')df_usr = df_usr[["user_id", "age", "sex", "user_lv_cd"]]return df_usruser_base = get_from_jdata_user()
user_base.head()

# 功能函数: 对每一个user分组的数据进行统计
def add_type_count(group):behavior_type = group.type.astype(int)  #behavior_type只有两列:index type  没有user_id# 用户行为类别type_cnt = Counter(behavior_type) # Counter({6: 4, 1: 2}) type6 出现了4次,type1出现了2次# 1: 浏览 2: 加购 3: 删除# 4: 购买 5: 收藏 6: 点击group['browse_num'] = type_cnt[1]group['addcart_num'] = type_cnt[2]group['delcart_num'] = type_cnt[3]group['buy_num'] = type_cnt[4]group['favor_num'] = type_cnt[5]group['click_num'] = type_cnt[6]return group[['user_id', 'browse_num', 'addcart_num','delcart_num', 'buy_num', 'favor_num','click_num']]'''
例子
behavior_type:
2     1
3     6
17    6
41    6
43    1
44    6group:user_id  type  browse_num  addcart_num  delcart_num  buy_num  favor_num   click_num
2    200719     1           2            0            0        0          0      4
3    200719     6           2            0            0        0          0      4
17   200719     6           2            0            0        0          0      4
41   200719     6           2            0            0        0          0      4
43   200719     1           2            0            0        0          0      4
44   200719     6           2            0            0        0          0      4
'''
#对action数据进行统计
#根据自己调节chunk_size大小
def get_from_action_data(fname, chunk_size=50000):reader = pd.read_csv(fname, header=0, iterator=True,encoding='gbk')chunks = []loop = Truewhile loop:try:# 只读取user_id和type两个字段chunk = reader.get_chunk(chunk_size)[["user_id", "type"]]chunks.append(chunk)except StopIteration:loop = Falseprint("Iteration is stopped")# 将块拼接为pandas dataframe格式df_ac = pd.concat(chunks, ignore_index=True)# 按user_id分组,对每一组进行统计,as_index 表示无索引形式返回数据df_ac = df_ac.groupby(['user_id'], as_index=False).apply(add_type_count)# 将重复的行丢弃df_ac = df_ac.drop_duplicates('user_id')return df_ac     # df_ac:每一个user_id 有多少次浏览、点击、、、
df_ac=get_from_action_data(fname=ACTION_201602_FILE)
df_ac

# 将各个action数据的统计量进行聚合
def merge_action_data():df_ac = []df_ac.append(get_from_action_data(fname=ACTION_201602_FILE))df_ac.append(get_from_action_data(fname=ACTION_201603_FILE))df_ac.append(get_from_action_data(fname=ACTION_201604_FILE))df_ac = pd.concat(df_ac, ignore_index=True)# 用户在不同action表中统计量求和df_ac = df_ac.groupby(['user_id'], as_index=False).sum()# 构造转化率字段df_ac['buy_addcart_ratio'] = df_ac['buy_num'] / df_ac['addcart_num']df_ac['buy_browse_ratio'] = df_ac['buy_num'] / df_ac['browse_num']df_ac['buy_click_ratio'] = df_ac['buy_num'] / df_ac['click_num']df_ac['buy_favor_ratio'] = df_ac['buy_num'] / df_ac['favor_num']# 将大于1的转化率字段置为1(100%)df_ac.loc[df_ac['buy_addcart_ratio'] > 1., 'buy_addcart_ratio'] = 1.df_ac.loc[df_ac['buy_browse_ratio'] > 1., 'buy_browse_ratio'] = 1.df_ac.loc[df_ac['buy_click_ratio'] > 1., 'buy_click_ratio'] = 1.df_ac.loc[df_ac['buy_favor_ratio'] > 1., 'buy_favor_ratio'] = 1.return df_ac
user_behavior = merge_action_data()
# print(user_behavior.shape)
user_behavior.head(50)

# 连接成一张表,类似于SQL的左连接(left join)
user_behavior = pd.merge(user_base, user_behavior, on=['user_id'], how='left')
# 保存为user_table.csv
user_behavior.to_csv(USER_TABLE_FILE, index=False)user_table = pd.read_csv(USER_TABLE_FILE)
user_table.head()

构建Item_table

# 读取Product中商品
def get_from_jdata_product():df_item = pd.read_csv(PRODUCT_FILE, header=0,encoding='gbk')return df_item
item_base = get_from_jdata_product()
print(item_base.shape)
item_base.head()

# 评论数据
df_cmt = pd.read_csv(COMMENT_FILE, header=0)
print("before:\n",df_cmt.shape,'\n',df_cmt.head())
df_cmt.dt.value_counts()

# 获取评论中的商品数据,如果存在某一个商品有两个日期的评论,我们取最晚的那一个
def get_from_jdata_comment():df_cmt = pd.read_csv(COMMENT_FILE, header=0)df_cmt['dt'] = pd.to_datetime(df_cmt['dt'])# find latest comment indexidx = df_cmt.groupby(['sku_id'])['dt'].transform(max) == df_cmt['dt']  # 取最晚的那一个??df_cmt = df_cmt[idx]return df_cmt[['sku_id', 'comment_num','has_bad_comment', 'bad_comment_rate']]item_comment = get_from_jdata_comment()
print(item_comment.shape)
item_comment.head()

# 对每一个商品分组进行统计
def add_type_count(group):behavior_type = group.type.astype(int)type_cnt = Counter(behavior_type)group['browse_num'] = type_cnt[1]group['addcart_num'] = type_cnt[2]group['delcart_num'] = type_cnt[3]group['buy_num'] = type_cnt[4]group['favor_num'] = type_cnt[5]group['click_num'] = type_cnt[6]return group[['sku_id', 'browse_num', 'addcart_num','delcart_num', 'buy_num', 'favor_num','click_num']]#对action中的数据进行统计
def get_from_action_data(fname, chunk_size=50000):reader = pd.read_csv(fname, header=0, iterator=True)chunks = []loop = Truewhile loop:try:chunk = reader.get_chunk(chunk_size)[["sku_id", "type"]]chunks.append(chunk)except StopIteration:loop = Falseprint("Iteration is stopped")df_ac = pd.concat(chunks, ignore_index=True)df_ac = df_ac.groupby(['sku_id'], as_index=False).apply(add_type_count)# Select unique rowdf_ac = df_ac.drop_duplicates('sku_id')return df_acdef merge_action_data():df_ac = []df_ac.append(get_from_action_data(fname=ACTION_201602_FILE))df_ac.append(get_from_action_data(fname=ACTION_201603_FILE))df_ac.append(get_from_action_data(fname=ACTION_201604_FILE))df_ac = pd.concat(df_ac, ignore_index=True)df_ac = df_ac.groupby(['sku_id'], as_index=False).sum()df_ac['buy_addcart_ratio'] = df_ac['buy_num'] / df_ac['addcart_num']df_ac['buy_browse_ratio'] = df_ac['buy_num'] / df_ac['browse_num']df_ac['buy_click_ratio'] = df_ac['buy_num'] / df_ac['click_num']df_ac['buy_favor_ratio'] = df_ac['buy_num'] / df_ac['favor_num']df_ac.loc[df_ac['buy_addcart_ratio'] > 1., 'buy_addcart_ratio'] = 1.df_ac.loc[df_ac['buy_browse_ratio'] > 1., 'buy_browse_ratio'] = 1.df_ac.loc[df_ac['buy_click_ratio'] > 1., 'buy_click_ratio'] = 1.df_ac.loc[df_ac['buy_favor_ratio'] > 1., 'buy_favor_ratio'] = 1.return df_ac
item_behavior = merge_action_data()
print(item_behavior.shape)
item_behavior.head()

# SQL: left join
item_behavior = pd.merge(item_base, item_behavior, on=['sku_id'], how='left')
item_behavior = pd.merge(item_behavior, item_comment, on=['sku_id'], how='left')item_behavior.to_csv(ITEM_TABLE_FILE, index=False)
print(item_behavior.shape)
print(item_behavior.head())

这么多NaN 是不是哪里出问题了??

数据清洗

用户清洗

import pandas as pd
df_user = pd.read_csv('data/User_table.csv',header=0)
pd.options.display.float_format = '{:,.3f}'.format  #输出格式设置,保留三位小数
df_user.describe()# 由上述统计信息发现: 第一行中根据User_id统计发现有105321个用户,发现有3个用户没有age,sex字段,
# 而且根据浏览、加购、删购、购买等记录却只有105180条记录,说明存在用户无任何交互记录,因此可以删除上述用户。

delete_list = df_user[df_user['age'].isnull()].index
df_user.drop(delete_list,axis=0,inplace=True)
df_user.describe()

#删除无交互记录的用户
df_naction = df_user[(df_user['browse_num'].isnull()) & (df_user['addcart_num'].isnull()) & (df_user['delcart_num'].isnull()) & (df_user['buy_num'].isnull()) & (df_user['favor_num'].isnull()) & (df_user['click_num'].isnull())]
df_user.drop(df_naction.index,axis=0,inplace=True)
df_user.describe()

#统计无购买记录的用户
df_bzero = df_user[df_user['buy_num']==0].index
#输出购买数为0的总记录数
print (len(df_bzero))
df_user.drop(df_bzero,axis=0,inplace=True)  # 共75694条

删除爬虫及惰性用户
由上表所知,浏览购买转换比和点击购买转换比均值为0.018,0.030,因此这里认为浏览购买转换比和点击购买转换比小于0.0005的用户为惰性用户

bindex = df_user[df_user['buy_browse_ratio']<0.0005].index
print (len(bindex))
df_user.drop(bindex,axis=0,inplace=True) # 共90条
cindex = df_user[df_user['buy_click_ratio']<0.0005].index
print (len(cindex))
df_user.drop(cindex,axis=0,inplace=True)  #共323
df_user.describe()
#最后这29070个用户为最终预测用户数据集

京东用户购买意向预测(一)数据清洗相关推荐

  1. 【机器学习】京东用户购买意向预测-数据集介绍和数据清洗 - 1

    主题:京东用户购买意向预测 数据集: 这里涉及到的数据集是京东最新的数据集: JData_User.csv 用户数据集 105,321个用户 JData_Comment.csv 商品评论 558,55 ...

  2. 京东用户购买意向预测(一)

    数据清洗 故事背景: 数据集: 数据挖掘流程: 数据集验证 首先检查JData_User中的用户和JData_Action中的用户是否一致 因为数据量很大所以每次读取的时间有点长,所以很着急看结果的话 ...

  3. NO.90——京东用户购买意向预测之数据预处理

    文章目录 1 目标 2 数据集 3 数据挖掘流程 4 数据清洗 4.1 数据集验证 4.2 检查是否有重复记录 4.3 检查是否存在注册时间在2016年-4月-15号之后的用户 4.4 行为数据中的u ...

  4. JData数据处理及高潜用户购买意向预测

    竞赛概述: 本次大赛以京东商城真实的用户.商品和行为数据(脱敏后)为基础,参赛队伍需要通过数据挖掘的技术和机器学习的算法,构建用户购买商品的预测模型,输出高潜用户和目标商品的匹配结果,为精准营销提供高 ...

  5. 京东算法大赛-高潜用户购买意向预测(一) 资料整理

    初学者可以参考daoliker提供的资料:https://github.com/daoliker/JData,这是一位热心的参赛者提供的一份入门程序,涵盖了数据清洗.数据(统计)分析.特征抽取.搭建模 ...

  6. 京东JData算法大赛——高潜用户购买意向预测

    赛题分析 京东提供了用户在2016-02-01-2016-04-15时间区域内用户对商品的行为评价等数据,预测2016-04-16-2016-04-20时间区间内用户的下单情况. 赛题和阿里的第一个竞 ...

  7. 京东JData算法大赛高潜用户购买意向预测——复现(并没有),提供数据集

    19-1-15更新,后面改了做法所以随笔烂尾了,具体内容不用看,想参考的可以看下面的参考链接 另外提供数据集在百度云,希望能帮到大家 链接: https://pan.baidu.com/s/1ojjV ...

  8. 京东JData算法大赛-高潜用户购买意向预测(github源码)

    向AI转型的程序员都关注了这个号

  9. 京东JData2017算法大赛高潜用户购买意向预测数据集下载

    找了老半天,都没找到,要么链接过期,要么要收费,感觉这种东西收费不是很君子,毕竟这东西不是咱们自己产的嘛,感谢这位博主,下面是这位博主提供的下载链接 这位博主还提供了一些复现的思路,大家可以学习下 链 ...

最新文章

  1. C++学习笔记24,方法重写与方法隐藏
  2. 图灵71年前就已提出神经网络!《智能机器》再掀热议却一生未发表
  3. java面试怎样成功率高一些_java初学者参加面试怎样提高成功率?
  4. SQL Server FOR XML PATH 语句的应用
  5. Qt中多线程与界面组件的通信
  6. C++中初始化列表的使用
  7. Pixhawk之姿态解算篇(5)_ECF/EKF/GD介绍
  8. java中退订程序怎么写_如何在RxJava中的自定义Observable中获得观察者的退订操作的通知...
  9. hibernate中主键的生成策略
  10. FTP下载文件中文名乱码FTP访问
  11. Katalon Recorder录制脚本
  12. python定义初始化函数_Python 语言定义的Class的初始化函数的函数名是( )
  13. python列表用什么符号表示_python列表类型
  14. 后勤管理系统-在线报修系统
  15. 2022年PC必备的5款软件,功能强大且免费,你用过几个?
  16. OkHttp3 源码解读
  17. 火灾探测和监测系统的最新进展回顾
  18. 浅谈移动通信的切换技术(转)
  19. 一些《集成电路与光刻机》笔记
  20. AM4379 EDMA相关总结

热门文章

  1. POI数据库的广泛应用(全国商户数据、社区数据、学校数据、医院数据等POI服务)
  2. Boostnote 离线版本(local 版)
  3. kafka基础入门(三)
  4. pom中配置maven仓库(阿里仓库)
  5. JWT安全WebGoat实战与预编译CASE注入
  6. 操作系统|知识梳理|复习(下)
  7. 最小二乘法的一阶、二阶辨识系统
  8. 那些你不知道的炫酷按钮交互效果
  9. 战争迷雾效果 第4章_真正的迷雾来了!
  10. py爬虫数据到本地Excel表格