[web开发] Vue + spring boot + echart 微博爬虫展示平台

1.微博登录

2.爬取数据

3.mysql存储

4.pyechart本地展示

5.用vue搭建网站web展示

1.微博登录

新浪微博的登录不是简单的post就能解决的,他的登录有加密,所以我们要使用一定的解密算法才能正常登录微博,得到我们想要的数据。

先不要慌,第一步当然是import我们需要的库

from urllib import request,parse
import http.cookiejar
import base64
import json
import rsa
import binascii
from PIL import Image
from bs4 import BeautifulSoup
import pymysql

要登录,那肯定要先拿到验证码

    def GetCode(self):
        url="https://login.sina.com.cn/cgi/pin.php?r=694905&s=0&p=gz-52086a8a846fadcdacf4fb058324aa387858"#验证码地址
        img=self.opener.open(url)
        f=open(‘vv.png‘,‘wb‘)
        f.write(img.read())
        f.close()
        im=Image.open(‘vv.png‘)
        im.show()

拿到了验证码还不够,登录之前还有个预登录,拿到我们后面加密需要的参数

def prelogin(self):
        url="https://login.sina.com.cn/sso/prelogin.php?entry=weibo&callback=sinaSSOController.preloginCallBack&su=NDc5MTkyNzQyJTQwcXEuY29t&rsakt=mod&checkpin=1&client=ssologin.js(v1.4.19)&_=1529471491358"
        a=self.opener.open(url).read().decode(‘utf-8‘)
        a=a[a.find("(")+1:a.find(")")]
        b=json.loads(a)
        return b
‘’‘
sinaSSOController.preloginCallBack({"retcode":0,"servertime":1540617565,"pcid":"gz-65c55b3534f8a1df1330b4708fb6d1b57273","nonce":"ONED4A","pubkey":"EB2A38568661887FA180BDDB5CABD5F21C7BFD59C090CB2D245A87AC253062882729293E5506350508E7F9AA3BB77F4333231490F915F6D63C55FE2F08A49B353F444AD3993CACC02DB784ABBB8E42A9B1BBFFFB38BE18D78E87A0E41B9B8F73A928EE0CCEE1F6739884B9777E4FE9E88A1BBE495927AC4A799B3181D6442443","rsakv":"1330428213","is_openlock":0,"showpin":0,"exectime":10})’‘’

然后用这些参数对登录参数进行加密,说实在话具体的加密细节我也不记得了,当时做的时候拿了个记事本把所有东西记下来然后分析,也查了很多博客的资料才做好。

def GetMixUser(self,username,password):
        username_struct={‘username‘:username}
        rsaPubkey=int(self.pre[‘pubkey‘],16)
        key=rsa.PublicKey(rsaPubkey, 65537)
        message = str(self.pre[‘servertime‘]) + ‘\t‘ + self.pre[‘nonce‘] + ‘\n‘ + password
        passwd = rsa.encrypt(message.encode(‘utf-8‘), key)
        upass = binascii.b2a_hex(passwd)
        uname=base64.b64encode(parse.urlencode(username_struct).encode(‘utf-8‘)).decode(‘utf-8‘)[12:]
        mix={‘uname‘:uname,‘upass‘:upass.decode(‘utf-8‘)}
        return mix

拿到加密后的登录参数,可以提交了

