zl程序教程

您现在的位置是:首页 >  云平台

当前栏目

cnblogs_client博客园客户端——雏形

客户端 Client 博客园 cnblogs 雏形
2023-09-14 09:00:34 时间

一、背景

博客园后台管理中,每页只能显示10篇文章的管理信息,如果想按照文章阅读量排序,根本就不可能。

 

二、分析方案

1、python爬虫requests获取后台页面中的所有文章管理数据。

2、导入电子表格Excel进行排序查看。

 

三、实现代码

1、cookie值的获取方法:

(1)打开谷歌浏览器Chrome,
(2)访问博客园并且登录账号,
(3)选择“新随笔”进入后台管理页面,
(4)再按下F12键,弹窗新的浏览器窗口工具,在窗口工具中选择“network”,以后注意观察,
(5)再点击“随笔”,
(6)此时观察到窗口工具中的特殊情况,如图:

 

 cookie值的替换样式:

'cookie': 'xxx',

注意:
(1)cookie就是你的密码信息,不要告诉他人或发布到文章中;
(2)xxx表示你的全部cookie值;
(3)cookie要用英文状态下的单引号括起来。

 

2、python代码如下。注意:'cookie': 0,要修改为正确的值。

安装python3
python -V # 验证python3是否安装成功
安装pip3
pip -V # 验证pip3是否安装成功
安装依赖包
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple requests
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple openpyxl

python源码(注意记得替换源码中的cookie值)

import time
import json
import math
import requests
import sys
import os

from openpyxl import Workbook

# 启动前输出
version_str = "V1.0"
logo_str = "cnBlogs_List"
logo_pic_str = """
            ____  _                           _     _     _   
  ___ _ __ | __ )| | ___   __ _ ___          | |   (_)___| |_ 
 / __| '_ \|  _ \| |/ _ \ / _` / __|         | |   | / __| __|
| (__| | | | |_) | | (_) | (_| \__ \         | |___| \__ \ |_ 
 \___|_| |_|____/|_|\___/ \__, |___/  _____  |_____|_|___/\__|
                          |___/      |_____|                  
"""
print("%s %s" % (logo_str, version_str), end='')
print(logo_pic_str)
print("%s %s 启动中..." % (logo_str, version_str))
time.sleep(3)

# 开始启动
# 配置
# 方式一:直接赋值给常量COOKIE_STR
# cookie值
COOKIE_STR = ""
# 方式二:将cookie值存到一个指定的文件
COOKIE_PATH = "./mycookie.txt"
if os.path.exists(COOKIE_PATH) and len(COOKIE_STR) == 0:
    # 如果存在cookie存值文件,且没有对系统常量cookie赋值,则读取文件中的内容
    with open(COOKIE_PATH, 'r', encoding="utf-8") as f:
        data_str = f.read()
        if len(data_str) > 1:
            # 如果存在文件内容,则向系统赋值cookie常量
            COOKIE_STR = data_str
        else:
            print("There is no cookie value in the file %s" % COOKIE_PATH)
            sys.exit()
# sys.exit()
CACHE_FILE_NAME = "cache.txt"  # 缓存文件名称
EXCEL_FILE_NAME = "result.xls"  # 电子表格文件名称
WORKSHEET_NAME = "cnblogs_admin"  # 工作簿名称
# TABLE_HEAD_TITLE_LIST = ["title", "viewCount", "url", "comment_count", "datePublished", "dateUpdated"]  # 表头名称
TABLE_HEAD_TITLE_LIST = ["标题", "阅读量", "链接", "评论数", "首次发布时间", "最近更新时间"]  # 表头名称
SINGLE_PAGE_COUNT = 10  # 每页文章数目


