Python ---- 爬虫练习 爬取 CSDN 2020 博客之星投票数据

效果

2020 博客之星年度总评选排名

分析网页数据

  1. 2020 博客之星年度总评选
  2. 页面数据接口分析
    2.1 (以谷歌浏览器为例)

浏览器打开2020 博客之星年度总评选 ===》 F12(鼠标右键 ===》 检查) ===》 Network ===》 XHR ===》 在列表中找到数据接口点击

在这里插入图片描述

2.2 查看接口和请求方式

当前实例数据接口:https://bss.csdn.net/m/topic/blog_star2020/getUsers
请求方式:POST

在这里插入图片描述
2.3 查看请求头和请求参数

在这里插入图片描述
2.4 查看接口返回结果
在这里插入图片描述

爬取投票信息

爬取数据并保存到 csdn2020.js 文件中

  1. 引入 requests 和 json 模块;
  2. 设置常量 url 和 headers ;
  3. 创建抓取数据的方法 getCSDNBlogStar;
  4. 捕获抓取中存在的异常;
  5. requests 抓取数据,json 解析数据;
  6. 对返回数据判断是 list 同时长度大于 0,将数据更新到 UP_DIR_JS + “csdn2020.js” 文件中;
  7. 如果返回数据不满足上一条件,就到 UP_DIR_JS + “csdn2020.js” 文件读取原来的数据返回。
"""
@Author  :Rattenking
@Date    :2021/02/07 09:35
@CSDN	 :https://blog.csdn.net/m0_38082783
"""
import requests
import json
url = "https://bss.csdn.net/m/topic/blog_star2020/getUsers"
headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.162 Safari/537.36",
    "Referer": "https://bss.csdn.net/m/topic/blog_star2020"
}
def getCSDNBlogStar():
  try:
    res = requests.get(url, headers=headers)
    results = json.loads(res.text)['data']
    if(isinstance(results, list) and len(results) > 0):
      file = open(UP_DIR_JS + "csdn2020.js", 'w', encoding='utf-8')
      file.write(json.dumps(results))
      file.close()
    else:
      with open(UP_DIR_JS + "csdn2020.js", encoding='utf-8') as csdn2020:
        content = csdn2020.read()
        results = json.loads(content)
    return results
  except Exception as e:
    print(e)
    return "获取 CSDN 2020 博客之星排名失败!"

通过 api 接口将数据返回

  1. 调用 getCSDNBlogStar 获取数据;
  2. resultGenerator 类对结果进行统一封装处理;
@api.route('/csdn/star2020',methods=['POST','GET'])
def getCSDNStar():
  try:
    return resultGenerator.genSuccessResult(getCSDNBlogStar())
  except Exception as e:
    print(e)
    return resultGenerator.genFailResult("查询异常!")