def login(self,username,password,code):
        mix=self.GetMixUser(username,password)
        uname=mix[‘uname‘]
        upass=mix[‘upass‘]
        url="https://login.sina.com.cn/sso/login.php?client=ssologin.js(v1.4.19)"
        print("登录中……")
        postData={
            "door":code,
            "encoding":"utf-8",
            "entry":"weibo",
            "from":"null",
            "gateway":1,
            "nonce":self.pre[‘nonce‘],
            "prelt":72,
            "pwencode":"rsa2",
            "qrcode_flag":False,
            "returntype":"META",
            "savestate":7,
            "servertime":self.pre[‘servertime‘],
            "service":"miniblog",
            "rsakv":self.pre[‘rsakv‘],
            "su":uname,
            "sp":upass,
            "url":"https://weibo.com/ajaxlogin.php?framelogin=1&callback=parent.sinaSSOController.feedBackUrlCallBack",
            "useticket":1,
            "vsnf":1
        }
        postData=parse.urlencode(postData).encode(‘utf-8‘)
        result=self.opener.open(url,postData).read().decode(‘gbk‘)
        url1=result[result.find("replace")+9:result.find(‘)‘)-1]
        result=self.opener.open(url1).read().decode("gbk")
        if(result.find("身份")!=-1):
            return False
        result=result[result.find(‘location‘)+18:]
        url2=result[:result.find(‘)‘)-1]
        self.opener.open(url2).read().decode("gbk")
        return True

2.爬取信息

先得到用户follow的列表

    def GetUserList(self,uid,pageNum):
        url="https://weibo.com/"+str(uid)+"/follow?page="+str(pageNum)
        try:
            result=self.opener.open(url).read().decode(‘utf-8‘)
            html = result.replace(‘\\n‘, ‘‘).replace(‘\\t‘, ‘‘).replace(‘\\r‘, ‘‘).replace(‘\\‘, ‘‘)
            html = html[html.find("<!--关注/粉丝列表-->"):html.find("<!--关欧盟隐私协议弹窗-->")]
            soup = BeautifulSoup(html, "html.parser")
            list_a = soup.findAll(name=‘div‘, attrs={"class": "info_name W_fb W_f14"})
            name = []
            uid = []
            for a in list_a:
                try:
                    b = a.find(name="a")
                    b = b[‘usercard‘]
                    b = b[3:13:]
                    uid.append(b)
                    name.append(a.text)
                    print("加入用户:" + a.text)
                except:
                    print("No Data")
            dic = {"name": name, "uid": uid}
            return dic
        except:
            pass

再拿到这些用户的主页微博言论,我们得到他们发的所有博文

def GetTalks(self,uid):
        rlist = []
        i=0
        html=""
        while(True):
            try:
                result=self.opener.open("https://weibo.com/u/"+str(uid)+"?page="+str(i)).read().decode("utf-8")
                html = result.replace("\\t", "").replace("\\n", "").replace("\\r", "").replace("\\", "")
                html = html[html.find("<div class=\"WB_feed WB_feed_v3 WB_feed_v4\""):]
            except:
                pass
            soup=BeautifulSoup(html,"html.parser")
            list_a = soup.find_all(name="div", attrs={"class": "WB_text W_f14"})
            i = i + 1
            if list_a:
                print("第" + str(i) + "页")
                for a in list_a:
                    at=a.text
                    at=at.replace(" ","")
                    if at:
                        rlist.append(at)
                        print("内容存入:"+at)
            else:
                break
        return rlist

3.数据存储

我暂时只做了这些,然后存储到数据库吧。mysql的基础语句很简单,我也就会这么几句,不会的百度吧。。

