结对第二次作业——顶会热词统计的实现

这个作业属于哪个课程 2021春软件工程实践 | W班 (福州大学)
这个作业要求在哪里 结对第二次作业——顶会热词统计的实现
结对学号 111801429 & 221801139
这个作业的目标 实现顶会热词统计的相关功能
其他参考文献 elementUI

PSP表格

PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
Planning 计划 30 10
• Estimate • 估计这个任务需要多少时间 30 10
Development 开发 3190 2745
• Analysis • 需求分析 (包括学习新技术) 30 60
• Design Spec • 生成设计文档 10 10
• Design Review • 设计复审 10 5
• Coding Standard • 代码规范 (为目前的开发制定合适的规范) 10 30
• Design • 具体设计 60 60
• Coding • 具体编码 3000 2520
• Code Review • 代码复审 60 30
• Test • 测试(自我测试,修改代码,提交修改) 10 30
Reporting 报告 50 45
• Test Report • 测试报告 30 30
• Size Measurement • 计算工作量 10 5
• Postmortem & Process Improvement Plan • 事后总结, 并提出过程改进计划 10 10
合计 3270 2800

Github仓库地址

https://github.com/lilith0120/PairProject

项目访问地址

http://118.31.56.126

成果展示

1. 本项目whichpage的项目首页,显示已导入的论文列表,以及数据库爬取的总Top10热词排行:

2. 对已导入的论文列表进行模糊查询:

3. 点击右侧Top10热词,展示相关已导入的论文:

4. 点击删除图标,可对被选中论文进行删除操作,删除成功后会给予相应提示:

5. 点击详细页图标,可进入被选中论文详细页面(点击返回按钮,即可返回首页):

6. 在主页面点击修改图标,或在论文详细页点击修改按钮,均可进入被选中论文的修改页面:


7. 在修改页面点击保存修改按钮,将提示修改成功信息,并返回该论文的详细页面:

8. 在论文导入页面搜索相关论文题目,显示已爬取的相关性最高的前6条论文列表(鼠标悬停导航栏可出现高亮):

9. 点击导入可将被选中论文导入至首页(已导入论文列表)内:

10. 使用饼图、雷达图、折线图对近十年间、不同顶会的热词呈现热度走势对比,并以动图的形式呈现:

结对过程

基于第一次结对作业的原型设计,初步决定使用vue编写前端,使用python编写后端,并双双激情购入服务器(x2)。PS: 笑死,根本不够用!
通过在同一个工位的编程,方便了两人互相逼逼赖赖,如图所示:

在工作初期发现如果文件夹名为学号,笑死,vue根本跑不了 :/
另外由于第一次使用github高级功能,前期的github commit记录总是奇奇怪怪的,且有自己的想法(大无语事件发生)
最后通过不是那么万能的百度发现了宝藏语句git pull --rebase

前期工作准备完毕后,火速完成前端页面的编写,并双双阵亡在了爬取数据上。离谱,八爪鱼是什么垃圾!还是python大法好 :)
于是经过了坎坷的爬取数据后,收获到了1500+的论文数据,以及若干的关键词。数据库内容如下(由于篇幅有限,此处每个表只展示1000条数据):

由于不知道服务器怎么同时运行两个服务,于是两台服务器双双上岗(PS: 一个拿去极限编程了,哭哭)

实现过程

  • 前端:
  1. 使用vue-cli框架+ElementUI实现基本的项目框架的搭建,并使用vue-routeraxios来实现路由跳转以及与后端交互,并通过echarts来展示相关数据。
  2. 通过将右侧的Top10列表和顶部的导航栏复用,减少了不必要的代码冗余。并分别用三个页面展示论文列表、导入论文以及本站焦点模块。
  • 后端:
  1. 使用pythonflask框架进行接口的编写,并通过postman进行相关的接口测试。
  2. 主要通过每个论文独有的isbn,对论文进行删除、更改操作。
  3. tag_list表进行相关的数据排序与获取,用于前端图标的显示。

功能结构图

代码说明

1. 前端导入依赖如下:

"dependencies": {
    "axios": "^0.21.1",
    "core-js": "^3.6.5",
    "echarts": "^4.8.0",
    "element-ui": "^2.15.1",
    "vue": "^2.6.11",
    "vue-router": "^3.5.1"
  },

2. 前端路由设置如下:

const router = new VueRouter({
    mode: 'history',
    base: '',
    routes: [
        {
            path: '/',
            redirect: { name: 'home' },
        },
        {
            path: '/home',
            component: home,
            name: 'home',
            redirect: { name: 'listpage' },
            children: [
                {
                    path: 'listpage',
                    component: listpage,
                    name: 'listpage',
                },
                {
                    path: 'insertpage',
                    component: insertpage,
                    name: 'insertpage',
                },
                {
                    path: 'detailpage/:isbn',
                    component: detailpage,
                    name: 'detailpage',
                },
                {
                    path: 'editpage/:isbn',
                    component: editpage,
                    name: 'editpage',
                }
            ]
        },
        {
            path: '/hotpage',
            component: hotpage,
            name: 'hotpage',
        },
    ]
})

3. 前端主页面如下:

<template>
    <div id="home">
        <router-view></router-view>

        <toplist></toplist>
    </div>
</template>

4. 前端图标页面如下:

<template>
    <div id="hot_page">
        <div id="chart_part">
            <div id="pie_chart" ref="pie"></div>
            <div id="radar_chart" ref="radar"></div>
        </div>
        <div id="line_chart" ref="line"></div>
    </div>
</template>

5. 前端导航栏页面如下:

<template>
    <div id="navbar">
        <div id="logo">
            <img id="nav_logo" src="../assets/logo.png" alt="" />
        </div>
        <div>
            <div id="nav_button">
                <div class="nav_button_item" @click="go_home">
                    <i class="iconfont icon-home"></i>
                    <span>首页</span>
                </div>
                <div class="nav_button_item" @click="go_insert">
                    <i class="iconfont icon-insert"></i>
                    <span>论文导入</span>
                </div>
                <div class="nav_button_item" @click="go_hot">
                    <i class="iconfont icon-data"></i>
                    <span>本站聚焦</span>
                </div>
            </div>
        </div>
    </div>
</template>

6. 后端爬取论文数据(部分代码):

# 获取数据
def get_message(num):
    if len(br.find_elements_by_xpath('//div[@class="u-mb-1"]/div')):
        abstract = br.find_elements_by_xpath(
            '//div[@class="u-mb-1"]/div')[0].text
    else:
        return

    if len(
            br.find_elements_by_xpath(
                '//div[@class="u-pb-1 doc-abstract-dateadded"]')):
        date = br.find_elements_by_xpath(
            '//div[@class="u-pb-1 doc-abstract-dateadded"]')[0].text
        date = date.split(r': ')[1]
    else:
        return

    link = br.find_elements_by_xpath(
        '//div[@class="u-pb-1 stats-document-abstract-doi"]/a')
    if len(link):
        link = link[0]
        link = link.get_attribute('href')

    if len(br.find_elements_by_xpath('//h1[@class="document-title"]')):
        title = br.find_elements_by_xpath(
            '//h1[@class="document-title"]')[0].text
    else:
        return

    if len(br.find_elements_by_xpath('//div[@class="u-pb-1"]')) >= 4:
        isbn = br.find_elements_by_xpath('//div[@class="u-pb-1"]')[3].text
        isbn = isbn.split(r': ')[1]
    elif len(br.find_elements_by_xpath('//div[@class="u-pb-1"]')) >= 3:
        isbn = br.find_elements_by_xpath('//div[@class="u-pb-1"]')[2].text
        isbn = isbn.split(r': ')[1]
    else:
        return

    pointer_url = "https://ieeexplore.ieee.org/document/67511" + str(
        num) + "/keywords#keywords"
    br.get(pointer_url)
    time.sleep(2)
    key_list = br.find_elements_by_xpath(
        '//ul[@class="u-mt-1 u-p-0 List--no-style List--inline"]/li')

    key_word = ""
    for k in key_list:
        key_word += k.text

    key_list = key_word.split("\n,")
    key_word = key_word.split("\n")
    key_word = "".join(key_word)

    save_data(isbn, key_word, title, link, date, abstract)
    save_tag(key_list)

