: param is_count : 是否需要计算collection中的数据数量 : return : 一个公众号是一个collection 返回全部的collection名称

def get_all_nickname(is_count=False):
        """
        :param is_count:是否需要计算collection中的数据数量
        :return: 一个公众号是一个collection 返回全部的collection名称
        """
        nicknames = db_instance.collection_names()
        if is_count is False:
            return nicknames
        else:
            nicknames_count = []
            for nickname in nicknames:
                nicknames_count.append((nickname,count(nickname)))
        return nicknames_count

def get_all_nickname ( is_count = False ) : nicknames = db_instance . collection_names ( ) if is_count is False : return nicknames else : nicknames_count = [ ] for nickname in nicknames : nicknames_count . append ( ( nickname , count ( nickname ) ) ) return nicknames_count


: param nickname : 公众号昵称 : return : 一个公众号的全部文章列表 { title : 公众号名称 articles : [ {} {} {} ] }

def get_all_articles_data(nickname):
    """
    :param nickname:公众号昵称
    :return:一个公众号的全部文章列表
    {'title':'公众号名称','articles':[{},{},{}]}
    """
    use_keys = ['article_id',
                'p_date',
                'read_num',
                'like_num',
                'reward_num',
                'comment_num',
                'author',
                'mov',
                'title',
                'content_url']
    data = {}
    data['title'] = nickname
    data['articles'] = []
    articles = get_collection_article(nickname)
    id_counter = 0
    for article in articles:
        if 'title' not in article:
            continue
        id_counter += 1
        use_data = {}
        # use_data = dict((k, article[k]) for k in use_keys)
        for k in use_keys:
            if k in article:
                use_data[k] = article[k]
            else:
                use_data[k] = '-'
        # 发文时间格式转化
        use_data['p_date'] = use_data['p_date'].strftime("%Y/%m/%d")
        use_data['article_id'] = id_counter
        data['articles'].append(use_data)
    return data


def allStatistic(self):
        '''
        针对主副文章分别做统计，返回的dataframe的collum有两层深度第一层是主副（发文位置）第二层是统计数字
        '''
        # 计算机A各项指标的平均值
        df_move = self.posts_df.groupby('mov')[['read','like','reward','comment']].describe(percentiles=[.5])
        return df_move

def
allStatistic
(
self
)
:
# 计算机A各项指标的平均值
df_move
=
self
.
posts_df
.
groupby
(
'mov'
)
[
[
'read'
,
'like'
,
'reward'
,
'comment'
]
]
.
describe
(
percentiles
=
[
.5
]
)
return
df_move


返回所有主文章的阅读数据 落差指数仅仅针对主文章有意义

返回所有主文章的阅读数据 落差指数仅仅针对主文章有意义

返回所有主文章的阅读数据 落差指数仅仅针对主文章有意义

def allMainDateRead(self):
        '''
        返回所有主文章的阅读数据 落差指数仅仅针对主文章有意义
        '''
        main_posts_df = self.posts_df.loc[self.posts_df['mov']==10][['id','title_cnt','url','date','read','like','comment','reward','deep_index']]
        # 加入上一次文章的阅读量
        main_posts_df['pre_read'] = main_posts_df.read.shift(-1)
        # 落差指数 上次阅读量/本次阅读量*1000
        main_posts_df['fall_index'] = round((main_posts_df['pre_read']/main_posts_df['read'])*1000,2)
        # 按发文时间降序排序
        return main_posts_df.sort_values(by='date',ascending=False)

def
allMainDateRead
(
self
)
:
main_posts_df
=
self
.
posts_df
.
loc
[
self
.
posts_df
[
'mov'
]
==
10
]
[
[
'id'
,
'title_cnt'
,
'url'
,
'date'
,
'read'
,
'like'
,
'comment'
,
'reward'
,
'deep_index'
]
]
# 加入上一次文章的阅读量
main_posts_df
[
'pre_read'
]
=
main_posts_df
.
read
.
shift
(
1
)
# 落差指数 上次阅读量/本次阅读量*1000
main_posts_df
[
'fall_index'
]
=
round
(
(
main_posts_df
[
'pre_read'
]
/
main_posts_df
[
'read'
]
)
*
1000
,
2
)
# 按发文时间降序排序
return
main_posts_df
.
sort_values
(
by
=
'date'
,
ascending
=
False
)


返回各类文章在阅读量上的统计数字 明确50%作为中位数

返回各类文章在阅读量上的统计数字 明确50%作为中位数

返回各类文章在阅读量上的统计数字 明确50%作为中位数

def dirPostsNumRelated(self):
        '''
        返回各类文章在阅读量上的统计数字 明确50%作为中位数
        '''
        dfd = {}
        dfd['mov'] = self.posts_df.groupby('mov').describe(percentiles=[.5])['read']
        dfd['week'] = self.posts_df.groupby('week').describe(percentiles=[.5])['read']
        dfd['hour'] = self.posts_df.groupby('hour').describe(percentiles=[.5])['read']
        return dfd

def dirPostsNumRelated ( self ) : dfd = { } dfd [ 'mov' ] = self . posts_df . groupby ( 'mov' ) . describe ( percentiles = [ .5 ] ) [ 'read' ] dfd [ 'week' ] = self . posts_df . groupby ( 'week' ) . describe ( percentiles = [ .5 ] ) [ 'read' ] dfd [ 'hour' ] = self . posts_df . groupby ( 'hour' ) . describe ( percentiles = [ .5 ] ) [ 'read' ] return dfd


将posts中可能和阅读量有关的所有因素返回,建议使用散点图表示

将posts中可能和阅读量有关的所有因素返回,建议使用散点图表示

将posts中可能和阅读量有关的所有因素返回 建议使用散点图表示

def factorsAndRead(self):
        '''
        将posts中可能和阅读量有关的所有因素返回,建议使用散点图表示
        '''
        main_posts_df = self.posts_df.loc[self.posts_df['mov']==10][['id','read','like','title','pic','video','week','hour']]
        # 加入上一次文章的阅读量
        main_posts_df['pre_read'] = main_posts_df.read.shift(-1)
        # 落差指数 上次阅读量/本次阅读量*1000
        main_posts_df['fall_index'] = round((main_posts_df['pre_read']/main_posts_df['read'])*1000,2)
        return main_posts_df

def
factorsAndRead
(
self
)
:
main_posts_df
=
self
.
posts_df
.
loc
[
self
.
posts_df
[
'mov'
]
==
10
]
[
[
'id'
,
'read'
,
'like'
,
'title'
,
'pic'
,
'video'
,
'week'
,
'hour'
]
]
# 加入上一次文章的阅读量
main_posts_df
[
'pre_read'
]
=
main_posts_df
.
read
.
shift
(
1
)
# 落差指数 上次阅读量/本次阅读量*1000
main_posts_df
[
'fall_index'
]
=
round
(
(
main_posts_df
[
'pre_read'
]
/
main_posts_df
[
'read'
]
)
*
1000
,
2
)
return
main_posts_df