def sqllogin(self):
        db=pymysql.connect(host=‘localhost‘,user=‘root‘,db=‘weibouser‘,passwd=‘root‘,charset=‘utf8mb4‘)
        return db
    def sqlProcess(self,db):
        while(True):
            cursor=db.cursor()
            cursor.execute("SELECT * FROM USERS WHERE TAG =1")           #1 表示 未处理 2 表示 正在处理 3 表示完成处理
            result=cursor.fetchone()
            if(result):
                cursor.execute("UPDATE USERS SET TAG=2 WHERE USERID=‘%s‘" % (result[2]))
                talks=self.GetTalks(uid=result[2])
                for i in range(1,4):
                   uids=""
                   names=""
                   userlist = self.GetUserList(uid=result[2], pageNum=i)
                   try:
                        uids=userlist[‘uid‘]
                        names=userlist[‘name‘]
                   except:
                       break
                   if int(result[4])!=3:
                       for t in range(len(uids)):
                           try:
                               if self.IfExist(db,"users","name",names[t])==False:
                                    cursor.execute("INSERT INTO USERS (NAME,USERID,TAG,CLASS) VALUES (‘%s‘,‘%s‘,%d,%d)" % (names[t], uids[t], 1, int(result[4])+1))  # 数据库写userlist
                                    cursor.execute("INSERT INTO FOLLOWS (USERID,FUID,FUNAME) VALUES (‘%s‘,‘%s‘,‘%s‘)" % (result[2], uids[t],names[t]))
                           except:
                               print("Error")
                for talk in talks:
                    try:
                        cursor.execute("INSERT INTO USERTALKS (USERID,NAME,TALK)VALUES (‘%s‘,‘%s‘,‘%s‘)" % (result[2],result[1],talk))#数据库写评论
                    except:
                        print("Error")
                cursor.execute("UPDATE USERS SET TAG=3 WHERE USERID=‘%s‘"%(result[2]))
            else:
                break
    def AnotherProcess(self,db):
        cursor=db.cursor();
        cursor.execute("SELECT * FROM USERS WHERE 1");
        results=cursor.fetchall()
        for result in results:
            sex="女"
            try:
                r = self.opener.open("https://weibo.com/u/"+result[2]).read().decode("utf-8")
                html = r.replace("\\t", "").replace("\\n", "").replace("\\r", "").replace("\\", "")
                if html.find("female") == -1:
                    sex="男"
            except:
                pass
            soup = BeautifulSoup(html, "html.parser")
            keywords=soup.find(attrs={"name":"keywords"})[‘content‘]
            description=soup.find(attrs={"name":"description"})[‘content‘]
            cursor.execute("INSERT INTO USERDETAILS (NAME,DESCRIPTION,KEYWORDS,SEX)VALUES(‘{}‘,‘{}‘,‘{}‘,‘{}‘)".format(result[1],description,keywords,sex))

4.echart本地展示

import pymysql
from pyecharts import Graph
class DrawCharts:
    raw_nodes = []
    links = []
    def __init__(self):
        self.CreatRelation()
        self.DrawCharts()
    def CreatRelation(self):
        db=pymysql.connect(host=‘localhost‘,user=‘root‘,db=‘weibouser‘,passwd=‘root‘,charset=‘utf8mb4‘)
        cursor=db.cursor()
        cursor.execute("SELECT * FROM USERS WHERE 1");
        users=cursor.fetchall()
        for user in users:#上海大学
            cursor.execute("SELECT * FROM FOLLOWS WHERE USERID=‘%s‘"%(user[2]));
            results=cursor.fetchall()
            if results:
                for result in results:
                    links.append({"source":user[1],"target":result[4]})
                    print(user[1]+"->"+result[4])
        for i in range(3):
            cursor.execute("SELECT * FROM USERS WHERE CLASS=%d"%(i+1))
            results=cursor.fetchall()
            for result in results:
                self.raw_nodes.append({"name": result[1], "symbolSize": 30-i*13,"category":i})

        db.close()
    def DrawCharts(self):
        graph = Graph("微博关注关系图", width=1200, height=600)
        categories=[
            {
            "name":"一级深度",
            "itemStyle":
                {
                    "normal":{
                        "color":‘#CC0033‘,
                        "borderColor": "#5182ab",
                        "borderWidth": 1.8,
                        "show":"True"
                    }
                }
            },
            {
                "name": "二级深度",
                "itemStyle":
                    {
                        "normal": {
                            "color": ‘#f44242‘,
                            "borderColor": "#5182ab",
                            "borderWidth": 1.8,
                            "show":"True"
                        }
                    }
            },
            {
                "name": "三级深度",
                "itemStyle":
                    {
                        "normal": {
                            "color": ‘#663366‘,
                            "borderColor": "#5182ab",
                            "borderWidth": 1.8,
                            "show":"True"
                        }
                    }
            }
        ]
        graph.add("",self.raw_nodes,self.links,label_pos="right",graph_repulsion=10, is_legend_show=False,categories=categories,
                  label_text_color=None,is_label_show=True)
        graph.render()

