基于可视化的导航书签

《项链》莫泊桑的

一、         内容

为小说阅读创建一个可视化工具,能够将小说的人物,场景,主题,地点,时间等特征进行可视化,允许读者根据自己的兴趣爱好快速定位到相关内容,提供交互手段生成导航书签并进行书签编辑。

二、         背景介绍

小说因为字数过多,读者可能难以定位到自己感兴趣的地方,也难以了解到故事的主线,通过可视化分析,使小说的内容更加容易被理解和定位,选择分析的小说是莫泊桑的《项链》。我选择了文章之中分析出的人名,地名,时间线作为书签,在页面可以阅读小说,也可以通过书签进行跳转翻页。

三、         数据处理

首先对文章进行词性的分析和分词,运用的工具为THULAC,找出文章中的人名,地名,名词,动词等关键词语,将词语提取出来之后进行词频分析,运用的为java语言,分析之后结果如下:

N:太太:18东西:14丈夫:11店:10晚会:9项链:9朋友:8首饰:8衣裳:7盒子:6时候:6妇人:5手:5事:5车子:5裙袍:4镜子:4数目:4光景:3金刚:3神气:3钱:3颈项:3妻子:3机会:3男宾:3楼:3诱惑力:3珠宝:3样子:3

NP:骆塞尔:8玛蒂尔德:3伏来士洁:2若尔日:1金当郎:1金元:1莫泊桑:1郎波诺:1侍应生:1约翰妮:1南兑尔:1金法郎:1玛蒂尔蒂:1

NS:骆塞尔:6巴黎:1塞纳河:1布列塔尼省:1故宫街:1殉教街:1威尼斯:1香榭丽舍:1

A:小:10好:8大:5女:5伤心:4老:3清:3相同:3痛苦:3精美:3新:3快活:3漂亮:3失望:2真:2一般:2吃惊:2豪华:2一样:2像样:2遗憾:2完全:2高兴:2有钱:2黑:2早:2糊涂:2对:2日常:2骇人:1

V:是:45到:32去:28没有:21可以:16说:16有:14走:13借:10找:10要:10想:9带:8梦想:8能够:8叫:8会:7做:6像:6感到:6应当:6上:5下:5满意:5钻:5看:5对:5成:4回来:4穿:4

通过对关键词的分析绘制小说可视化图像。

四、         可视化设计

1关键词可视化:

运用工具:BLUEMC

 

 

通过文章之中出现次数最多的词语了解文章答题内容,省略部分无意义代词,通过词云可以了解文章大致主题,例如主角为太太,配角有丈夫,主要围绕项链,文中人物动作较多,场景切换有晚会,店里等。

2.制作树状图

制作树状图是为了了解文章大体结构,主要用了文中前30个名词关键词,词频大的在文章之中占比更大,在内容上更加重要,为根节点,词频小一点的为其子节点,查看附近形容词为其延伸词,以此来了解文章大体的结构层次。

 

 

3.制作树形图

文章中共有六章,提取出每章的关键词运用词频进行绘制树形图,通过这个图像可视化可以了解到每一章中的主要内容,方便读者了解到每一章的内容,并且进行相关选择,

定位到每一章。

 

4.制作文章人物关系图

运用Echars模板,通过文章之中出现的人名的次数来区分主角,配角,然后了解人物之间的关系

 

 

5.制作柱状图

柱状图的X轴为时间线,Y轴为地点线,通过文章前五关键词出现次数,了解文章时间和地点的结合点,从而了解文章的时间线和地点线,读者可以选择跳转到自己感兴趣的时间。

6.制作词频分析图

 

 

正为名词,负为动词,通过动词与名词的结合了解到文章在此点的结构和文章的主题变化。

五、    代码实现

环境配置:D3要在wamp中运行,并且有D3的工具包,Echarts要有echarts的工具包,在网页之中有超链接直接连到相应网页

Eclipse运行THULAC工具,可以将总结到的词性和词频输出到文件当中。

用浏览器打开相应的网页可以阅读小说

人物关系图代码(Echarts):

<!DOCTYPE html>

<html>

<head>

    <meta charset="utf-8">

    <title>人物关系图</title>

    <!-- 引入 echarts.js -->

    <script src="echarts.js"></script>

   