一天中的不同小时段发文数量并不相同 仅仅比较发文总数 和总阅读量无法评估每个小时段对应的单位效果 应该采用该时段的平均阅读量 = 阅读总量 / 发文数量 建议使用条形图展示

def averageHourRead(self):
        '''
        一天中的不同小时段发文数量并不相同,仅仅比较发文总数,和总阅读量无法评估每个小时段对应的单位效果
        应该采用该时段的平均阅读量=阅读总量/发文数量
        建议使用条形图展示
        '''
        return self.posts_df.groupby('hour').describe(percentiles=[.5])['read']

def averageHourRead ( self ) : return self . posts_df . groupby ( 'hour' ) . describe ( percentiles = [ .5 ] ) [ 'read' ]


返回指定字段最高或最低的n行

返回指定字段最高或最低的n行

返回指定字段最高或最低的n行

def getNumN(self,com='read',n=10, asc=0, mov='main'):
        '''
        返回指定字段最高或最低的n行
        '''
        if com == 'fall_index':
            df = self.allMainDateRead()
        else:
            df = self.posts_df
        if mov=='main' and com!='fall_index':df = df.loc[df['mov']==10]
        # 按照阅读量进行降序排序
        df2 = df.sort_values([com],ascending=asc)
        return df2.loc[df2.index[0:n]]

def
getNumN
(
self
,
com
=
'read'
,
n
=
10
,
asc
=
0
,
mov
=
'main'
)
:
if
com
==
'fall_index'
:
df
=
self
.
allMainDateRead
(
)
else
:
df
=
self
.
posts_df
if
mov
==
'main'
and
com
!=
'fall_index'
:
df
=
df
.
loc
[
df
[
'mov'
]
==
10
]
# 按照阅读量进行降序排序
df2
=
df
.
sort_values
(
[
com
]
,
ascending
=
asc
)
return
df2
.
loc
[
df2
.
index
[
0
:
n
]
]


返回指定字段最高或最低的n行

返回指定字段最高或最低的n行

返回指定字段最高或最低的n行

def getNumNExcept(self,com='read',exce=100001,n=10, asc=0, mov='main'):
        '''
        返回指定字段最高或最低的n行
        '''
        df = self.posts_df.loc[self.posts_df[com] != exce]
        if mov=='main':df = df.loc[df['mov']==10]
        # 按照阅读量进行降序排序
        df2 = df.sort_values([com],ascending=asc)
        return df2.loc[df2.index[0:n]]

def
getNumNExcept
(
self
,
com
=
'read'
,
exce
=
100001
,
n
=
10
,
asc
=
0
,
mov
=
'main'
)
:
df
=
self
.
posts_df
.
loc
[
self
.
posts_df
[
com
]
!=
exce
]
if
mov
==
'main'
:
df
=
df
.
loc
[
df
[
'mov'
]
==
10
]
# 按照阅读量进行降序排序
df2
=
df
.
sort_values
(
[
com
]
,
ascending
=
asc
)
return
df2
.
loc
[
df2
.
index
[
0
:
n
]
]


返回指定字段最高或最低的n行

返回指定字段最高或最低的n行

返回指定字段最高或最低的n行

def getNumCondition(self,com='read',thr=100001,dir='==', mov='main'):
        '''
        返回指定字段最高或最低的n行
        '''
        df = self.posts_df
        if mov=='main':df = df.loc[df['mov']==10]
        if dir=='!=':return df.loc[df[com] != thr]
        elif dir=='>=':return df.loc[df[com] >= thr]
        elif dir=='<=':return df.loc[df[com] <= thr]
        elif dir=='>':return df.loc[df[com] > thr]
        elif dir=='<':return df.loc[df[com] < thr]
        else:return df.loc[df[com] == thr]

def getNumCondition ( self , com = 'read' , thr = 100001 , dir = '==' , mov = 'main' ) : df = self . posts_df if mov == 'main' : df = df . loc [ df [ 'mov' ] == 10 ] if dir == '!=' : return df . loc [ df [ com ] != thr ] elif dir == '>=' : return df . loc [ df [ com ] >= thr ] elif dir == '<=' : return df . loc [ df [ com ] <= thr ] elif dir == '>' : return df . loc [ df [ com ] > thr ] elif dir == '<' : return df . loc [ df [ com ] < thr ] else : return df . loc [ df [ com ] == thr ]


返回原始的数据集合 自己编写搜索规则 # 某个属性包含多个值中的一个 df2 . loc [ df2 [ hour ] . isin ( [ 21 20 ] ) ] # 多个条件 df2 . loc [ ( df2 . hour == 21 ) & ( df2 . read > = 20000 ) ] # 指定需要返回的collumes df2 . loc [ ( df2 . hour == 21 ) & ( df2 . read > = 20000 ) [ like hour ]]

def getRwaDatarame(self):
        '''
        返回原始的数据集合,自己编写搜索规则
        # 某个属性包含多个值中的一个
        df2.loc[df2['hour'].isin([21,20])]
        # 多个条件
        df2.loc[(df2.hour==21) & (df2.read>=20000)]
        # 指定需要返回的collumes
        df2.loc[(df2.hour==21) & (df2.read>=20000),['like','hour']]
        '''
        return self.posts_df

def getRwaDatarame ( self ) : return self . posts_df


def __init__(self, nickname):
        """
        :param nickname: 公众号名称
        """
        self.nickname = nickname
        # 生成器转化成为list 赋值给self.posts
        self.posts = []
        self.total_num = 0
        self.crawled_num = 0
        self.uncrawled_num = 0
        for p in get_collection_article(nickname):
            # 过滤掉没有爬取阅读数据的文章
            if 'read_num' in p:
                self.posts.append(p)
                self.crawled_num += 1
            else:
                self.uncrawled_num += 1
            self.total_num += 1
        #
        if self.crawled_num != 0:
            self.gzh = GZH(self.posts)
            self.gzh.postsToDataframe()
            # echarts的option_data
            self.option_data = {}
            # 公众号名称
            self.option_data['account_name'] = nickname
            # 累计发文总数
            self.option_data['posts_info'] = ' 有效文章%d 其中%d具有阅读数据 还剩%d尚无阅读数据'%\
                                                  (self.total_num,self.crawled_num,self.uncrawled_num)