效果就不发了,运行起来比较卡,因为节点太多了,当时老师说怎么怎么加速,也不说细节,我当时一脸懵逼,也就没管了,大不了减少节点数量嘛。

5.web展示

前端两段关键代码。。

<style scoped>
  .layout-con{
    height: 100%;
    width: 100%;
  }
  .menu-item span{
    display: inline-block;
    overflow: hidden;
    width: 69px;
    text-overflow: ellipsis;
    white-space: nowrap;
    vertical-align: bottom;
    transition: width .2s ease .2s;
  }
  .menu-item i{
    transform: translateX(0px);
    transition: font-size .2s ease, transform .2s ease;
    vertical-align: middle;
    font-size: 16px;
  }
  .collapsed-menu span{
    width: 0px;
    transition: width .2s ease;
  }
  .collapsed-menu i{
    transform: translateX(5px);
    transition: font-size .2s ease .2s, transform .2s ease .2s;
    vertical-align: middle;
    font-size: 22px;
  }
</style>
<template>
  <div class="layout">
    <Layout :style="{minHeight: ‘100vh‘}">
      <Sider collapsible :collapsed-width="78" v-model="isCollapsed">
        <Menu active-name="1-1" theme="dark" width="auto" :class="menuitemClasses">
          <MenuItem name="1-1" @click.native="tab_search_onclick()">
            <Icon type="search"></Icon>
            <span>搜索</span>

          </MenuItem>
          <MenuItem name="1-2" @click.native="tab_follow_onclick()">
            <Icon type="person"></Icon>
            <span>follow关系</span>
          </MenuItem>
          <MenuItem name="1-3" @click.native="tab_words_onclick()">
            <Icon type="cloud"></Icon>
            <span >热词云图</span>
          </MenuItem>
        </Menu>
      </Sider>
      <Layout>
        <Header :style="{background: ‘#fff‘, boxShadow: ‘0 2px 3px 2px rgba(0,0,0,.1)‘,height:‘100px‘}">
          <img src="../assets/logo.png" style="height: 100%"/>
        </Header>
        <Content :style="{padding: ‘0 16px 16px‘}">

          <Card style="margin-top: 20px">
            <p slot="title">{{Content_Title}}</p>
            <div style="height: 650px">
              <div v-show="v_search">
                  <div style="margin-bottom: 30px;margin-top: 30px">
                    <Input v-model="input_word" icon="ios-clock-outline" placeholder="请输入微博用户名称!" style="width: 250px;margin-right: 10px"></Input>
                    <Button type="primary" shape="circle" icon="ios-search" @click="fs_search">查询</Button>
                  </div>
                  <div style="width: 50%;margin: auto">
                    <Card :bordered="true" style="height: 350px;text-align: left">
                      <p slot="title">{{Search_Card_Title}}</p>
                      <p v-for="item in items" style="height: 70px">{{item.message}}</p>
                    </Card>
                  </div>
              </div>
              <div v-show="v_follows">
                <div style="width: 80%;margin: auto">
                  <Card :bordered="true" style="height: 580px;width: 100%;margin-top: 50px">
                    <p slot="title">{{Follow_Card_Title}}</p>
                    <div id="Follow_Chart" style="height: 500px;width:800px;margin: auto;"></div>
                  </Card>
                </div>

              </div>
              <div v-show="v_words">
                <div style="width: 50%;margin: auto">
                  <Card :bordered="true" style="height: 330px;margin-top:50px ">
                    <p slot="title">{{Words_Card_Title}}</p>
                    <div id="Words_Chart" style="height: 250px;width:500px;margin: auto"></div>
                  </Card>
                </div>
              </div>
            </div>
          </Card>
        </Content>
      </Layout>
    </Layout>
  </div>