7. 后端实现模糊搜索接口:

# 搜索论文
@pages.route('/page/search/<num>', methods=['POST'])
def searchPages(num):
    re_dict = request.get_json()
    isbn = re_dict.get('isbn')
    title = re_dict.get('title')
    tag = re_dict.get('tag')

    pages = models.User_page.query.filter(
        models.User_page.isbn.like('%{isbn}%'.format(isbn=isbn)),
        models.User_page.title.like('%{title}%'.format(title=title)),
        models.User_page.tag.like('%{tag}%'.format(tag=tag))).paginate(
            int(num), 6)

    result = {}
    data = []
    for p in pages.items:
        d = {}
        d['isbn'] = p.isbn
        d['title'] = p.title
        d['tag'] = p.tag
        data.append(d)

    result['total_num'] = pages.pages
    result['pages'] = data

    return jsonify(errno=0, data=result)

8. 后端获取Top10热词排行接口:

# 获取top10热词
@pages.route('/tag', methods=['GET'])
def showTopTags():
    result = db.session.query(
        func.sum(models.Tag_list.num).label('total_num'),
        models.Tag_list.name).group_by(models.Tag_list.name).order_by(
            text("total_num desc")).limit(10).all()

    data = []
    for r in result:
        d = {}
        d['title'] = r.name
        data.append(d)

    return jsonify(errno=0, data=data)

心路历程,队友评价

第二次结对的心路历程与收获

小皮(221801139):

心路历程:
  第一次接触vue感觉很新鲜也很好用(虽然一开始不太懂,但后面越来越好上手,开心!),在本次实践中也很享受做前端页面的工作,elementUI真是个宝藏网址,完美的实现了我们的原型和需求,爱了爱了。
收获:

  1. 被强行安利一嘴的vue,并成功上手
  2. 学到了前后端交互的axios编写方式
  3. 代码规范得到救治,并受到了夸奖

九歌(111801429):

心路历程:
  最开始的时候,很担心两只咸鱼做不完这项艰巨的任务。但是随着前端框架的搭建以及静态界面的完成,感觉事情似乎又好起来了。虽然在爬取论文数据的时候遇到了比较大的挫折,但是磋磨磋磨,总能盘活这件事情。最后,通过接口测试以及部署到服务器后的页面测试,圆满完成了这项任务。好耶!!!!!
收获:

  1. 重新拾起python的爬取技能点
  2. 重新拾起python的接口编写技能点
  3. 巩固了vue框架的使用并成功安利出去
  4. 对小皮同志的代码起到了一定的规范作用

队友评价

小皮(221801139)=>九歌(111801429):

  被九歌同志成功安利vuepython,做出来的爬虫也太酷了吧,果然强行和九歌同志绑定是个正确的决定!虽然在部署服务器的过程中,经历了好多困难,但是还是被她成功攻破,棒!如果她不逼逼赖赖就更好了...好想上手痛击怎么办,在线等,挺急的 :)一起加油吧,勇敢的狗狗们!诶嘿!
PS: 熬到凌晨的感觉也太开心了吧,我很快乐,真的 :)

九歌(111801429)=>小皮(221801139):

  小皮同志是一个好同志,能容忍我一直逼逼赖赖的吐槽(并且不会下手痛击她的队友)。并且小皮同志吃苦耐劳,大家一起加班,并拖延到了很晚。笑死,根本不困。:)在小皮同志的工位上,定点上下班(吗?)让我有体会了结对编程带来的变化,一直碎碎念,根本停不下。小皮同志在我的带领下,口音逐渐走上了一条不归路。笑死,根本改不回来。
PS: 快跑!小皮同志带着口音过来了!jiú命!!!

posted @ 2021-03-30 00:21  行露  阅读(289)  评论(19编辑  收藏  举报
the end