</head>

<body>

    <!-- 为ECharts准备一个具备大小(宽高)的Dom -->

    <div id="main" style="width: 1200px;height:650px;"></div>

    <script type="text/javascript">

        // 基于准备好的dom,初始化echarts实例

        var myChart = echarts.init(document.getElementById('main'));

 

        // 指定图表的配置项和数据

        var option = {

    title: {

        text: '人物关系图',

      

    },

    tooltip: {},

    animationDurationUpdate: 1500,

    animationEasingUpdate: 'quinticInOut',

    label: {

        normal: {

            show: true,

            textStyle: {

                fontSize: 18

            },

        }

    },

    legend: {

        x: "center",

        data: ["主角", "配角", '作者','路人']

    },

    series: [

 

        {

            type: 'graph',

            layout: 'force',

            symbolSize: 60,

            focusNodeAdjacency: true,

            roam: true,

            categories: [{

                name: '主角'

            }, {

                name: '配角'

            }, {

                name: '作者'

            }, {

                name: '路人'

            }],

            label: {

                normal: {

                    show: true,

                    textStyle: {

                        fontSize: 18

                    },

                }

            },

            force: {

                repulsion: 2000

            },

          

            edgeLabel: {

                normal: {

                    show: true,

                    textStyle: {

                        fontSize: 18

                    },

                    formatter: "{c}"

                }

            },

            data: [

            {

                name: '太太',

                category: 0,

                 draggable: true,

            },

            {

                name: '玛蒂尔德',

                category: 0 ,

                draggable: true,              

            },

            {

                name: '丈夫',

                category: 0  ,

                 draggable: true,

            },

            {

                name: '骆塞尔',

                category: 0,

                draggable: true,

            },

           

            {

                name: '伏来士洁',

                category: 1,

                draggable: true,

            },

            {

                name: '若尔日',

                category: 1,

                draggable: true,

           ……等人物点

           

            ],

            links: [{

                source: '太太',

                target: '丈夫',

                value: '夫妻',

                lineStyle:{

                    normal:{

                        color:'red',

                    }

                }

               

            },

            {

                source: '丈夫',

                target: '骆塞尔',

                value: '同名'

            },

            {

                source: '太太',

                target: '玛蒂尔德',

                value: '同名'

            },

            {

                source: '莫泊桑',

                target: '太太',

                value: '作者'

            },

            {

                source: '太太',

                target: '伏来士洁',

                value: '朋友,借项链',

              

            },

             ……等人物关系线

            ],

            lineStyle: {

                normal: {

                    opacity: 0.7,

                    width: 2,

                    //curveness: 0.1

                   color:'black',

                }

            }

        }

    ]

};

 

        // 使用刚指定的配置项和数据显示图表。

        myChart.setOption(option);

    </script>

</body>

</html>

树状图:

<!DOCTYPE html>

<style>

 

form {

  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;

}

 

svg {

  font: 10px sans-serif;

}

 

</style>

<svg width="960" height="570"></svg>

<form>

  <label><input type="radio" name="mode" value="sumBySize" checked> Size</label>

  <label><input type="radio" name="mode" value="sumByCount"> Count</label>

</form>

<script src="https://d3js.org/d3.v4.min.js"></script>

<script>

 

var svg = d3.select("svg"),

    width = +svg.attr("width"),

    height = +svg.attr("height");

 

var fader = function(color) { return d3.interpolateRgb(color, "#fff")(0.2); },

    color = d3.scaleOrdinal(d3.schemeCategory20.map(fader)),

    format = d3.format(",d");

 

var treemap = d3.treemap()

    .tile(d3.treemapResquarify)

    .size([width, height])

    .round(true)

    .paddingInner(1);

 

d3.json("flare.json", function(error, data) {

  if (error) throw error;

 

  var root = d3.hierarchy(data)

      .eachBefore(function(d) { d.data.id = (d.parent ? d.parent.data.id + "." : "") + d.data.name; })

      .sum(sumBySize)

      .sort(function(a, b) { return b.height - a.height || b.value - a.value; });

 

  treemap(root);

 

  var cell = svg.selectAll("g")

    .data(root.leaves())

    .enter().append("g")

      .attr("transform", function(d) { return "translate(" + d.x0 + "," + d.y0 + ")"; });

 

  cell.append("rect")

      .attr("id", function(d) { return d.data.id; })

      .attr("width", function(d) { return d.x1 - d.x0; })

      .attr("height", function(d) { return d.y1 - d.y0; })

      .attr("fill", function(d) { return color(d.parent.data.id); });

 

  cell.append("clipPath")

      .attr("id", function(d) { return "clip-" + d.data.id; })

    .append("use")

      .attr("xlink:href", function(d) { return "#" + d.data.id; });

 

  cell.append("text")

      .attr("clip-path", function(d) { return "url(#clip-" + d.data.id + ")"; })

    .selectAll("tspan")

      .data(function(d) { return d.data.name.split(/(?=[A-Z][^A-Z])/g); })

    .enter().append("tspan")

      .attr("x", 4)

      .attr("y", function(d, i) { return 13 + i * 10; })

      .text(function(d) { return d; });

 

  cell.append("title")

      .text(function(d) { return d.data.id + "\n" + format(d.value); });

 

  d3.selectAll("input")

      .data([sumBySize, sumByCount], function(d) { return d ? d.name : this.value; })

      .on("change", changed);

 

  var timeout = d3.timeout(function() {

    d3.select("input[value=\"sumByCount\"]")

        .property("checked", true)

        .dispatch("change");

  }, 2000);

 

  function changed(sum) {

    timeout.stop();

 

    treemap(root.sum(sum));

 

    cell.transition()

        .duration(750)

        .attr("transform", function(d) { return "translate(" + d.x0 + "," + d.y0 + ")"; })

      .select("rect")

        .attr("width", function(d) { return d.x1 - d.x0; })

        .attr("height", function(d) { return d.y1 - d.y0; });

  }

});

 

function sumByCount(d) {

  return d.children ? 0 : 1;

}

 

function sumBySize(d) {

  return d.size;

}

 

</script>

树形图:

<!DOCTYPE html>

<style>

 

form {

  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;

}

 

svg {

  font: 10px sans-serif;

}

 

</style>

<svg width="960" height="570"></svg>

<form>

  <label><input type="radio" name="mode" value="sumBySize" checked> Size</label>

  <label><input type="radio" name="mode" value="sumByCount"> Count</label>

</form>

<script src="https://d3js.org/d3.v4.min.js"></script>

<script>

 

var svg = d3.select("svg"),

    width = +svg.attr("width"),

    height = +svg.attr("height");

 

var fader = function(color) { return d3.interpolateRgb(color, "#fff")(0.2); },

    color = d3.scaleOrdinal(d3.schemeCategory20.map(fader)),

    format = d3.format(",d");

 

var treemap = d3.treemap()

    .tile(d3.treemapResquarify)

    .size([width, height])

    .round(true)

    .paddingInner(1);

 

d3.json("flare.json", function(error, data) {

  if (error) throw error;

 

  var root = d3.hierarchy(data)

      .eachBefore(function(d) { d.data.id = (d.parent ? d.parent.data.id + "." : "") + d.data.name; })

      .sum(sumBySize)

      .sort(function(a, b) { return b.height - a.height || b.value - a.value; });

 

  treemap(root);

 

  var cell = svg.selectAll("g")

    .data(root.leaves())

    .enter().append("g")

      .attr("transform", function(d) { return "translate(" + d.x0 + "," + d.y0 + ")"; });

 

  cell.append("rect")

      .attr("id", function(d) { return d.data.id; })

      .attr("width", function(d) { return d.x1 - d.x0; })

      .attr("height", function(d) { return d.y1 - d.y0; })

      .attr("fill", function(d) { return color(d.parent.data.id); });

 

  cell.append("clipPath")

      .attr("id", function(d) { return "clip-" + d.data.id; })

    .append("use")

      .attr("xlink:href", function(d) { return "#" + d.data.id; });

 

  cell.append("text")

      .attr("clip-path", function(d) { return "url(#clip-" + d.data.id + ")"; })

    .selectAll("tspan")

      .data(function(d) { return d.data.name.split(/(?=[A-Z][^A-Z])/g); })

    .enter().append("tspan")

      .attr("x", 4)

      .attr("y", function(d, i) { return 13 + i * 10; })

      .text(function(d) { return d; });

 

  cell.append("title")

      .text(function(d) { return d.data.id + "\n" + format(d.value); });

 

  d3.selectAll("input")

      .data([sumBySize, sumByCount], function(d) { return d ? d.name : this.value; })

      .on("change", changed);

 

  var timeout = d3.timeout(function() {

    d3.select("input[value=\"sumByCount\"]")

        .property("checked", true)

        .dispatch("change");

  }, 2000);

 

  function changed(sum) {

    timeout.stop();

 

    treemap(root.sum(sum));

 

    cell.transition()

        .duration(750)

        .attr("transform", function(d) { return "translate(" + d.x0 + "," + d.y0 + ")"; })

      .select("rect")

        .attr("width", function(d) { return d.x1 - d.x0; })

        .attr("height", function(d) { return d.y1 - d.y0; });

  }

});

 

function sumByCount(d) {

  return d.children ? 0 : 1;

}

 

function sumBySize(d) {

  return d.size;

}

 

</script>

柱形图:

<!DOCTYPE html>

<html>

<head>

    <meta charset="utf-8">

    <title>ECharts</title>

    <!-- 引入 echarts.js -->

    <script src="echarts.js"></script>

    <script src="http://echarts.baidu.com/resource/echarts-gl-latest/dist/echarts-gl.min.js"></script>

</head>

<body>

    <!-- 为ECharts准备一个具备大小(宽高)的Dom -->

    <div id="main" style="width: 1200px;height:650px;"></div>

    <script type="text/javascript">

        // 基于准备好的dom,初始化echarts实例

        var myChart = echarts.init(document.getElementById('main'));

 

        // 指定图表的配置项和数据

        var hours = ['某晚', '三天后', '第二天', '一月十八', '十二点', '一星期', '十年'];

var days = ['', '朋友家', '晚会',

        '出租车', '小店', '街上'];

var data = [[0,0,9],[0,1,3],[1,1,5],[1,2,4],[2,3,11],[2,4,5],[3,4,5],[4,5,17],[5,6,2]];

option = {

    tooltip: {},

    visualMap: {

        max: 20,

        inRange: {

            color: ['#313695', '#4575b4', '#74add1', '#abd9e9', '#e0f3f8', '#ffffbf', '#fee090', '#fdae61', '#f46d43', '#d73027', '#a50026']

        }

    },

    xAxis3D: {

        type: 'category',

        data: hours

    },

    yAxis3D: {

        type: 'category',

        data: days

    },

    zAxis3D: {

        type: 'value'

    },

    grid3D: {

        boxWidth: 200,

        boxDepth: 80,

        light: {

            main: {

                intensity: 1.2

            },

            ambient: {

                intensity: 0.3

            }

        }

    },

    series: [{

        type: 'bar3D',

        data: data.map(function (item) {

            return {

                value: [item[1], item[0], item[2]]

            }

        }),

        shading: 'color',

 

        label: {

            show: false,

            textStyle: {

                fontSize: 16,

                borderWidth: 1

            }

        },

       

        itemStyle: {

            opacity: 0.4

        },

 

        emphasis: {

            label: {

                textStyle: {

                    fontSize: 20,

                    color: '#900'

                }

            },

            itemStyle: {

                color: '#900'

            }

        }

    }]

}

 

        // 使用刚指定的配置项和数据显示图表。

        myChart.setOption(option);

    </script>

</body>

</html>

 

 

六、    探索发现

通过文章的关键词可以了解到文章的大体结构,从而更加有利于读者的了解,文章的可视化使得文章故事更加立体,提取出的关键更加明了,有利于文章整体构造,通过阅读资料了解,现在已有算法可以通过文章词语了解到文章所表达的情感变换,有利于人们的阅读和分类。

七、    总结

可以对文章进行分词处理,提取出文章的关键词进行分析,通过对文章的不同词语的不同词频的分析,可以得到许多与文章内容相关的提要,使书签制作出来,更加有利于读者的阅读。

 

转载于:https://www.cnblogs.com/merfy/p/8644620.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值