</template>
<script>
  let echarts = require(‘echarts‘);
  require(‘echarts-wordcloud‘);
  require("echarts/lib/chart/graph/forceLayout");
  export default {
    data () {
      return {
        isCollapsed: false,
        items:[],
        Search_Card_Title:‘搜索结果‘,
        Content_Title:"资料搜索",
        Follow_Card_Title:"关系图绘制结果",
        Words_Card_Title:"词云绘制结果",
        input_word:‘‘,
        v_search:true,
        v_follows:false,
        v_words:false
      };
    },
    computed: {
      menuitemClasses: function () {
        return [
          ‘menu-item‘,
          this.isCollapsed ? ‘collapsed-menu‘ : ‘‘
        ]
      }
    },
    methods:{
      fs_search(){
        let axios=this.$axios;
        let word=this.input_word;
        function getDetails(){
          return axios.get("http://localhost:9090/details?name="+word);
        }
        function getUsers(){
          return axios.get("http://localhost:9090/words?name="+word);
        }
        function getNodes() {
          return axios.get("http://localhost:9090/nodes?name="+word);
        }
        function getLinks(){
          return axios.get("http://localhost:9090/links?name="+word);
        }

        axios.all([getDetails(),getUsers(),getNodes(),getLinks()]).then(axios.spread((details,users,nodes,links)=>{
          this.draw_relations(nodes.data,links.data);
          this.set_details(details.data);
          this.draw_words(users.data);
          this.$Notice.success({
            title: ‘绘制成功‘,
            desc: ‘您搜索的用户‘+word+‘关系图和热词已经成功绘制!‘
          });
        })).catch(res=>{
          this.$Notice.error({
            title: ‘绘制失败‘,
            desc: ‘您搜索的用户‘+word+‘关系图或热词绘制失败,请检查网络或输入信息!‘
          });
        })
      },
      tab_search_onclick:function(){
        this.v_search=true;
        this.v_follows=false;
        this.v_words=false;
        this.Content_Title="资料搜索"
      },
      tab_follow_onclick:function(){
        this.v_follows=true;
        this.v_words=false;
        this.v_search=false;
        this.Content_Title="follow关系";
      },
      draw_words:function(words_data){
        let mychart=echarts.init(document.getElementById(‘Words_Chart‘));
        mychart.setOption({
          tootip: {
            show: true
          },
          series: {
            name: ‘词云图‘,
            type: ‘wordCloud‘,
            textStyle: {
              normal: {
                color: function () {
                  return ‘rgb(‘ + [
                    Math.round(Math.random() * 160),
                    Math.round(Math.random() * 160),
                    Math.round(Math.random() * 160)
                  ].join(‘,‘) + ‘)‘
                }
              }
            },
            textRotation: [0, 90, -45, 45],
            autoSize: true,
            data:
            words_data
          }
        })
      },
      set_details(details){
          this.items.push({"message":"微博名:"+details["name"]});
          this.items.push({"message":"微博描述:"+details["description"]});
          this.items.push({"message":"关键词:"+details["keywords"]});
          this.items.push({"message":"用户性别:"+details["sex"]});
      },
      draw_relations:function(nodes,links){
        let mychart=echarts.init(document.getElementById("Follow_Chart"));
        let option={
          title: {                    // 图表标题
            text: "关注关系图",           // 标题文本
            left : ‘3%‘,                    // 标题距离左侧边距
            top : ‘3%‘,                     // 标题距顶部边距
            textStyle : {                       // 标题样式
              color : ‘#000‘,                     // 标题字体颜色
              fontSize : ‘30‘,                    // 标题字体大小
            }
          },

          series: [{
            type: "graph",          // 系列类型:关系图
            top: ‘10%‘,             // 图表距离容器顶部的距离
            roam: true,             // 是否开启鼠标缩放和平移漫游。默认不开启。如果只想要开启缩放或者平移,可以设置成 ‘scale‘ 或者 ‘move‘。设置成 true 为都开启
            focusNodeAdjacency: true,   // 是否在鼠标移到节点上的时候突出显示节点以及节点的边和邻接节点。[ default: false ]
            force: {                // 力引导布局相关的配置项,力引导布局是模拟弹簧电荷模型在每两个节点之间添加一个斥力,每条边的两个节点之间添加一个引力,每次迭代节点会在各个斥力和引力的作用下移动位置,多次迭代后节点会静止在一个受力平衡的位置,达到整个模型的能量最小化。
              // 力引导布局的结果有良好的对称性和局部聚合性,也比较美观。
              repulsion: 1000,            // [ default: 50 ]节点之间的斥力因子(关系对象之间的距离)。支持设置成数组表达斥力的范围,此时不同大小的值会线性映射到不同的斥力。值越大则斥力越大
              // [ default: 30 ]边的两个节点之间的距离(关系对象连接线两端对象的距离,会根据关系对象值得大小来判断距离的大小),
              // 这个距离也会受 repulsion。支持设置成数组表达边长的范围,此时不同大小的值会线性映射到不同的长度。值越小则长度越长。如下示例:
              // 值最大的边长度会趋向于 10,值最小的边长度会趋向于 50      edgeLength: [10, 50]
            },
            layout: "force",            // 图的布局。[ default: ‘none‘ ]
                                        // ‘none‘ 不采用任何布局,使用节点中提供的 x, y 作为节点的位置。
                                        // ‘circular‘ 采用环形布局;‘force‘ 采用力引导布局.
            // 标记的图形
            //symbol: "path://M19.300,3.300 L253.300,3.300 C262.136,3.300 269.300,10.463 269.300,19.300 L269.300,21.300 C269.300,30.137 262.136,37.300 253.300,37.300 L19.300,37.300 C10.463,37.300 3.300,30.137 3.300,21.300 L3.300,19.300 C3.300,10.463 10.463,3.300 19.300,3.300 Z",
            symbol: ‘circle‘,
            lineStyle: {            // 关系边的公用线条样式。其中 lineStyle.color 支持设置为‘source‘或者‘target‘特殊值,此时边会自动取源节点或目标节点的颜色作为自己的颜色。
              normal: {
                color: ‘#000‘,          // 线的颜色[ default: ‘#aaa‘ ]
                width: 1,               // 线宽[ default: 1 ]
                type: ‘solid‘,          // 线的类型[ default: solid ]   ‘dashed‘    ‘dotted‘
                opacity: 0.5,           // 图形透明度。支持从 0 到 1 的数字,为 0 时不绘制该图形。[ default: 0.5 ]
                curveness: 0            // 边的曲度,支持从 0 到 1 的值,值越大曲度越大。[ default: 0 ]
              }
            },
            label: {                // 关系对象上的标签
              normal: {
                show: true,                 // 是否显示标签
                position: "inside",         // 标签位置:‘top‘‘left‘‘right‘‘bottom‘‘inside‘‘insideLeft‘‘insideRight‘‘insideTop‘‘insideBottom‘‘insideTopLeft‘‘insideBottomLeft‘‘insideTopRight‘‘insideBottomRight‘
                textStyle: {                // 文本样式
                  fontSize: 16
                }
              }
            },
            data: nodes,
            links: links
          }],

          animationEasingUpdate: "cubicOut",          // 数据更新动画的缓动效果。[ default: cubicOut ]    "quinticInOut"
          // 数据更新动画的时长。[ default: 300 ]
        };
        mychart.setOption(option);
      },
      tab_words_onclick:function(){
        this.Content_Title="用户词云";
        this.v_words=true;
        this.v_follows=false;
        this.v_search=false;
      },

    },
    name:"HelloWorld"
  }