# 定义函数
def get_data(page_n=1):
    page_num = page_n

    url = r'https://i-beta.cnblogs.com/api/posts/list?p=%s&cid=&t=1&cfg=0' % page_num
    headers = {
        'authority': 'i-beta.cnblogs.com',
        'method': 'GET',
        'path': '/api/posts/list?p=1&cid=&t=1&cfg=0',
        'scheme': 'https',
        'accept': 'application/json, text/plain, */*',
        'accept-encoding': 'gzip, deflate, br',
        'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8',
        'cookie': COOKIE_STR,
        'referer': 'https://i-beta.cnblogs.com/posts',
        'sec-fetch-dest': 'empty',
        'sec-fetch-mode': 'cors',
        'sec-fetch-site': 'same-origin',
        'user-agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36',
        'x-blog-id': '158654'}

    # 发起get请求
    response = requests.get(url, headers=headers, verify=True)
    html_data = response.content.decode()
    data_dict = json.loads(html_data)
    post_list = data_dict["postList"]  # 获取页面内容
    all_post_count = data_dict["postsCount"]  # 获取总文章数目
    page_count = math.ceil(all_post_count / 10)  # 获取总页数

    if page_n == 1:
        print("【code %s】第 %s 页:首页请求2遍,一遍获取总页数,另一遍获取首页数据写入文件" % (response.status_code, page_n))
    else:
        print("【code %s】第 %s 页" % (response.status_code, page_n))

    info_result = []  # 写入表格的数据
    # 写入首行
    if page_num == 1:
        info = TABLE_HEAD_TITLE_LIST  # 首行内容
        info_result.append(info)

    # 获取当页内容
    for index, item in enumerate(post_list):
        title = item['title']  # 获取标题
        viewCount = item['viewCount']  # 获取点击量
        url = "https:%s" % item['url']  # 获取文章url
        comment_count = item['feedBackCount']  # 获取评论数量
        datePublished = item['datePublished']  # 获取首次发布日期
        dateUpdated = item['dateUpdated']  # 获取最近修改日期
        print((index + ((page_n - 1) * SINGLE_PAGE_COUNT) + 1), end='  ')
        print(title)
        # print(viewCount)
        # print(url)
        # print(comment_count)
        # print("首发日期:", datePublished)
        # print("修改日期:", dateUpdated)
        # print()

        info = [title, viewCount, url, comment_count, datePublished, dateUpdated]  # 每行的内容
        info_result.append(info)

    return page_count, page_num, info_result


# 启动测试
if __name__ == '__main__':
    info_result_all = []  # 所有页面的数据汇总列表
    try:
        page_count = int(get_data()[0])  # 获取总页面数。请求一次第一页。
    except Exception:
        print("请求无效,请替换为新Cookie值(COOKIE_STR)后重试")
        sys.exit()

    # 遍历所有页面
    # for n in range(1, page_count + 1):
    for n in range(1, 2 + 1):
        time.sleep(1)  # 休息一秒钟,降低请求频率
        one_page_data_list = get_data(n)  # 请求一次第n页
        page_count = one_page_data_list[0]
        page_num = one_page_data_list[1]
        info_result = one_page_data_list[2]

        info_result_all.extend(info_result)

        # 将本页面数据写入缓存文件
        save_file_cache = CACHE_FILE_NAME
        with open(save_file_cache, 'a', encoding="utf-8") as f:
            f.write("## 第 %s 页\n" % page_num)  # 缓存页面号
            for line in info_result:
                f.write("%s\t%s\t%s\t%s\t%s\t%s\n" % tuple(line))  # 本页内容写入缓存

    # 最后:将数据写入excel
    save_file = EXCEL_FILE_NAME  # 存入文件名称
    sheet_name = WORKSHEET_NAME  # 工作簿名称
    wb = Workbook()  # 新建工作簿
    ws1 = wb.active  # 获得当前活跃的工作页,默认为第一个工作页
    ws1.title = sheet_name  # 修改页名称。sheet名称
    for row in info_result_all:
        ws1.append(row)
    wb.save(save_file)  # Excel文件名称,保存文件

  

3、运行后:

 4、Excel排序后

 

 v1.3版

新增:

1、存mysql数据

2、sql建库建表

3、已存mysql的不再重复存入,url作为唯一标识。

py文件代码:

import time
import json
import math
import requests
import sys
import os

from openpyxl import Workbook
import pymysql

# 启动前输出
version_str = "V1.3"
logo_str = "cnBlogs_List"
logo_pic_str = """
            ____  _                           _     _     _  
  ___ _ __ | __ )| | ___   __ _ ___          | |   (_)___| |_
 / __| '_ \|  _ \| |/ _ \ / _` / __|         | |   | / __| __|
| (__| | | | |_) | | (_) | (_| \__ \         | |___| \__ \ |_
 \___|_| |_|____/|_|\___/ \__, |___/  _____  |_____|_|___/\__|
                          |___/      |_____|                 
"""
print("%s %s" % (logo_str, version_str), end='')
print(logo_pic_str)
print("%s %s 启动中..." % (logo_str, version_str))
time.sleep(2.5)