def
__init__
(
self
,
nickname
)
:
self
.
nickname
=
nickname
# 生成器转化成为list 赋值给self.posts
self
.
posts
=
[
]
self
.
total_num
=
0
self
.
crawled_num
=
0
self
.
uncrawled_num
=
0
for
p
in
get_collection_article
(
nickname
)
:
# 过滤掉没有爬取阅读数据的文章
if
'read_num'
in
p
:
self
.
posts
.
append
(
p
)
self
.
crawled_num
+=
1
else
:
self
.
uncrawled_num
+=
1
self
.
total_num
+=
1
#
if
self
.
crawled_num
!=
0
:
self
.
gzh
=
GZH
(
self
.
posts
)
self
.
gzh
.
postsToDataframe
(
)
# echarts的option_data
self
.
option_data
=
{
}
# 公众号名称
self
.
option_data
[
'account_name'
]
=
nickname
# 累计发文总数
self
.
option_data
[
'posts_info'
]
=
' 有效文章%d 其中%d具有阅读数据 还剩%d尚无阅读数据'%\
(
self
.
total_num
,
self
.
crawled_num
,
self
.
uncrawled_num
)


: return : 将公众号表格中需要的数据逐个添加到self . option_data

def _add_option_data(self):
        """
        :return:将公众号表格中需要的数据逐个添加到self.option_data
        """
        # 历史所有文章阅读数据
        df = self.gzh.allMainDateRead()
        all_mian_date_read = draw_all_mian_date_read(df)
        self.option_data['all_mian_date_read'] = all_mian_date_read

        # 主副文章统计数据
        df = self.gzh.allStatistic()
        all_statistic = draw_all_statistic(df)
        self.option_data['all_statistic'] = all_statistic

        # 不同主副/小时/星期类别文章发文数量统计
        dfd = self.gzh.dirPostsNumRelated()
        dir_posts_num_related  = draw_dir_posts_num_related(dfd)
        self.option_data['dir_posts_num_related'] = dir_posts_num_related

        # 阅读量分别和点赞量/上一次阅读量之间的关系
        df = self.gzh.factorsAndRead()
        self.option_data['read_vs_factors'] = draw_read_vs_factors(df)
        # 探索最佳推文小时 推文星期 标题词数 插图数量 视频数量
        self.option_data['find_best_factors'] = draw_find_best_factors(df)

        # 文章列表数据
        self.option_data['table'] = {}
        # 表9 100001除外阅读来那个最高的10篇文章
        df = self.gzh.getNumNExcept(mov='all')
        self.option_data['table']['particular_most_read_10_except_100001'] = df2table(df, ['like','点赞量'])
        # 表10 阅读量最低且为非0的10篇文章
        df = self.gzh.getNumNExcept(com='read', exce=0, asc=1)
        self.option_data['table']['particular_least_read_10_except_0'] = df2table(df, ['like','点赞量'])
        # 表11 深度指数最高的10篇文章.
        df = self.gzh.getNumN(com='deep_index')
        self.option_data['table']['particular_most_deep_10'] = df2table(df, ['deep_index','深度指数'])
        # 表12 深度指数最低的10篇文章
        df = self.gzh.getNumN(com='deep_index', asc=1)
        self.option_data['table']['particular_least_deep_10'] = df2table(df, ['deep_index','深度指数'])
        # 表13 落差指数最低的10篇文章
        df = self.gzh.getNumN(com='fall_index', asc=1)
        self.option_data['table']['particular_least_fall_10'] = df2table(df, ['fall_index','落差指数'])
        # 表14 所有的100001文章
        df = self.gzh.getNumCondition(mov='all')
        self.option_data['table']['particular_all_10001'] = df2table(df, ['like','点赞量'])

def
_add_option_data
(
self
)
:
# 历史所有文章阅读数据
df
=
self
.
gzh
.
allMainDateRead
(
)
all_mian_date_read
=
draw_all_mian_date_read
(
df
)
self
.
option_data
[
'all_mian_date_read'
]
=
all_mian_date_read
# 主副文章统计数据
df
=
self
.
gzh
.
allStatistic
(
)
all_statistic
=
draw_all_statistic
(
df
)
self
.
option_data
[
'all_statistic'
]
=
all_statistic
# 不同主副/小时/星期类别文章发文数量统计
dfd
=
self
.
gzh
.
dirPostsNumRelated
(
)
dir_posts_num_related
=
draw_dir_posts_num_related
(
dfd
)
self
.
option_data
[
'dir_posts_num_related'
]
=
dir_posts_num_related
# 阅读量分别和点赞量/上一次阅读量之间的关系
df
=
self
.
gzh
.
factorsAndRead
(
)
self
.
option_data
[
'read_vs_factors'
]
=
draw_read_vs_factors
(
df
)
# 探索最佳推文小时 推文星期 标题词数 插图数量 视频数量
self
.
option_data
[
'find_best_factors'
]
=
draw_find_best_factors
(
df
)
# 文章列表数据
self
.
option_data
[
'table'
]
=
{
}
# 表9 100001除外阅读来那个最高的10篇文章
df
=
self
.
gzh
.
getNumNExcept
(
mov
=
'all'
)
self
.
option_data
[
'table'
]
[
'particular_most_read_10_except_100001'
]
=
df2table
(
df
,
[
'like'
,
'点赞量'])
# 表10 阅读量最低且为非0的10篇文章
df
=
self
.
gzh
.
getNumNExcept
(
com
=
'read'
,
exce
=
0
,
asc
=
1
)
self
.
option_data
[
'table'
]
[
'particular_least_read_10_except_0'
]
=
df2table
(
df
,
[
'like'
,
'点赞量'])
# 表11 深度指数最高的10篇文章.
df
=
self
.
gzh
.
getNumN
(
com
=
'deep_index'
)
self
.
option_data
[
'table'
]
[
'particular_most_deep_10'
]
=
df2table
(
df
,
[
'deep_index'
,
'深度指数'])
# 表12 深度指数最低的10篇文章
df
=
self
.
gzh
.
getNumN
(
com
=
'deep_index'
,
asc
=
1
)
self
.
option_data
[
'table'
]
[
'particular_least_deep_10'
]
=
df2table
(
df
,
[
'deep_index'
,
'深度指数'])
# 表13 落差指数最低的10篇文章
df
=
self
.
gzh
.
getNumN
(
com
=
'fall_index'
,
asc
=
1
)
self
.
option_data
[
'table'
]
[
'particular_least_fall_10'
]
=
df2table
(
df
,
[
'fall_index'
,
'落差指数'])
# 表14 所有的100001文章
df
=
self
.
gzh
.
getNumCondition
(
mov
=
'all'
)
self
.
option_data
[
'table'
]
[
'particular_all_10001'
]
=
df2table
(
df
,
[
'like'
,
'点赞量'])


: param des_dir : 产生js文件的存储位置 : return : js文件名