</script>

后端关键代码

//用户的具体信息domainpackage com.example.demo;

import org.hibernate.engine.loading.internal.CollectionLoadContext;

import javax.persistence.*;

@Entity
@Table(name = "userdetails")
public class UserDetails {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private int num;
    @Column(name="description")
    public String description;
    @Column(name="keywords")
    public String keywords;
    @Column(name="sex")
    public String sex;
    @Column(name="name")
    public String name;
    void setName(String name){
        this.name=name;
    }
    void setDescription(String description){
        this.description=description;
    }
    void setKeywords(String keywords){
        this.keywords=keywords;
    }
    void setSex(String sex){
        this.sex=sex;
    }
    String getName(){
        return this.name;
    }
    String getDescription(){
        return this.description;
    }
    String getKeywords(){
        return this.keywords;
    }
    String getSex(){
        return this.sex;
    }

}
//最重要的controllerpackage com.example.demo;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.ArrayList;
import java.util.List;
@Controller
@CrossOrigin
public class IndexController {
    @Autowired
    private UserRepositroy userRepositroy;
    @RequestMapping(value="users")
    @ResponseBody
    public Object GetUser(){
       List<User> userlist=userRepositroy.findAll();
        return userlist;
    }
    @RequestMapping(value="links")
    @ResponseBody
    public Object GetLinks(String name){
        List<Follows> followsList =followsRepositroy.findByName(name);
        List<RetnLinks> links =new ArrayList<RetnLinks>();

        for(int i=0;i<followsList.size();i++){
            RetnLinks l=new RetnLinks();
            l.setSource(followsList.get(i).getName());
            l.setTarget(followsList.get(i).getFuname());
            links.add(l);
        }
    return links;
    }
    @RequestMapping(value="nodes")
    @ResponseBody
    public Object GetNodes(String name){
        List<Follows> followsList=followsRepositroy.findByName(name);
        List<RetnNodes> nodes =new ArrayList<RetnNodes>();
        RetnNodes r=new RetnNodes();
        r.setName(name);
        r.setCategory(1);
        r.setSymbolSize(30);
        nodes.add(r);
        for(int i=0;i<followsList.size();i++){
            RetnNodes rs=new RetnNodes();
            rs.setName(followsList.get(i).getFuname());
            rs.setCategory(2);
            rs.setSymbolSize(20);
            nodes.add(rs);
        }
        return nodes;
    }
    @RequestMapping(value="words")
    @ResponseBody
    public Object GetWords(String name){
        List<User> userlist=userRepositroy.findByName(name);
        String word = userlist.get(0).getKeywords();
        String value=userlist.get(0).getKeyvalue();
        String[] array_word= word.split(",");
        String[] array_value= value.split(",");
        List<RetnWords> words=new ArrayList<RetnWords>();
        for(int i=0;i<50;i++){
            RetnWords w=new RetnWords();
            w.setName(array_word[i]);
            w.setValue(Double.parseDouble(array_value[i]));
            words.add(w);
        }
        return words;
    }
    @Autowired
    private FollowsRepositroy followsRepositroy;
    @RequestMapping(value="follows")
    @ResponseBody
    public Object GetFollows(String name){
        List<Follows> followslist=followsRepositroy.findByName(name);
        return followslist;
    }
    @Autowired
    private DetailsRepositroy detailsRepositroy;
    @RequestMapping(value="details")
    @ResponseBody
    public Object GetDetails(String name){
        UserDetails userDetails=detailsRepositroy.findOneByName(name);
        return userDetails;
    }

}