# 开始启动
# 配置
# 方式一:直接赋值给常量COOKIE_STR
# cookie值
COOKIE_STR = ""
# 方式二:将cookie值存到一个指定的文件
COOKIE_PATH = "./mycookie.txt"
if os.path.exists(COOKIE_PATH) and len(COOKIE_STR) == 0:
    # 如果存在cookie存值文件,且没有对系统常量cookie赋值,则读取文件中的内容
    with open(COOKIE_PATH, 'r', encoding="utf-8") as f:
        data_str = f.read()
        if len(data_str) > 0:
            # 如果存在文件内容,则向系统赋值cookie常量
            COOKIE_STR = data_str
        else:
            print("There is no cookie value in the file %s" % COOKIE_PATH)
            sys.exit()
# sys.exit()
CACHE_FILE_NAME = "cache.txt"  # 缓存文件名称
EXCEL_FILE_NAME = "result.xls"  # 电子表格文件名称
WORKSHEET_NAME = "cnblogs_admin"  # 工作簿名称
# TABLE_HEAD_TITLE_LIST = ["title", "countView", "countCommet", "url", "datePublished", "dateUpdated"]  # 表头名称
TABLE_HEAD_TITLE_LIST = ["标题", "阅读量", "评论数", "链接", "首次发布时间", "最近更新时间"]  # *.xls或cache.txt表头名称
SINGLE_PAGE_COUNT = 10  # 每页文章数目

# 配置请求参数
REQUEST_URL_PART = r'https://i-beta.cnblogs.com/api/posts/list?p=%s&cid=&t=1&cfg=0'
REQUEST_HEADERS = {
    'authority': 'i-beta.cnblogs.com',
    'method': 'GET',
    'path': '/api/posts/list?p=1&cid=&t=1&cfg=0',
    'scheme': 'https',
    'accept': 'application/json, text/plain, */*',
    'accept-encoding': 'gzip, deflate, br',
    'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8',
    'cookie': COOKIE_STR,
    'referer': 'https://i-beta.cnblogs.com/posts',
    'sec-fetch-dest': 'empty',
    'sec-fetch-mode': 'cors',
    'sec-fetch-site': 'same-origin',
    'user-agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36',
}

# 全局变量
info_result_all = []  # 所有页面的数据汇总列表

# 配置mysql数据库连接参数
MYSQL_HOST = 'localhost'
MYSQL_PORT = 3306
MYSQL_USER = 'root'
MYSQL_PASSWD = 'root'
MYSQL_DB = 'cbs'
MYSQL_CHARSET = 'utf8'

# 连接数据库
connect = pymysql.Connect(
    host=MYSQL_HOST,
    port=MYSQL_PORT,
    user=MYSQL_USER,
    passwd=MYSQL_PASSWD,
    db=MYSQL_DB,
    charset=MYSQL_CHARSET
)
# 获取游标
cursor = connect.cursor()


# 定义函数
# 获取总页数
def get_page_count(page_n=1):
    page_num = page_n
    # 构造请求参数
    url = REQUEST_URL_PART % page_num
    headers = REQUEST_HEADERS
    # 发起get请求
    response = requests.get(url, headers=headers, verify=True)
    html_data = response.content.decode()
    data_dict = json.loads(html_data)
    all_post_count = data_dict["postsCount"]  # 获取总文章数目
    page_count = math.ceil(all_post_count / 10)  # 获取总页数
    # 返回总页数
    return page_count


