mdbq 3.3.15__py3-none-any.whl → 3.4.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,6 @@
1
1
  # -*- coding: UTF-8 –*-
2
2
  import os
3
+ import re
3
4
  import socket
4
5
  import platform
5
6
  import datetime
@@ -444,7 +445,7 @@ class DataShow:
444
445
  yref='paper',
445
446
  showarrow=False, # 显示箭头
446
447
  align="left", # 文本对齐方式
447
- font=dict(size=16),
448
+ font=dict(size=14),
448
449
  )
449
450
  fig.update_layout(
450
451
  title_text=f'多店推广花费_按日聚合',
@@ -499,12 +500,11 @@ class DataShow:
499
500
  print(f'{table_name}: 数据长度不能为 0')
500
501
  continue
501
502
  df['日期'] = pd.to_datetime(df['日期'])
503
+
502
504
  df['商品id'] = df['商品id'].astype('int64')
503
505
  df = df[df['商品id'] == int(item_id)]
504
- last_date = df['日期'].max()
505
506
  # 对数据进行筛选
506
507
  df = df[
507
- (df['日期'] == last_date) &
508
508
  ~df['标签名称'].str.contains('unknown', case=False) &
509
509
  (df['洞察类型'] == lab) &
510
510
  (df['行为类型'] == option) &
@@ -515,6 +515,7 @@ class DataShow:
515
515
  fig = make_subplots(rows=2, cols=3)
516
516
  # 在每个子图中绘制柱形图
517
517
  count = 0
518
+ sv_date = {}
518
519
  for table_name, df in dict_list.items():
519
520
  if len(df) == 0:
520
521
  count += 1
@@ -522,7 +523,12 @@ class DataShow:
522
523
  # print(count, table_name)
523
524
  if count > 5:
524
525
  break
525
- labels = df['标签名称'].tolist()
526
+ last_date = df['日期'].max()
527
+ sv_date.update({table_name: last_date.strftime('%Y-%m-%d')})
528
+ df = df[df['日期'] == last_date]
529
+ # 先进行排序,以便柱形图从高到底
530
+ df.sort_values(['标签人群数量'], ascending=[False], ignore_index=True, inplace=True)
531
+ labels = df['标签名称'].tolist() # 由于上面有自定义排序,labels 和 values 要放在一起
526
532
  values = df['标签人群数量'].tolist()
527
533
  df['Percentage'] = df['标签人群数量'] / df['标签人群数量'].sum() * 100
528
534
  percentages = df['Percentage']
@@ -530,8 +536,10 @@ class DataShow:
530
536
  x=labels,
531
537
  y=values,
532
538
  name=table_name,
539
+ orientation='v', # 垂直柱形图
533
540
  text=percentages.map('{:.2f}%'.format), # 设置要显示的文本(百分比)
534
541
  # textposition = 'outside', # 设置文本位置在柱形图外部
542
+ width=0.55 # 调整柱子最大宽度
535
543
  )
536
544
  row = count // 3 + 1
537
545
  col = count % 3 + 1
@@ -541,20 +549,20 @@ class DataShow:
541
549
  col=col,
542
550
  )
543
551
  if count < 3:
544
- x = 0.01 + 0.395 * (count)
552
+ x = 0.01 + 0.385 * (count)
545
553
  y = 1.04
546
554
  else:
547
- x = 0.01 + 0.395 * (count % 3)
555
+ x = 0.01 + 0.385 * (count % 3)
548
556
  y = 1.04 - 0.59 * (count // 3)
549
557
  fig.add_annotation(
550
- text=table_name,
558
+ text=f'{table_name}',
551
559
  x=x,
552
560
  y=y,
553
561
  xref='paper', # # 相对于整个图表区域
554
562
  yref='paper',
555
563
  showarrow=False, # 显示箭头
556
564
  align="left", # 文本对齐方式
557
- font=dict(size=16),
565
+ font=dict(size=15),
558
566
  )
559
567
  count += 1
560
568
 
@@ -573,7 +581,7 @@ class DataShow:
573
581
  # legend=dict(orientation="h")
574
582
  )