其他的都是类似的。无限重复改名。

最终结果:

原文地址:https://www.cnblogs.com/aoru45/p/9860946.html

时间: 2024-11-01 23:17:00

[web开发] Vue + spring boot + echart 微博爬虫展示平台的相关文章

Web 开发入门教程(Vue + Spring Boot)

前言 这是一套面向 Java Web 技术栈新手的入门实战教程. 网上相关教程很多,但要么只是做了一个 DEMO ,要么对许多关键问题一笔带过.我的目标是根据这个教程,可以把一个完整的项目还原出来.当然,每个人的理解方式不同,可能有些细节没讲到位,欢迎大家在评论区提问,也可以通过邮箱 ([email protected]) 联系我,我一定会认真解答. 专栏目录(持续更新) 第一部分 Vue + Spring Boot 项目实战(一):项目简介 Vue + Spring Boot 项目实战(二):

Vue + Spring Boot 项目实战(一):项目简介 &#619178;

原文: http://blog.gqylpy.com/gqy/489 置顶:来自一名75后老程序员的武林秘籍--必读(博主推荐) 来,先呈上武林秘籍链接:http://blog.gqylpy.com/gqy/401/ 你好,我是一名极客!一个 75 后的老工程师! 我将花两分钟,表述清楚我让你读这段文字的目的! 如果你看过武侠小说,你可以把这个经历理解为,你失足落入一个山洞遇到了一位垂暮的老者!而这位老者打算传你一套武功秘籍! 没错,我就是这个老者! 干研发 20 多年了!我也年轻过,奋斗过!我