def create_js(self):
        """
        :param des_dir:产生js文件的存储位置
        :return:js文件名
        """
        from time import time
        self._add_option_data()
        js_name = 'cache_'+str(time())
        js_file = r"ui/static/auto_created_js/"+js_name+'.js'
        # 打开模板文件
        with open(r'ui/templates/option_data.js','r',encoding='utf8') as f:
            template = Template(f.read())
        # 使用self.option_data渲染js模板文件option_data.js
        option_data_js = template.render(data=self.option_data)
        # 保存渲染后的option_data.js
        with open(js_file,'w',encoding='utf8') as f:
            f.writelines(option_data_js)
        return option_data_js,'auto_created_js/'+js_name+'.js'


attr是表格独自列的英文名称和中文名称 例如 : [ name 名字 ] 英文名称用于索引df 中文名称用于表格标题

def df2table(df, attr):
    '''
    attr是表格独自列的英文名称和中文名称,例如:['name','名字']
    英文名称用于索引df 中文名称用于表格标题
    '''
    table_data = {}
    table_data['attribute'] = attr[1]
    table_data['data'] = []
    id = 0
    for index,row in df.iterrows():
        id += 1
        data_content = {}
        data_content['id'] = id
        # 之所以要使用正则表达式去除标题中的`是因为在js文件中将使用``表示多行字符串
        data_content['title_cnt'] =  re.sub(r'`','',row.title_cnt)
        data_content['url'] = row.url
        data_content['read'] = row.read
        data_content['like'] = row.like
        data_content['date'] = row.date
        if attr[0]!='read' : data_content['attribute'] = row[attr[0]]
        if attr[0]!='like' : data_content['attribute'] = row[attr[0]]
        table_data['data'].append(data_content)
    return table_data


def draw_all_mian_date_read(df):
    """
    :param df:
    :return:所有主文章的阅读数据
    """
    bar = Bar('所有发文历史数据')
    bar.add('阅读量', df['date'], df['read'], mark_line=["min", "max", "average"], is_datazoom_show=True, datazoom_type='both')
    bar.add('点赞量', df['date'], df['like'], mark_line=["min", "max", "average"], is_datazoom_show=True, datazoom_type='both')
    bar.add('评论量', df['date'], df['comment'], mark_line=["min", "max", "average"], is_datazoom_show=True, datazoom_type='both')
    bar.add('赞赏量', df['date'], df['reward'], mark_line=["min", "max", "average"], is_datazoom_show=True, datazoom_type='both')
    bar.add('深度指数', df['date'], df['deep_index'], mark_line=["min", "max", "average"], is_datazoom_show=True, datazoom_type='both')
    return bar.get_echarts_options()