575
583
  fig.add_annotation(
576
- text=f'数据日期: {last_date.strftime('%Y-%m-%d')} 统计范围: {lab}/{option} {d_str}',
584
+ text=f'统计范围: {lab}/{option} {d_str}',
577
585
  x=0.5,
578
586
  y=-0.1,
579
587
  xref='paper', # # 相对于整个图表区域
@@ -582,17 +590,166 @@ class DataShow:
582
590
  align="left", # 文本对齐方式
583
591
  font=dict(size=14),
584
592
  )
593
+ fig.add_annotation(
594
+ text=re.sub('[{}\',]', '', str(sv_date)),
595
+ x=0.5,
596
+ y=-0.135,
597
+ xref='paper', # # 相对于整个图表区域
598
+ yref='paper',
599
+ showarrow=False, # 显示箭头
600
+ align="left", # 文本对齐方式
601
+ font=dict(size=12),
602
+ )
603
+ fig.write_html(os.path.join(self.path, f'{filename}.html'))
604
+
605
+ def crowd(self, db_name='人群画像2', table_list=None, pro_list=None, filename='达摩盘人群画像', crowd_id=None, last_date=None):
606
+ # item_ids = [696017020186, 714066010148, 830890472575]
607
+ if not pro_list:
608
+ pro_list = ['日期', '店铺名称', '人群id', '人群名称', '标签名称', '标签人群数量']
609
+ if not table_list:
610
+ table_list = [
611
+ '消费能力等级',
612
+ '用户年龄',
613
+ '月均消费金额',
614
+ '大快消策略人群',
615
+ '店铺潜新老客',
616
+ '城市等级',
617
+ '用户职业',
618
+ ]
619
+ if not crowd_id:
620
+ crowd_id = 40457369
621
+
622
+ dict_list = {}
623
+ for table_name in table_list:
624
+ df = self.getdata(db_name=db_name, table_name=table_name, pro_list=pro_list)
625
+ if len(df) == 0:
626
+ print(f'{table_name}: 数据长度不能为 0')
627
+ continue
628
+ df['日期'] = pd.to_datetime(df['日期'])
629
+
630
+ df['人群id'] = df['人群id'].astype('int64')
631
+ df = df[df['人群id'] == int(crowd_id)]
632
+ # 对数据进行筛选
633
+ df = df[
634
+ (df['店铺名称'] == '万里马官方旗舰店')
635
+ # ~df['标签名称'].str.contains('unknown', case=False)
636
+ ]
637
+ dict_list.update({table_name: df})
638
+ crowd_name = df.head(1)['人群名称'].tolist()[0] # 随便取一条数据读取人群名称
639
+ fig = make_subplots(rows=2, cols=3)
640
+ # 在每个子图中绘制柱形图
641
+ count = 0
642
+ sv_date = {}
643
+ unknown_dict = {}
644
+ for table_name, df in dict_list.items():
645
+ if len(df) == 0:
646
+ count += 1
647
+ continue
648
+ # print(count, table_name)
649
+ if count > 5:
650
+ break
651
+ last_date = df['日期'].max()
652
+ df = df[df['日期'] == last_date]
653
+ unknown = df[df['标签名称'].str.contains('unknown', case=False)]
654
+ if len(unknown) > 0:
655
+ unknown = unknown['标签人群数量'].tolist()[0] # 未知人群数量值
656
+
657
+ df = df[~df['标签名称'].str.contains('unknown', case=False)]
658
+ # 先进行排序,以便柱形图从高到底
659
+ df.sort_values(['标签人群数量'], ascending=[False], ignore_index=True, inplace=True)
660
+ labels = df['标签名称'].tolist() # 由于上面有自定义排序,labels 和 values 要放在一起
661
+ values = df['标签人群数量'].tolist()
662
+ crowd_sum = df['标签人群数量'].values.sum()
663
+ sv_date.update({table_name: crowd_sum})
664
+ unknown_dict.update({table_name: unknown})
665
+ df['Percentage'] = df['标签人群数量'] / df['标签人群数量'].sum() * 100
666
+ percentages = df['Percentage']
667
+ bar = go.Bar(
668
+ x=labels,
669
+ y=values,
670
+ name=table_name,
671
+ orientation='v', # 垂直柱形图
672
+ text=percentages.map('{:.2f}%'.format), # 设置要显示的文本(百分比)
673
+ # textposition = 'outside', # 设置文本位置在柱形图外部
674
+ width=0.55 # 调整柱子最大宽度
675
+ )
676
+ row = count // 3 + 1
677
+ col = count % 3 + 1
678
+ fig.add_trace(
679
+ bar,
680
+ row=row,
681
+ col=col,
682
+ )
683
+ if count < 3:
684
+ x = 0.01 + 0.42 * (count)
685
+ y = 1.04
686
+ else:
687
+ x = 0.01 + 0.42 * (count % 3)
688
+ y = 1.04 - 0.59 * (count // 3)
689
+ fig.add_annotation(
690
+ text=f'{table_name} 人群数量: {crowd_sum}',
691
+ x=x,
692
+ y=y,
693
+ xref='paper', # # 相对于整个图表区域
694
+ yref='paper',
695
+ showarrow=False, # 显示箭头
696
+ align="left", # 文本对齐方式
697
+ font=dict(size=15),
698
+ )
699
+ count += 1
700
+
701
+ fig.update_layout(
702
+ title_text=f'达摩盘人群画像 人群id: {crowd_id} / 人群名字: 【{crowd_name}】',
703
+ xaxis_title='标签',
704
+ yaxis_title='人群数量',
705
+ # width=self.screen_width // 1.4,
706
+ # height=self.screen_width // 2,
707
+ margin=dict(
708
+ l=100, # 左边距
709
+ r=100,
710
+ t=100, # 上边距
711
+ b=100,
712
+ ),
713
+ # legend=dict(orientation="h")
714
+ )
715
+ res = {}
716
+ for k, v in sv_date.items():
717
+ res.update({k: int(v)})
718
+ unknown_res = {}
719
+ for k, v in unknown_dict.items():
720
+ unknown_res.update({k: int(v)})
721
+
722
+ fig.add_annotation(
723
+ text=f'分析人群数量: {re.sub('[{}\',]', '', str(res))}',
724
+ x=0.5,
725
+ y=-0.1,
726
+ xref='paper', # # 相对于整个图表区域
727
+ yref='paper',
728
+ showarrow=False, # 显示箭头
729
+ align="left", # 文本对齐方式
730
+ font=dict(size=12),
731
+ )
732
+ fig.add_annotation(
733
+ text=f'与官方统计存在差异,官方计算中包含未知人群,数量为: {re.sub('[{}\',]', '', str(unknown_res))},未知人群占比越大,同官方差异越大',
734
+ x=0.5,
735
+ y=-0.135,
736
+ xref='paper', # # 相对于整个图表区域
737
+ yref='paper',
738
+ showarrow=False, # 显示箭头
739
+ align="left", # 文本对齐方式
740
+ font=dict(size=12),
741
+ )
585
742
  fig.write_html(os.path.join(self.path, f'{filename}.html'))
