爬取CVPR2019年的论文数据并实现可视化热词云

写在前面

本次课堂练习,老师提出要我们做一个热词云。说实话看到的一瞬间有些懵逼,不知道要怎么做。但查阅了资料后一切明朗起来。也提示我们凡事不要怕,先做就是了。
本文web端代码已上传github:https://github.com/wushenjiang/PaperData

需求

本次任务的需求:爬取CVPR2019年所有论文的题目,并提取题目中的关键字,做成按照热度显示大小的热词云。

成品截图

成品链接:http://39.97.109.245/PaperData/papercloud.jsp
截图:

爬虫模块设计及代码

这里我起先设计了一个爬虫代码,但插入时时失败,出现莫名其妙的错误。且速度极慢。在借鉴了同学的爬虫模块后,速度依然很慢,但好歹可以插入了。也让我提高了我的python水平。代码如下:

# coding=utf-8
import pymysql
import requests
from lxml import etree


class Spider:
    def __init__(self):
        self.url = "http://openaccess.thecvf.com/CVPR2019.py"
        self.header = {
            "user-agent": "Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.116 Mobile Safari/537.36"}
        self.db = pymysql.connect(host='localhost', port=3306, user='root', passwd='abc456', db='paperdata',
                                  charset='utf8')
        self.cursor = self.db.cursor()
        self.html_list = []

    def getHtmlList(self):
        response = requests.get(self.url, headers=self.header)
        html_body = etree.HTML(response.text)
        title = html_body.xpath("//dt[@class='ptitle']/a/@href")
        for item in title:
            self.html_list.append("http://openaccess.thecvf.com/" + item)

    def getContent(self, url):
        try:
            response = requests.get(url, headers=self.header)
            body = etree.HTML(response.text)
            title = body.xpath("//div[@id='papertitle']/text()")[0]
            abstract = body.xpath("//div[@id='abstract']/text()")[0]
            down_url = body.xpath("//div[@id='content']//a/@href")[0].replace("../../", "http://openaccess.thecvf.com/")

            sql = '''insert into data values({},"{}","{}","{}")'''.format(0, title, down_url, str(abstract))
            self.cursor.execute(sql)
            print(title + "插入成功!")
            self.db.commit()
        except Exception as e:
            print(e)

    def run(self):
        self.getHtmlList()
        for url in self.html_list:
            self.getContent(url)


if __name__ == '__main__':
    spwder = Spider()
    spwder.run()

我们来分析一下这个爬虫模块是如何运行的:首先是新建了一个类,在__init__初始化函数中定义了基本的爬取地址等变量。在getHtmlList方法中提取出了每个论文的详情链接,供在下面循环遍历使用。在
getContent方法中执行了一次插入方法。这里实际上只启动了一个事务。最后在run方法中循环执行插入方法。这个程序的好处在于,对每一个功能做了模块化的封装,提高了运行效率。但python里的插入还是有点慢,加上这是外网,所以爬取过程会耗费一定时间。网页分析就不再赘述,可以自行看代码分析。这里主要使用了xpath进行读取。

web端设计和分析

在搜查了资料后得知,echarts具有词汇云的拓展模块。于是上网搜索了一番后获得了相应的js文件,这东西官网有的下,不再提供下载地址了。对于echarts的用法,近一段时间已经十分熟悉了。这里主要说说service层的处理和点击事件的处理。由于我们从数据库读取的题目中并没有关键字,我们可以在service层对内容进行分析并统计出关键字次数。首先将每个题目都分成一个个单词,然后对单词出现次数做分析,筛选掉无用的介词如for in with等,如下代码:

public class DataService {

	public List<Word> getData() throws SQLException {
		DataDao dao = new DataDao();
		List<Data>  dataList= dao.getData();
		List<Word> wordList = new ArrayList<Word>();
		String [] names = new String[100000];
		for(Data data:dataList) {
			String name = data.getPapername();
			String[] namestemp = name.split(" ");
			names = (String[]) ArrayUtils.addAll(namestemp, names);//把两个字符数组合并。
		}
		HashMap<String, Integer> name_value = new HashMap<>();
		//如果键出现过就+1,没有就记为1
		for(String name:names) {
			name_value.put(name, !name_value.containsKey(name)?1:name_value.get(name)+1);
		}
		//keySet()表示全部键
		for(String name:name_value.keySet()) {
			Word word = new Word();
			if(name!=null&&(name_value.get(name)>1)&&(name.length()>4)) {
				word.setName(name);
				word.setValue(name_value.get(name));
				wordList.add(word);
			}

		}
		return wordList;
	}

至于点击事件,首先在前台输入以下代码:

		chart.on('click', function(params) {
			var url = "clickFunction?name=" + params.name;
			window.location.href = url;

然后就编写servlet等一系列层进行标题的模糊查询,返回集合后在前台读取即可。常规操作了,不再赘述。

总结

本次课堂作业的难度主要体现在爬取。一是外网,二是数据量庞大。加上python插入速度很慢,只能不断优化代码。也提醒我任何关于数据库的操作一定要捕获异常,以免程序会莫名其妙的中断。

posted @ 2020-04-15 17:11  武神酱丶  阅读(614)  评论(0编辑  收藏  举报