Java Web系列:Spring Boot 基础 (转)

Spring Boot 项目(参考1) 提供了一个类似ASP.NET MVC的默认模板一样的标准样板,直接集成了一系列的组件并使用了默认的配置.使用Spring Boot 不会降低学习成本,甚至增加了学习成本,但显著降低了使用成本并提高了开发效率.如果没有Spring基础不建议直接上手. 1.基础项目 这里只关注基于Maven的项目构建,使用Spring Boot CLI命令行工具和Gradle构建方式请参考官网. (1)创建项目: 创建类型为quickstart的Maven项目,删除默认生成的

Java Web系列:Spring Boot 基础

Spring Boot 项目(参考1) 提供了一个类似ASP.NET MVC的默认模板一样的标准样板,直接集成了一系列的组件并使用了默认的配置.使用Spring Boot 不会降低学习成本,甚至增加了学习成本,但显著降低了使用成本并提高了开发效率.如果没有Spring基础不建议直接上手. 1.基础项目 这里只关注基于Maven的项目构建,使用Spring Boot CLI命令行工具和Gradle构建方式请参考官网. (1)创建项目: 创建类型为quickstart的Maven项目,删除默认生成的

Spring Boot 慕课网爬虫

一.项目简介(Demo简介) 慕课网...打了三个字,还是不介绍了避免广告.一个简单爬虫该网站的demo. 地址:https://www.imooc.com/course/list?c=springboot 二.项目结构 项目多层架构:common层,controller层,entity层,repository层,由于Demo比较简单就没有细分那么多了(偷懒). 三.项目说明 F12 查看页面html结构,发现如下 本次我只抽取了 课程名称,url,等级,描述四个字段. 数据库,创建imooc_

开发误区----spring boot误区

spring boot 配置加载MySQL驱动误区 若我们使用的是MySQL数据库,如果我们pom中使用的是如下的MySQL版本 <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.11</version> </dependency> 我们应该使用com.mysql.cj

Java Web开发中Spring+MyBatis框架的简单搭建

这里使用的eclipse,首先创建一个动态web项目. 1.导入Spring IOC.AOP.DAO.dbcp.dbdrive.mybatis.jar . mybatis-spring.jar  本人使用的jar包和版本如下: aopalliance.jaraspectjweaver.jarcommons-dbcp-1.4.jarcommons-logging.jarcommons-pool-1.5.6.jarmybatis-3.2.5.jarmybatis-spring-1.2.2.jarmy

Spring Boot 2.X 微信公众平台开发之接入

声明 : 本系列纯属自己为了学习而编写,均已测试号为例,如果不正之处,恳请指正,谢谢! 接入微信公众平台开发,开发者需要按照如下步骤完成: 1.填写服务器配置 由于只是接入,只需要一个Controller的方法路径 和 定义一个token,可以写在配置文件里 2.验证服务器地址的有效性 /** * FileName: CoreController * Author: Phil * Date: 8/1/2018 15:52 * Description: 接入微信并处理消息事件 * History:

《Pro Spring Boot 2》第四章:Web Applications with Spring Boot

The Spring MVC is designed around the org.springframework.web.servlet. DispatcherServlet class. This servlet is very flexible and has a very robust functionality that you won’t find in any other MVC web framework out there. With the DispatcherServlet