586
743
 
587
744
 
588
745
  def main():
589
746
  ds = DataShow()
590
- # ds.dpll()
591
- # ds.tg(
592
- # days=15,
593
- # # start_date='2024-11-01',
594
- # # end_date='2024-11-30',
595
- # )
747
+ ds.dpll()
748
+ ds.tg(
749
+ days=15,
750
+ # start_date='2024-11-01',
751
+ # end_date='2024-11-30',
752
+ )
596
753
  ds.item_crowd(
597
754
  item_id=839148235697,
598
755
  lab='全部渠道',
@@ -600,6 +757,10 @@ def main():
600
757
  last_date=None,
601
758
  d_str='近30天',
602
759
  )
760
+ ds.crowd(
761
+ crowd_id=40457166,
762
+ last_date=None,
763
+ )
603
764
 
604
765
 
605
766
  if __name__ == '__main__':
@@ -482,19 +482,39 @@ class MysqlDatasQuery:
482
482
  }
483
483
  )
484
484
  df.insert(loc=1, column='推广渠道', value='万相台无界版') # df中插入新列
485
+
486
+ # 开始处理用户特征
487
+ df_sx = self.download.data_to_df(
488
+ db_name='达摩盘3',
489
+ table_name=f'我的人群属性',
490
+ start_date=start_date,
491
+ end_date=end_date,
492
+ projection={'人群名称': 1, '消费能力等级': 1, '用户年龄': 1},
493
+ )
494
+ df_sx['人群名称'] = df_sx['人群名称'].apply(lambda x: f'达摩盘:{x}')
495
+ df_sx.rename(columns={'消费能力等级': '消费力层级'}, inplace=True)
496
+ df = pd.merge(df, df_sx, left_on=['人群名字'], right_on=['人群名称'], how='left')
497
+ df.pop('人群名称')
498
+ df['消费力层级'] = df['消费力层级'].apply(
499
+ lambda x: f'L{"".join(re.findall(r'L(\d)', str(x)))}' if str(x) != 'nan' else x)
500
+ df['用户年龄'] = df['用户年龄'].apply(
501
+ lambda x: "~".join(re.findall(r'(\d{2})\D.*(\d{2})岁', str(x))[0])
502
+ if str(x) != 'nan' and re.findall(r'(\d{2})\D.*(\d{2})岁', str(x)) else x)
503
+
485
504
  # 1. 匹配 L后面接 2 个或以上数字,不区分大小写,示例:L345