def
draw_all_mian_date_read
(
df
)
:
bar
=
Bar
(
'所有发文历史数据')
bar
.
add
(
'阅读量', df['
d
te
'
], df[
'
r
ad
'
], mar
k
_
ine=["min
"
,
"max
"
"ave
r
ge"], is_
d
a
azoom_show=True,
data
z
om_type='both
'
)
bar
.
add
(
'点赞量', df['
d
te
'
], df[
'
l
ke
'
], mar
k
_
ine=["min
"
,
"max
"
"ave
r
ge"], is_
d
a
azoom_show=True,
data
z
om_type='both
'
)
bar
.
add
(
'评论量', df['
d
te
'
], df[
'
c
mm
e
nt'], mar
k
_
ine=["min
"
,
"max
"
"ave
r
ge"], is_
d
a
azoom_show=True,
data
z
om_type='both
'
)
bar
.
add
(
'赞赏量', df['
d
te
'
], df[
'
r
wa
r
d'], mar
k
_
ine=["min
"
,
"max
"
"ave
r
ge"], is_
d
a
azoom_show=True,
data
z
om_type='both
'
)
bar
.
add
(
'深度指数', df['da
t
']
,
df['d
e
e
_i
n
dex'], mark_
l
i
e=["min",
"
max",
avera
g
"], is_da
t
a
oom_show=True, d
a
tazo
o
_type='both')
return
bar
.
get_echarts_options
(
)


:return:返回当前的所有分类数据, 温和前端的数据格式

:return:返回当前的所有分类数据, 温和前端的数据格式

: return : 返回当前的所有分类数据 温和前端的数据格式

def get_all_cat_data(self):
        """
        :return:返回当前的所有分类数据, 温和前端的数据格式
        """
        category = []
        # 获得数据库中所有公众号的名称为添加选项做准备
        gzh_list = list(get_article_metadata().keys())
        # 获得分类名称和该分类下的所有公众号
        queue = DBQ.get_queue_by_kv(queue_type=self.queue_type)
        for cat in queue:
            data = {}
            data['cat_name'] = cat['name']
            data['cat_members'] = []
            for mem in cat['queue']:
                data['cat_members'].append(mem['id'])
            # 找出不在分类中的公众号作为待加入选项
            # data['cat_available'] = [x for x in gzh_list if x not in data['cat_members']]
            data['cat_available'] = sub_list(gzh_list, data['cat_members'])
            category.append(data)
        return category

# 获得数据库中所有公众号的名称为添加选项做准备

# 获得分类名称和该分类下的所有公众号

# 找出不在分类中的公众号作为待加入选项


:param cat_name:分类名称
        :return: 添加一个分类

:param cat_name:分类名称
        :return: 添加一个分类

: param cat_name : 分类名称 : return : 添加一个分类

def add_cat(self, cat_name):
        """
        :param cat_name:分类名称
        :return: 添加一个分类
        """
        DBQ(cat_name,self.queue_type)
        return self.get_all_cat_data()

def add_cat ( self , cat_name ) : DBQ ( cat_name , self . queue_type ) return self . get_all_cat_data ( )


:param cat_name: 分类名称
        :return:删除一个分类

:param cat_name: 分类名称
        :return:删除一个分类

: param cat_name : 分类名称 : return : 删除一个分类

def delete_cat(self, cat_name):
        """
        :param cat_name: 分类名称
        :return:删除一个分类
        """
        DBQ.delete_queue(cat_name,self.queue_type)
        return self.get_all_cat_data()

def delete_cat ( self , cat_name ) : DBQ . delete_queue ( cat_name , self . queue_type ) return self . get_all_cat_data ( )


: param nickname : 公众号昵称 : param cat_name : 分类名称 : return : 在指定分类中增加一个公众号

def add_cat_gzh(self, nickname, cat_name):
        """
        :param nickname:公众号昵称
        :param cat_name:分类名称
        :return:在指定分类中增加一个公众号
        """
        cat = DBQ(name=cat_name,queue_type=self.queue_type)
        cat.add_element({'id':nickname})
        return self.get_all_cat_data()

def add_cat_gzh ( self , nickname , cat_name ) : cat = DBQ ( name = cat_name , queue_type = self . queue_type ) cat . add_element ( { 'id' : nickname } ) return self . get_all_cat_data ( )


: param nickname : 公众号昵称 : param cat_name : 分类名称 : return : 从指定分类中删除一个公众号

def delete_cat_gzh(self, nickname, cat_name):
        """
        :param nickname:公众号昵称
        :param cat_name: 分类名称
        :return:从指定分类中删除一个公众号
        """
        cat = DBQ(name=cat_name,queue_type=self.queue_type)
        cat.delete_element({'id':nickname})
        return self.get_all_cat_data()

def delete_cat_gzh ( self , nickname , cat_name ) : cat = DBQ ( name = cat_name , queue_type = self . queue_type ) cat . delete_element ( { 'id' : nickname } ) return self . get_all_cat_data ( )


: return : 产生数据报告所有公众号的状态 名称 更新时间 等信息 [ { nickname article_num update_time update_num } {} {} ] report一次需要单独计算机每一个collection中的文档数量 优秀浪费时间 方法待改进

def report_gzh_finished(self):
        """
        :return:产生数据报告所有公众号的状态 名称 更新时间 等信息
        [{nickname,article_num,update_time,update_num}{}{}]
        report一次需要单独计算机每一个collection中的文档数量 优秀浪费时间 方法待改进
        """
        # 获取mongdb中的公众号的状态
        report = {}
        report_data = []
        from db.meta_data import get_article_metadata
        from db import count
        meta_data = get_article_metadata(all=False)
        total_article = 0
        for key in meta_data:
            unit = {}
            unit['nickname'] = key
            unit['article_num'] = count(key)
            unit['update_time'] = meta_data[key]['date'].strftime("%Y/%m/%d %H:%M")
            unit['update_num'] = meta_data[key]['articles_num']
            report_data.append(unit)
            total_article += unit['article_num']
        report['data'] = report_data
        report['meta'] = {}
        report['meta']['total_gzh'] = len(report_data)
        report['meta']['total_article'] = total_article
        return report

def
report_gzh_finished
(
self
)
:
# 获取mongdb中的公众号的状态
report
=
{
}
report_data
=
[
]
from
db
.
meta_data
import
get_article_metadata
from
db
import
count
meta_data
=
get_article_metadata
(
all
=
False
)
total_article
=
0
for
key
in
meta_data
:
unit
=
{
}
unit
[
'nickname'
]
=
key
unit
[
'article_num'
]
=
count
(
key
)
unit
[
'update_time'
]
=
meta_data
[
key
]
[
'date'
]
.
strftime
(
"%Y/%m/%d %H:%M"
)
unit
[
'update_num'
]
=
meta_data
[
key
]
[
'articles_num'
]
report_data
.
append
(
unit
)
total_article
+=
unit
[
'article_num'
]
report
[
'data'
]
=
report_data
report
[
'meta'
]
=
{
}
report
[
'meta'
]
[
'total_gzh'
]
=
len
(
report_data
)
report
[
'meta'
]
[
'total_article'
]
=
total_article
return
report


: return : 产生数据报告正在进行任务的公众号状态 数据来自任务队列 任务队列中存在的公众号和当前正在处理的公众号 nickname percent begin_time need_time

def _report_gzh_doing(self):
        """
        :return:产生数据报告正在进行任务的公众号状态
        数据来自任务队列 任务队列中存在的公众号和当前正在处理的公众号
        nickname,percent,begin_time,need_time
        """
        report_data = []
        from tools.utils import dictstr_to_dict
        # 队列中需要处理的公众号
        gzh_need_todolist = self.gzh_task_rq.get_rq_data()
        for gzh in gzh_need_todolist:
            gzh_task = dictstr_to_dict(gzh)
            unit = {}
            unit['nickname'] = gzh_task['nickname']
            unit['percent'] = 'UNK/UNK'
            unit['begin_time'] = 'UNK'
            unit['need_time'] = 'UNK'
            report_data.append(unit)
        return report_data

def
_report_gzh_doing
(
self
)
:
report_data
=
[
]
from
tools
.
utils
import
dictstr_to_dict
# 队列中需要处理的公众号
gzh_need_todolist
=
self
.
gzh_task_rq
.
get_rq_data
(
)
for
gzh
in
gzh_need_todolist
:
gzh_task
=
dictstr_to_dict
(
gzh
)
unit
=
{
}
unit
[
'nickname'
]
=
gzh_task
[
'nickname'
]
unit
[
'percent'
]
=
'UNK/UNK'
unit
[
'begin_time'
]
=
'UNK'
unit
[
'need_time'
]
=
'UNK'
report_data
.
append
(
unit
)
return
report_data


:return:当前可能并未任务

:return:当前可能并未任务

: return : 当前可能并未任务

def report_gzh_doing(self):
        """
        :return:当前可能并未任务
        """
        try:
            report_data = self._report_gzh_doing()
        except:
            report_data = []
        return report_data

def report_gzh_doing ( self ) : try : report_data = self . _report_gzh_doing ( ) except : report_data = [ ] return report_data


def add_crawler(self,crawler):
        """
        :param self:
        :return:添加爬虫
        """
        self.phone_adb_dbq.add_element({'id':crawler['phone'],'nick_name':'未知','wxuin':'未知'})

def add_crawler ( self , crawler ) : self . phone_adb_dbq . add_element ( { 'id' : crawler [ 'phone' ] , 'nick_name' : '未知','wx u in':'未知 ' })


def delete_crawler(self,crawler):
        """
        :param crawler:
        :return:删除爬虫
        """
        print(crawler)
        self.phone_adb_dbq.delete_element({'id':crawler['phone']})

def delete_crawler ( self , crawler ) : print ( crawler ) self . phone_adb_dbq . delete_element ( { 'id' : crawler [ 'phone' ] } )


: param num : 日志条数 : param item : { nickname : ** percent : 12 / 1231 speed : 0 . 023 title : *** } : return :

def report_crawling(self,item,num=15):
        """
        :param num: 日志条数
        :param item:{'nickname':**,'percent':'12/1231','speed':0.023,'title':'***'}
        :return:
        """
        from ui.ui_instance import socketio
        self.report_crawling_items = [item] + self.report_crawling_items
        if len(self.report_crawling_items)>num:
            self.report_crawling_items.pop()
        socketio.emit('articles_logger_monitoring',self.report_crawling_items)
        return self.report_crawling_items

def report_crawling ( self , item , num = 15 ) : from ui . ui_instance import socketio self . report_crawling_items = [ item ] + self . report_crawling_items if len ( self . report_crawling_items ) > num : self . report_crawling_items . pop ( ) socketio . emit ( 'articles_logger_monitoring' , self . report_crawling_items ) return self . report_crawling_items


def add_gzh(self,gzh):
        """
        :param gzh:
        :return:添加公众号 到任务队列
        """
        self.gzh_task_rq.push(gzh)

def add_gzh ( self , gzh ) : self . gzh_task_rq . push ( gzh )


def delete_gzh(self,gzh):
        """
        :param gzh:
        :return:删除公众号
        """
        pass


def update_gzh(self,gzh,n):
        """
        :param gzh:
        :return: 更新公众号文章
        """
        pass

def update_gzh ( self , gzh , n ) : pass


:param gzh:
        :return:生成公众号历史文章数据报告

:param gzh:
        :return:生成公众号历史文章数据报告

def gzh_report(self,gzh):
        """
        :param gzh:
        :return:生成公众号历史文章数据报告
        """
        pass


:param gzh:
        :return: 生成公众号的所有文章列表

:param gzh:
        :return: 生成公众号的所有文章列表

def gzh_article_list(self,gzh):
        """
        :param gzh:
        :return: 生成公众号的所有文章列表
        """
        pass

def gzh_article_list ( self , gzh ) : pass


: param gzh : : param field : : return : 公众号的指定字段到处到excel

def export_excel(self,gzh,field):
        """
        :param gzh:
        :param field:
        :return:公众号的指定字段到处到excel
        """
        pass

def export_excel ( self , gzh , field ) : pass


: return : 新加入的爬虫每当接到文章爬取任时就会自动获取请求参数 公众号爬虫的整个生命周期中都需要有一个后台进程监控公众的的爬取任务和更新任务 run需要在一个进程中不停执行

def run(self):
        """
        :return:新加入的爬虫每当接到文章爬取任时就会自动获取请求参数
        公众号爬虫的整个生命周期中都需要有一个后台进程监控公众的的爬取任务和更新任务
        run需要在一个进程中不停执行
        """
        # 爬取任务
        from tools.utils import dictstr_to_dict
        gzh_task = self.gzh_task_rq.pop()
        if gzh_task == []:
            return
        gzh_task = dictstr_to_dict(gzh_task)
        self.gzh_in_service = gzh_task['nickname']
        print(gzh_task)
        # 获取参数
        adb_ports_raw = self.phone_adb_dbq.get_queue()
        adb_ports = []
        for adb in adb_ports_raw:
            adb_ports.append(adb['id'])
        wo = WeixinOperate(adb_ports)
        if gzh_task['aom'] == 'halfauto':
            wo.get_all_req_data(gzh_task['nickname'], hand=True)
        elif gzh_task['aom'] == 'auto':
            wo.get_all_req_data(gzh_task['nickname'], hand=False)
        # 调用爬虫
        from crawler import run_crawl
        config = int(gzh_task['range'])
        # from os import system
        # system('python run_crawler.py '+str(config))
        run_crawl(config)


获取redis中所有的请求文件，也就是key中含有 . req字段的记录。最终返回的数据根据key中的时间戳进行排序过 : return : ｛ 1532859863455 . getappmsgext . req : dict_file ) 1523423421446 . appmsg_comment . req : dict_file｝

def get_all_req_data():
        """
        获取redis中所有的请求文件，也就是key中含有.req字段的记录。最终返回的数据根据key中的时间戳进行排序过
        :return:
        ｛'1532859863455.getappmsgext.req':dict_file,)
          '1523423421446.appmsg_comment.req':dict_file｝
        """
        unordered_req_dict = {}
        ordered_req_dict = collections.OrderedDict()
        # 遍历所有的请求文件
        for key in redis_instance.keys("*.req"):
            req_bin_data = redis_instance.get(key)
            try:
                req_dict_data = json.loads(req_bin_data)
            except:
                req_dict_data = str(req_bin_data)
                # req_dict_data = req_bin_data.decode('utf8')
            unordered_req_dict[key.decode('utf8')] = req_dict_data
        # 按照时间顺序排序之后返回字典
        for key in sorted(unordered_req_dict.keys()):
            ordered_req_dict[key] = unordered_req_dict[key]
        return ordered_req_dict

# 按照时间顺序排序之后返回字典


: param ordered_req_dict : : return : 添加nick_name

def add_nick_name(ordered_req_dict):
        """
        :param ordered_req_dict:
        :return:添加nick_name
        """
        wxuin_nn_dict = {}
        nickname = TidyReqData.get_nickname()
        for key in redis_instance.keys("*.nick_name"):
            wxuin_nn_dict[(redis_instance.get(key)).decode('utf8')] = (key.decode('utf8')).split('.')[0]
        for key in ordered_req_dict:
            ordered_req_dict[key]['nick_name'] = wxuin_nn_dict[key]
            ordered_req_dict[key]['wxuin'] = key
            ordered_req_dict[key]['nickname'] = nickname
        return ordered_req_dict

def add_nick_name ( ordered_req_dict ) : wxuin_nn_dict = { } nickname = TidyReqData . get_nickname ( ) for key in redis_instance . keys ( "*.nick_name" ) : wxuin_nn_dict [ ( redis_instance . get ( key ) ) . decode ( 'utf8' ) ] = ( key . decode ( 'utf8' ) ) . split ( '.' ) [ 0 ] for key in ordered_req_dict : ordered_req_dict [ key ] [ 'nick_name' ] = wxuin_nn_dict [ key ] ordered_req_dict [ key ] [ 'wxuin' ] = key ordered_req_dict [ key ] [ 'nickname' ] = nickname return ordered_req_dict


: param req_dic : : return : 找出一个手机 ( 账号 ) 产生的最新请求信息 ｛ wxuin1 : { load_more : { update_time : 1532859858625 req_data : { ... }} content : { update_time : 1532859858625 req_data : { ... }} getappmsgext : { update_time : 1532859858625 req_data : { ... }} appmsg_comment : { update_time : 1532859858625 req_data : { ... }}} wxuin2 : { load_more : { update_time : 1532859858625 req_data : { ... }} content : { update_time : 1532859858625 req_data : { ... }} getappmsgext : { update_time : 1532859858625 req_data : { ... }} appmsg_comment : { update_time : 1532859858625 req_data : { ... }}} }

def combine(req_dic):
        """
        :param req_dic:
        :return: 找出一个手机(账号)产生的最新请求信息
        ｛
        'wxuin1':{
            'load_more':{'update_time':'1532859858625','req_data':{...}},
            'content':{'update_time':'1532859858625','req_data':{...}},
            'getappmsgext':{'update_time':'1532859858625','req_data':{...}},
            'appmsg_comment':{'update_time':'1532859858625','req_data':{...}}},
        'wxuin2':{
            'load_more':{'update_time':'1532859858625','req_data':{...}},
            'content':{'update_time':'1532859858625','req_data':{...}},
            'getappmsgext':{'update_time':'1532859858625','req_data':{...}},
            'appmsg_comment':{'update_time':'1532859858625','req_data':{...}}},
        }
        """
        tidy_req_dic = {}
        # 建立手机型号索引
        for key in req_dic:
            wxuin = TidyReqData.get_wxuin(req_dic[key])
            if wxuin=="NOT_WEIXIN":
                continue
            tidy_req_dic[wxuin] = {}

        # 为每个wxuin下的数据预留数据类型
        for wxuin in tidy_req_dic:
            tidy_req_dic[wxuin] = {}
        # 组织all_req_data数据
        for key in req_dic:
            key_info = key.split('.')
            # 获取一次请求数据中的元信息
            timestamp = int(key_info[0])
            _type = key_info[1]
            wxuin = TidyReqData.get_wxuin(req_dic[key])
            if wxuin=="NOT_WEIXIN":
                continue
            req_data = req_dic[key]

            # 构造一部手机的模拟请求数据结构
            # 重点关注的是all_req_data部分
            all_req_data = tidy_req_dic[wxuin]
            # 该种类型的请求数据尚未出现
            if _type not in all_req_data:
                all_req_data[_type] = {}
                all_req_data[_type]['update_time'] = timestamp
                all_req_data[_type]['req_data'] = req_data
            # 该种类型的请求数据已经存在根据timetamp和update_time的对比确定是否需要覆盖
            else:
                if timestamp > all_req_data[_type]['update_time']:
                    all_req_data[_type]['update_time'] = timestamp
                    all_req_data[_type]['req_data'] = req_data
        return tidy_req_dic

# 为每个wxuin下的数据预留数据类型

# 获取一次请求数据中的元信息

# 构造一部手机的模拟请求数据结构

# 该种类型的请求数据尚未出现


对redis中的请求数据整理归纳，找出每台手机最新的请求数据 : param redis : redis实例 db必须和proxy server存放的db相同 : return : 数据格式见combine 一方面返回字典另一方方面存入redis 并且增加属性 update_time

def tidy():
        """
        对redis中的请求数据整理归纳，找出每台手机最新的请求数据
        :param redis:redis实例 db必须和proxy server存放的db相同
        :return:数据格式见combine 一方面返回字典另一方方面存入redis 并且增加属性 'update_time'
        """
        tidy_req_data = TidyReqData.get_all_req_data()
        tidy_req_data = TidyReqData.combine(tidy_req_data)
        tidy_req_data = TidyReqData.add_nick_name(tidy_req_data)
        redis_instance.set('tidy_req_data',tidy_req_data)
        return tidy_req_data

def tidy ( ) : tidy_req_data = TidyReqData . get_all_req_data ( ) tidy_req_data = TidyReqData . combine ( tidy_req_data ) tidy_req_data = TidyReqData . add_nick_name ( tidy_req_data ) redis_instance . set ( 'tidy_req_data' , tidy_req_data ) return tidy_req_data


: param req : : return : 从redis中一个一条req记录中提取wxuin 用于识别不同的微信账号

def get_wxuin(req):
        """
        :param req:
        :return:从redis中一个一条req记录中提取wxuin 用于识别不同的微信账号
        """
        try:
            cookie_string = req["requestOptions"]["headers"]["Cookie"]
        except:
            return "NOT_WEIXIN"
        try:
            wxuin = re.findall(r'wxuin=\S*?;', cookie_string)[0][6:-1]
        except:
            wxuin = cookie_string.split('wxuin=')[-1]
        return wxuin

def get_wxuin ( req ) : try : cookie_string = req [ "requestOptions" ] [ "headers" ] [ "Cookie" ] except : return "NOT_WEIXIN" try : wxuin = re . findall ( r'wxuin=\S*?;' , cookie_string ) [ 0 ] [ 6 : - 1 ] except : wxuin = cookie_string . split ( 'wxuin=' ) [ - 1 ] return wxuin


: param names : 可使用通配符格式的key表达式比如 * . req : return : 删除redis中的热情数据

def flush_data(names=None):
        """
        :param names:可使用通配符格式的key表达式比如 *.req
        :return: 删除redis中的热情数据
        """
        if names==None:
            for key in redis_instance.keys():
                redis_instance.delete(key)
        for key in redis_instance.keys(names):
            redis_instance.delete(key)

def flush_data ( names = None ) : if names == None : for key in redis_instance . keys ( ) : redis_instance . delete ( key ) for key in redis_instance . keys ( names ) : redis_instance . delete ( key )


: param raw_req_data : _type [ req_data ] 它只是5种请求数据的一种 : return : 将anyproxy获取的req文件内容解析成为request参数所需要的字典

def req_to_dict(raw_req_data):
        """
        :param raw_req_data:_type['req_data'] 它只是5种请求数据的一种
        :return:将anyproxy获取的req文件内容解析成为request参数所需要的字典
        """
        req_data = {}
        url_lsit = raw_req_data['url'].split('?')
        url = url_lsit[0]+'?'
        req_data['url'] = url
        req_data['method'] = raw_req_data['requestOptions']['method']
        req_data['headers'] = raw_req_data['requestOptions']['headers']
        body_str = raw_req_data['requestData']
        body_dict = str_to_dict(body_str, "&", "=")
        url_param_str = url_lsit[1]
        url_param_dict = str_to_dict(url_param_str, "&", "=")
        req_data['body_dict'] = body_dict
        req_data['url_param_dict'] = url_param_dict
        # 添加一个测试字段
        req_data['url_param_str'] = url_param_str
        return req_data

def
req_to_dict
(
raw_req_data
)
:
req_data
=
{
}
url_lsit
=
raw_req_data
[
'url'
]
.
split
(
'?'
)
url
=
url_lsit
[
0
]
+
'?'
req_data
[
'url'
]
=
url
req_data
[
'method'
]
=
raw_req_data
[
'requestOptions'
]
[
'method'
]
req_data
[
'headers'
]
=
raw_req_data
[
'requestOptions'
]
[
'headers'
]
body_str
=
raw_req_data
[
'requestData'
]
body_dict
=
str_to_dict
(
body_str
,
"&"
,
"="
)
url_param_str
=
url_lsit
[
1
]
url_param_dict
=
str_to_dict
(
url_param_str
,
"&"
,
"="
)
req_data
[
'body_dict'
]
=
body_dict
req_data
[
'url_param_dict'
]
=
url_param_dict
# 添加一个测试字段
req_data
[
'url_param_str'
]
=
url_param_str
return
req_data


:return:返回为一个公众号准备的所有请求数据

:return:返回为一个公众号准备的所有请求数据

: return : 返回为一个公众号准备的所有请求数据

def get_gzh_req_data():
        """
        :return:返回为一个公众号准备的所有请求数据
        """
        # 所有请求参数字典格式 使用wxuin作为key
        req_data_dict = TidyReqData.tidy()
        # 所有请求参数list格式 方便按照顺序依次使用各个微信的请求参数
        req_data_list = []
        for key in req_data_dict:
                req_data_list.append(req_data_dict[key])
        # 可用请求参数微信数量
        wx_num = len(req_data_list)
        return wx_num, req_data_dict, req_data_list

def
get_gzh_req_data
(
)
:
# 所有请求参数字典格式 使用wxuin作为key
req_data_dict
=
TidyReqData
.
tidy
(
)
# 所有请求参数list格式 方便按照顺序依次使用各个微信的请求参数
req_data_list
=
[
]
for
key
in
req_data_dict
:
req_data_list
.
append
(
req_data_dict
[
key
]
)
# 可用请求参数微信数量
wx_num
=
len
(
req_data_list
)
return
wx_num
,
req_data_dict
,
req_data_list


: param r : html字符串 : return : 解析文章html 文章html中包含的信息非常丰富 不仅仅只有文章文本等基本数据还有comment_id video_num pic_num 还有原文的markdown信息

def decode_content(r):
        """
        :param r:html字符串
        :return:解析文章html
        文章html中包含的信息非常丰富 不仅仅只有文章文本等基本数据还有comment_id
        video_num pic_num 还有原文的markdown信息
        """
        data = {}
        r_data = r
        data['video_num'] = len(re.findall(REG_VIDEO_NUM, r_data))
        data['pic_num'] = len(re.findall(REG_PIC_NUM, r_data))
        data['comment_id'] = re.findall(REG_COMMENT_ID, r_data)
        if len(data['comment_id'])==1:data['comment_id']=data['comment_id'][0].split('"')[1]
        else:data['comment_id'] = str(0)
        r_data = DecodeArticle.part_of_html(r_data)
        try:
            data['article'] = html_to_text.handle(r_data)
        except Exception as e:
            try:
                data['article'] = html_to_text.handle(r)
            except:
                data['article'] = ""
        return data

def decode_content ( r ) : data = { } r_data = r data [ 'video_num' ] = len ( re . findall ( REG_VIDEO_NUM , r_data ) ) data [ 'pic_num' ] = len ( re . findall ( REG_PIC_NUM , r_data ) ) data [ 'comment_id' ] = re . findall ( REG_COMMENT_ID , r_data ) if len ( data [ 'comment_id' ] ) == 1 : data [ 'comment_id' ] = data [ 'comment_id' ] [ 0 ] . split ( '"' ) [ 1 ] else : data [ 'comment_id' ] = str ( 0 ) r_data = DecodeArticle . part_of_html ( r_data ) try : data [ 'article' ] = html_to_text . handle ( r_data ) except Exception as e : try : data [ 'article' ] = html_to_text . handle ( r ) except : data [ 'article' ] = "" return data


: param x_path : xpath表达式默认获取微信公众号的正文xpath : param raw_html : r . text : return : 截取html的一部分

def part_of_html(raw_html,x_path=r'//div[@id="js_content"]'):
        """
        :param x_path:xpath表达式默认获取微信公众号的正文xpath
        :param raw_html:r.text
        :return: 截取html的一部分
        """
        from lxml import html
        tree = html.fromstring(raw_html)
        data = tree.xpath(x_path)
        if len(data) == 1:
            data = tostring(data[0], encoding='unicode')
            return data
        else:
            return raw_html

def part_of_html ( raw_html , x_path = r'//div[@id="js_content"]' ) : from lxml import html tree = html . fromstring ( raw_html ) data = tree . xpath ( x_path ) if len ( data ) == 1 : data = tostring ( data [ 0 ] , encoding = 'unicode' ) return data else : return raw_html


: param response : 请求返回的response : return : 提取历史文章列表信息并且分类主副 主文章是一次推送的头条消息用10表示 其余文章从11开始表示 r [ r ] [ data ] : title digest content_url source_url cover author mov p_date id r [ r ] [ des ] : can_msg_continue next_offset

def decode_load_more(response):
        """
        :param response:请求返回的response
        :return:提取历史文章列表信息并且分类主副 主文章是一次推送的头条消息用10表示 其余文章从11开始表示
            r['r']['data']: title,digest,content_url,source_url,cover,author,mov,p_date,id
            r['r']['des']: can_msg_continue,next_offset
        """
        use_data = dict()
        use_data['data'] = []
        use_data['des'] = {}
        use_data['id'] = 0

        data = json.loads(response.body_as_unicode())
        # 添加本次获取列表之后是否可以继续以及下一个offset
        use_data['des']['can_msg_continue'] = data['can_msg_continue']
        use_data['des']['next_offset'] = data['next_offset']
        # 遍历消息列表
        data = DecodeArticleList.general_msg_list_to_list(data.get('general_msg_list'))
        # 解析消息列表
        for msg in data:
            p_date = msg.get("comm_msg_info").get("datetime")
            msg_info = msg.get("app_msg_ext_info")  # 非图文消息没有此字段
            if msg_info:
                mov = 10
                msg_info['mov'] = str(mov)
                DecodeArticleList._insert(use_data, msg_info, p_date)
                multi_msg_info = msg_info.get("multi_app_msg_item_list")
                for msg_item in multi_msg_info:
                    mov += 1
                    msg_item['mov'] = str(mov)
                    DecodeArticleList._insert(use_data, msg_item, p_date)
            else:
                logger.warning(u"此消息不是图文推送，data=%s" % json.dumps(msg.get("comm_msg_info")))
        use_data.pop('id')
        return use_data

# 添加本次获取列表之后是否可以继续以及下一个offset

# 非图文消息没有此字段


文章列表信息插入use_data

文章列表信息插入use_data

文章列表信息插入use_data

def _insert(use_data, item, p_date):
        '''
        文章列表信息插入use_data
        '''
        use_data['id'] += 1
        keys = ('title', 'author', 'content_url', 'digest', 'cover', 'source_url','mov')
        sub_data = DecodeArticleList.sub_dict(item, keys)
        p_date = datetime.fromtimestamp(p_date)
        sub_data["p_date"] = p_date
        use_data['data'].append(sub_data)
        logger.info('%d %s %s'%(use_data["id"],sub_data["mov"], sub_data["title"]))

def
_insert
(
use_data
,
item
,
p_date
)
:
use_data
[
'id'
]
+=
1
keys
=
(
'title'
,
'author'
,
'content_url'
,
'digest'
,
'cover'
,
'source_url'
,
'mov'
)
sub_data
=
DecodeArticleList
.
sub_dict
(
item
,
keys
)
p_date
=
datetime
.
fromtimestamp
(
p_date
)
sub_data
[
"p_date"
]
=
p_date
use_data
[
'data'
]
.
append
(
sub_data
)
logger
.
info
(
'%d %s %s'
%
(
use_data
[
"id"
]
,
sub_data
[
"mov"
]
,
sub_data
[
"title"
]
)
)