HTML 请求数据并展示

  1. 使用媒体查询做适配处理;
  2. 使用 vue 2.0 做数据渲染;
  3. jQuery 的 post 请求抓取的数据;
  4. 对抓取的数据 通过 sort 排序;
  5. jumpBlog 跳转当前博主在 CSDN 的博客首页!
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <meta name="referrer" content="no-referrer" />
  <meta content="email=no" name="format-detection">
  <meta content="telephone=no" name="format-detection">
  <meta name="msapplication-tap-highlight" content="no">
  <meta content="yes" name="apple-mobile-web-app-capable">
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
  <meta content="black" name="apple-mobile-web-app-status-bar-style">
  <meta content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no" name="viewport">
  <link rel="shortcut icon" href="https://www.tyfo.com/market/content/home_image/favicon.ico" type="image/x-icon" />
  <title>CSDN 2020博客之星排名</title>
  <script src="https://www.tyfo.com/common/js/jquery.js"></script>
  <script src="/static/assets/js/vue.js"></script>
  <link rel="stylesheet" href="/static/assets/css/common.css">
  <style>
    body{background-color: #111;}
    @media screen and (max-width: 1100px) {
      html {
        font-size: calc(100vw / 7.5);
      }
    }
    @media screen and (min-width: 1100px) and (max-width: 1920px) {
      html {
        font-size: calc(750px / 7.5);
      }
    }
    .rui-blog-star{
      max-width: 1100px;
      margin: 0 auto;
      box-sizing: border-box;
      padding: 0.3rem;
      display: -webkit-flex;
      display: flex;
      flex-wrap: wrap;
    }
    .rui-star-li{
      width: 49%;
      flex: none;
      border: 1px solid #0afcf0;
      border-radius: 3px;
      box-sizing: border-box;
      padding:0.3rem 0.1rem;
      margin-right: 2%;
      margin-bottom: 0.3rem;
    }
    .rui-star-li:nth-child(2n){margin-right: 0;}
    .rui-star-icon{
      width: 1.5rem;
      height: 1.5rem;
      flex: none;
      display: block;
      margin: 0 auto;
      border-radius: 50%;
    }
    .rui-star-name{
      font-size: 0.3rem;
      color: #F9F9F9;
      background: linear-gradient(
      0deg
      , #0787ff 0%, #04feef 46.24023438%, #0789ff 100%);
      -webkit-background-clip: text;
      -webkit-text-fill-color: transparent;
      line-height: 2;
      margin-top: 0.15rem;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      text-align: center;
    }
    .rui-vote-num{
      color: #07F5F2;
      font-size: 0.3rem;
    }
    .rui-star-code{
      color: #fff;
      font-size: 0.22rem;
      text-align: center;
      margin-top: 0.1rem;
    }
    .rui-star-vote{
      color: #fff;
      font-size: 0.3rem;
      display: -webkit-flex;
      display: flex;
      align-items: center;
      justify-content: center;
      margin-top: 0.1rem;
    }
    .rui-flex-ac{
      display: -webkit-flex;
      display: flex;
      align-items: center;
    }
    .rui-star-sort{
      font-size: 0.3rem;
      margin-bottom: 0.2rem;
      color: #fff;
      text-align: center;
    }
    .rui-title{
      font-size: 0.4rem;
      color: #fff;
      text-align: center;
      margin: 0.5rem;
    }
  </style>
</head>

<body>
  <div id="app">
    <div class="rui-title">CSDN 2020 博客之星最终排名</div>
    <div class="rui-blog-star">
      <div class="rui-star-li" v-for="(item,index) in list" @click="jumpBlog(item.title)">
        <div class="rui-star-sort">第<span  class="rui-vote-num" v-html="index + 1"></span>名</div>
        <img :src="item.avatar" class="rui-star-icon" alt="">
        <div v-html="item.nick_name" class="rui-star-name"></div>
        <div class="rui-star-code">码龄<span v-html="item.codeLevel"></span>年</div>
        <div class="rui-star-code">2020年度原创博文: <span v-html="item.brief"></span>篇</div>
        <div class="rui-star-vote">
          <div class="rui-flex-ac">最终票数:<div v-html="item.vote_num" class="rui-vote-num"></div>票</div>
        </div>
      </div>
    </div>
  </div>
  <script>
    var app = new Vue({
      el: '#app',
      data: {
        list: []
      },
      created() {
        this.getStar();
      },
      methods: {
        jumpBlog(title){
          location.href = `https://blog.csdn.net/${title}`;
        },
        getStar() {
          let _this = this;
          $.post('/api/csdn/star2020', res => {
            console.log(res.data)
            let list = res.data || [];
            _this.list = res.data.sort((a, b) => b.vote_num - a.vote_num)
          })
        }
      }
    })
  </script>
</body>

</html>

预览

2020 博客之星年度总评选排名

开发中的报错

  1. file.write 写入传的是字符串,开始采用的 str 方法,读取采用的是 list 方法,发现解析不正确;
  2. json 数据转字符串用 json.dumps,json 字符串转 json 用 json.loads;
  3. img 读取图片报 403 ,可以使用!
<meta name="referrer" content="no-referrer" />

猜你喜欢

转载自blog.csdn.net/m0_38082783/article/details/113738170