486
505
  # 2. 其余情况,L 后面接多个数字的都会被第一条 if 命中,不区分大小写
506
+
487
507
  df['消费力层级'] = df.apply(
488
508
  lambda x:
489
- ''.join(re.findall(r'(l\d+)', x['人群名字'].upper(), re.IGNORECASE)) if re.findall(r'(l\d{2,})',
490
- x['人群名字'],
491
- re.IGNORECASE)
492
- else 'L5' if re.findall(r'(l\d*5)', x['人群名字'], re.IGNORECASE)
493
- else 'L4' if re.findall(r'(l\d*4)', x['人群名字'], re.IGNORECASE)
494
- else 'L3' if re.findall(r'(l\d*3)', x['人群名字'], re.IGNORECASE)
495
- else 'L2' if re.findall(r'(l\d*2)', x['人群名字'], re.IGNORECASE)
496
- else 'L1' if re.findall(r'(l\d*1)', x['人群名字'], re.IGNORECASE)
497
- else '', axis=1)
509
+ ''.join(re.findall(r'(l\d+)', x['人群名字'].upper(), re.IGNORECASE))
510
+ if re.findall(r'(l\d{2,})', x['人群名字'], re.IGNORECASE) and str(x['消费力层级']) == 'nan'
511
+ else 'L5' if re.findall(r'(l\d*5)', x['人群名字'], re.IGNORECASE) and str(x['消费力层级']) == 'nan'
512
+ else 'L4' if re.findall(r'(l\d*4)', x['人群名字'], re.IGNORECASE) and str(x['消费力层级']) == 'nan'
513
+ else 'L3' if re.findall(r'(l\d*3)', x['人群名字'], re.IGNORECASE) and str(x['消费力层级']) == 'nan'
514
+ else 'L2' if re.findall(r'(l\d*2)', x['人群名字'], re.IGNORECASE) and str(x['消费力层级']) == 'nan'
515
+ else 'L1' if re.findall(r'(l\d*1)', x['人群名字'], re.IGNORECASE) and str(x['消费力层级']) == 'nan'
516
+ else x['消费力层级'], axis=1)
517
+
498
518
  # 1. 匹配连续的 4 个数字且后面不能接数字或"元"或汉字,筛掉的人群示例:月均消费6000元|受众20240729175213|xxx2024真皮公文包