# 请求每个列表页的数据
# 1、打印到控制台
# 2、存入mysql数据库cbs中article_list表中
def get_per_page_data(page_n=1, save_mysql=True):
    page_num = page_n

    url = REQUEST_URL_PART % page_num
    headers = REQUEST_HEADERS
    # 发起get请求
    response = requests.get(url, headers=headers, verify=True)
    html_data = response.content.decode()
    data_dict = json.loads(html_data)
    post_list = data_dict["postList"]  # 获取页面内容
    all_post_count = data_dict["postsCount"]  # 获取总文章数目
    page_count = math.ceil(all_post_count / 10)  # 获取总页数

    print("【status %s】第 %s 页" % (response.status_code, page_n))

    info_result = []  # 写入表格的数据
    # 写入首行
    if page_num == 1:
        info = TABLE_HEAD_TITLE_LIST  # 首行内容
        info_result.append(info)

    # 获取当页内容
    for index, item in enumerate(post_list):
        title = item['title']  # 获取标题
        viewCount = item['viewCount']  # 获取点击量
        comment_count = item['feedBackCount']  # 获取评论数量
        url = "https:%s" % item['url']  # 获取文章url
        datePublished = item['datePublished']  # 获取首次发布日期
        dateUpdated = item['dateUpdated']  # 获取最近修改日期
        # 打印到控制台
        print((index + ((page_n - 1) * SINGLE_PAGE_COUNT) + 1), end='  ')
        print(title)

        info = [title, viewCount, comment_count, url, datePublished, dateUpdated]  # 每行的内容
        # 存内存列表
        info_result.append(info)

        if save_mysql is True:
            # 存mysql数据库

            # 先检查数据库中是否已经存有,如果已存,则不再存入
            sql_0 = "select url from article_list where url='%s'"
            cursor.execute(sql_0 % url)  # 生成增加sql语句
            url_list = cursor.fetchall()  # 获取查询结果

            if len(url_list) > 0:
                print("数据库已存在:%s " % url)
            else:
                # 增加数据操作
                sql_1 = "INSERT INTO article_list(title,countView,countComment,url,datePublished,dateUpdated) VALUES ('%s','%s','%s','%s','%s','%s');"
                data = tuple(info)
                cursor.execute(sql_1 % data)  # 生成增加sql语句
                # cursor.execute(sql_1)  # 生成增加sql语句
                connect.commit()  # 确认永久执行增加

    return page_count, page_num, info_result


# 变量列表页,数据存mysql、txt
def get_cbs_list_data(page_count, save_cache=True):
    for n in range(1, page_count + 1):
        time.sleep(1)  # 休息一秒钟,降低请求频率
        one_page_data_list = get_per_page_data(n, save_mysql=True)  # 请求一次第n页,并存mysql数据库
        page_num = one_page_data_list[1]
        info_result = one_page_data_list[2]

        info_result_all.extend(info_result)

        if save_cache is True:
            # 将本页面数据写入缓存文件cache.txt
            save_file_cache = CACHE_FILE_NAME
            with open(save_file_cache, 'a', encoding="utf-8") as f:
                f.write("## 第 %s/%s 页\n" % (page_num, page_count))  # 缓存页面号
                for line in info_result:
                    f.write("%s\t%s\t%s\t%s\t%s\t%s\n" % tuple(line))  # 本页内容写入缓存


# 将数据写入excel
def save_excel():
    save_file = EXCEL_FILE_NAME  # 存入文件名称
    sheet_name = WORKSHEET_NAME  # 工作簿名称
    wb = Workbook()  # 新建工作簿
    ws1 = wb.active  # 获得当前活跃的工作页,默认为第一个工作页
    ws1.title = sheet_name  # 修改页名称。sheet名称
    for row in info_result_all:
        ws1.append(row)
    wb.save(save_file)  # Excel文件名称,保存文件


# 主函数
# 1、遍历所有页面
# 2、存入缓存文件cache.txt、存入mysql数据库
# 3、数据存入内存
# 4、存入xls电子表格中
def main():
    # 尝试请求第一个列表页,获取总页数
    try:
        page_count = int(get_page_count())  # 获取总页面数。
    except Exception:
        print("请求无效,请替换为新Cookie值(COOKIE_STR)后重试")
        sys.exit()

    # 遍历所有页面。存mysql,存cache.txt文件
    # get_cbs_list_data(page_count, save_cache=False)
    get_cbs_list_data(2, save_cache=True)  # 遍历前2页

    # 最后:将数据写入excel
    # save_excel()


# 启动测试
if __name__ == '__main__':
    # 启动主程序
    main()

  

建表语句

1、添加url的btree类型索引

/*
Navicat MySQL Data Transfer

Source Server         : win7_local
Source Server Version : 50717
Source Host           : localhost:3306
Source Database       : cbs

Target Server Type    : MYSQL
Target Server Version : 50717
File Encoding         : 65001

Date: 2020-05-27 11:35:19
*/

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for article_list
-- ----------------------------
DROP TABLE IF EXISTS `article_list`;
CREATE TABLE `article_list` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `title` varchar(255) DEFAULT NULL,
  `countView` varchar(10) DEFAULT NULL,
  `countComment` varchar(10) DEFAULT NULL,
  `url` varchar(100) DEFAULT NULL,
  `datePublished` datetime DEFAULT NULL,
  `dateUpdated` datetime DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `url_index` (`url`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;