499
519
  # 2. 匹配 2数字_2数字且前面不能是数字,合法匹配:人群_30_50_促; 非法示例:L345_3040 避免识别出 35~20 岁用户的情况
500
520
  # pattern = r'(\d{4})(?!\d|[\u4e00-\u9fa5])' # 匹配 4 个数字,后面不能接数字或汉字
@@ -506,21 +526,30 @@ class MysqlDatasQuery:
506
526
  pattern2 = r'(?<![\dlL])(\d{2}_\d{2})'
507
527
  df['用户年龄'] = df.apply(
508
528
  lambda x:
509
- ''.join(re.findall(pattern1, x['人群名字'].upper())) if re.findall(pattern1, x['人群名字'])
510
- # else ''.join(re.findall(r'[^\d|l|L](\d{2}_\d{2})', x['人群名字'].upper())) if re.findall(r'[^\d|l|L](\d{2}_\d{2})', x['人群名字'])
511
- else ''.join(re.findall(pattern2, x['人群名字'].upper())) if re.findall(pattern2, x['人群名字'])
512
- else ''.join(re.findall(r'(\d{2}-\d{2})岁', x['人群名字'].upper())) if re.findall(r'(\d{2}-\d{2})',
513
- x['人群名字'])
514
- else '', axis=1)
529
+ ''.join(re.findall(pattern1, x['人群名字'].upper()))
530
+ if re.findall(pattern1, x['人群名字']) and str(x['用户年龄']) == 'nan'
531
+ else ''.join(re.findall(pattern2, x['人群名字'].upper()))
532
+ if re.findall(pattern2, x['人群名字']) and str(x['用户年龄']) == 'nan'
533
+ else ''.join(re.findall(r'(\d{2}-\d{2})岁', x['人群名字'].upper()))
534
+ if re.findall(r'(\d{2}-\d{2})岁', x['人群名字']) and str(x['用户年龄']) == 'nan'
535
+ else x['用户年龄'], axis=1)
515
536
  df['用户年龄'] = df['用户年龄'].apply(
516
537
  lambda x: f'{x[:2]}~{x[2:4]}' if str(x).isdigit()
517
- else str(x).replace('_', '~') if '_' in x
518
- else str(x).replace('-', '~') if '-' in x
538
+ else str(x).replace('_', '~') if '_' in str(x)
539
+ else str(x).replace('-', '~') if '-' in str(x)
519
540
  else x
520
541
  )
521
542
  # 年龄层不能是 0 开头
522
543
  df['用户年龄'] = df['用户年龄'].apply(
523
544
  lambda x: '' if str(x).startswith('0') else x)
545
+ df['用户年龄'] = df['用户年龄'].apply(
546
+ lambda x:
547
+ re.sub(f'~50', '~49' ,str(x)) if '~50' in str(x) else
548
+ re.sub(f'~40', '~39', str(x)) if '~40' in str(x) else
549
+ re.sub(f'~30', '~29' ,str(x)) if '~30' in str(x) else
550
+ re.sub(r'\d{4}~', '', str(x)) if str(x) != 'nan' else
551
+ x
552
+ )
524
553
  # df = df.head(1000)
525
554
  # df.to_csv('/Users/xigua/Downloads/test.csv', index=False, header=True, encoding='utf-8_sig')
526
555
  # breakpoint()
@@ -3809,6 +3838,10 @@ if __name__ == '__main__':
3809
3838
  # query3(months=2, less_dict=[])
3810
3839
 
3811
3840
  sdq = MysqlDatasQuery() # 实例化数据处理类
3812
- sdq.months = 100 # 设置数据周期, 1 表示近 2 个月
3841
+ sdq.months = 1 # 设置数据周期, 1 表示近 2 个月
3813
3842
  sdq.update_service = True # 调试时加,true: 将数据写入 mysql 服务器
3814
- sdq.dplyd(db_name='聚合数据', table_name='店铺流量来源构成')
3843
+ sdq.tg_rqbb(db_name='聚合数据', table_name='天猫_人群报表')
3844
+
3845
+ # string = '30-34岁,35-39岁,40-49岁'
3846
+ # d = "~".join(re.findall(r'(\d+)\D.*\D(\d+)岁', string)[0])
3847
+ # print(d)
mdbq/mysql/mysql.py CHANGED
@@ -113,6 +113,7 @@ class MysqlUpload:
113
113
 
114
114
  @staticmethod
115
115
  def try_except(func): # 在类内部定义一个异常处理方法
116
+
116
117
  @wraps(func)
117
118
  def wrapper(*args, **kwargs):
118
119
  try:
@@ -122,6 +123,7 @@ class MysqlUpload:
122
123
  with open(error_file, 'a') as f:
123
124
  now = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
124
125
  f.write(f'\n{now} \n')
126
+ f.write(f'函数注释内容(用于定位函数): {func.__doc__} \n')
125
127
  # f.write(f'报错的文件:\n{e.__traceback__.tb_frame.f_globals["__file__"]}\n') # 发生异常所在的文件
126
128
  traceback.print_exc(file=open(error_file, 'a')) # 返回完整的堆栈信息
127
129
  print(f'更多信息请查看日志文件: {error_file}')
@@ -1439,6 +1441,7 @@ class OptimizeDatas:
1439
1441
 
1440
1442
  @staticmethod
1441
1443
  def try_except(func): # 在类内部定义一个异常处理方法
1444
+
1442
1445
  @wraps(func)
1443
1446
  def wrapper(*args, **kwargs):
1444
1447
  try:
@@ -1448,6 +1451,7 @@ class OptimizeDatas:
1448
1451
  with open(error_file, 'a') as f:
1449
1452
  now = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
1450
1453
  f.write(f'\n{now} \n')
1454
+ f.write(f'函数注释内容(用于定位函数): {func.__doc__} \n')
1451
1455
  # f.write(f'报错的文件:\n{e.__traceback__.tb_frame.f_globals["__file__"]}\n') # 发生异常所在的文件
1452
1456
  traceback.print_exc(file=open(error_file, 'a')) # 返回完整的堆栈信息
1453
1457
  print(f'更多信息请查看日志文件: {error_file}')
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: mdbq
3
- Version: 3.3.15
3
+ Version: 3.4.0
4
4
  Home-page: https://pypi.org/project/mdbq
5
5
  Author: xigua,
6
6
  Author-email: 2587125111@qq.com
@@ -2,9 +2,9 @@ mdbq/__init__.py,sha256=Il5Q9ATdX8yXqVxtP_nYqUhExzxPC_qk_WXQ_4h0exg,16
2
2
  mdbq/__version__.py,sha256=y9Mp_8x0BCZSHsdLT_q5tX9wZwd5QgqrSIENLrb6vXA,62
3
3
  mdbq/aggregation/__init__.py,sha256=EeDqX2Aml6SPx8363J-v1lz0EcZtgwIBYyCJV6CcEDU,40
4
4
  mdbq/aggregation/aggregation.py,sha256=-yzApnlqSN2L0E1YMu5ml-W827qpKQvWPCOI7jj2kzY,80264
5
- mdbq/aggregation/datashow.py,sha256=sNZYwhPraF3KmcYdBVKvVaVoN-jGjh7ALRRLpanzQ6w,25673
5
+ mdbq/aggregation/datashow.py,sha256=2NzHGjGoUy2WG-MxmbilCj6KBAmVah3jqFuEd2zv9XU,32379
6
6
  mdbq/aggregation/optimize_data.py,sha256=RXIv7cACCgYyehAxMjUYi_S7rVyjIwXKWMaM3nduGtA,3068
7
- mdbq/aggregation/query_data.py,sha256=4Fd4dMGi6Cu-KgNTf1OBNYe8InjvpMA5JALxCwvsHyw,173841
7
+ mdbq/aggregation/query_data.py,sha256=FiNZhL5_El2B5ADfCPGUZXsE2iZd3UmGml9Te9qJIpU,175364
8
8
  mdbq/bdup/__init__.py,sha256=AkhsGk81SkG1c8FqDH5tRq-8MZmFobVbN60DTyukYTY,28
9
9
  mdbq/bdup/bdup.py,sha256=LAV0TgnQpc-LB-YuJthxb0U42_VkPidzQzAagan46lU,4234
10
10
  mdbq/config/__init__.py,sha256=jso1oHcy6cJEfa7udS_9uO5X6kZLoPBF8l3wCYmr5dM,18
@@ -18,7 +18,7 @@ mdbq/log/mylogger.py,sha256=oaT7Bp-Hb9jZt52seP3ISUuxVcI19s4UiqTeouScBO0,3258
18
18
  mdbq/mongo/__init__.py,sha256=SILt7xMtQIQl_m-ik9WLtJSXIVf424iYgCfE_tnQFbw,13
19
19
  mdbq/mongo/mongo.py,sha256=M9DUeUCMPDngkwn9-ui0uTiFrvfNU1kLs22s5SmoNm0,31899
20
20
  mdbq/mysql/__init__.py,sha256=A_DPJyAoEvTSFojiI2e94zP0FKtCkkwKP1kYUCSyQzo,11
21
- mdbq/mysql/mysql.py,sha256=OndnoP1cBDM9h1bR_Uh2waT3yUjlgr05zHIlC7mmxhc,99378
21
+ mdbq/mysql/mysql.py,sha256=r5YkS1WnV9dGtEHFcwaekjtUBgFcvkdmwif-m52CyHI,99560
22
22
  mdbq/mysql/recheck_mysql.py,sha256=ppBTfBLgkRWirMVZ31e_ZPULiGPJU7K3PP9G6QBZ3QI,8605
23
23
  mdbq/mysql/s_query.py,sha256=6L5Cp90zq13noZHjzSA5mqms_hD01c8GO1_NfbYDu6w,9252
24
24
  mdbq/mysql/year_month_day.py,sha256=VgewoE2pJxK7ErjfviL_SMTN77ki8GVbTUcao3vFUCE,1523
@@ -34,7 +34,7 @@ mdbq/pbix/refresh_all.py,sha256=OBT9EewSZ0aRS9vL_FflVn74d4l2G00wzHiikCC4TC0,5926
34
34
  mdbq/pbix/refresh_all_old.py,sha256=_pq3WSQ728GPtEG5pfsZI2uTJhU8D6ra-htIk1JXYzw,7192
35
35
  mdbq/spider/__init__.py,sha256=RBMFXGy_jd1HXZhngB2T2XTvJqki8P_Fr-pBcwijnew,18
36
36
  mdbq/spider/aikucun.py,sha256=eAIITxnbbxsR_EoohJ78CRw2dEdfSHOltfpxBrh0cvc,22207
37
- mdbq-3.3.15.dist-info/METADATA,sha256=ZoivLw_LLapTkSRtAZGP2xvD8jpaBpX53MrIGKJ_LkQ,244
38
- mdbq-3.3.15.dist-info/WHEEL,sha256=eOLhNAGa2EW3wWl_TU484h7q1UNgy0JXjjoqKoxAAQc,92
39
- mdbq-3.3.15.dist-info/top_level.txt,sha256=2FQ-uLnCSB-OwFiWntzmwosW3X2Xqsg0ewh1axsaylA,5
40
- mdbq-3.3.15.dist-info/RECORD,,
37
+ mdbq-3.4.0.dist-info/METADATA,sha256=5yMS8KxK8EkUCkrPLlPexLMSb2JYk3pVTL5b2S39uME,243
38
+ mdbq-3.4.0.dist-info/WHEEL,sha256=eOLhNAGa2EW3wWl_TU484h7q1UNgy0JXjjoqKoxAAQc,92
39
+ mdbq-3.4.0.dist-info/top_level.txt,sha256=2FQ-uLnCSB-OwFiWntzmwosW3X2Xqsg0ewh1axsaylA,5
40
+ mdbq-3.4.0.dist-info/RECORD,,
File without changes