标题: [原创代码] [Perl][LWP]获取中行外汇牌价的历史记录 [打印本页]
作者: 523066680 时间: 2015-8-24 23:07 标题: [Perl][LWP]获取中行外汇牌价的历史记录
本帖最后由 523066680 于 2018-10-30 18:43 编辑
2018-10 补充
项目地址:https://github.com/vicyang/Exchange-Rates
git clone git@github.com:vicyang/Exchange-Rates.git
环境配置
推荐 Strawberry Perl Portable PDL Edition
在 Strawberry Perl 的基础上需要添加的模块
Font::FreeType
HTML::TableExtract
Math::Geometry::Delaunay
作者: 523066680 时间: 2015-8-24 23:13
数据展示,我已做成动图
作者: 523066680 时间: 2015-8-29 09:44
补上动态图的对应代码- =info
- 滚动显示外汇牌价某一项的变动
- 额外依赖的模块:OpenGL
- 依赖的文件:Year_USD.txt (中行外汇牌价的历史记录)
-
- 编写:523066680
- 日期:2015-08
- 使用:按 w a s d 调整观察角度,按字母q退出
- 备注:左下角显示年/月,左侧显示汇率轴,每条线左侧显示日期
- =cut
-
- use Encode;
- use utf8;
- use v5.16;
- use IO::Handle;
- use OpenGL qw/ :all /;
- use OpenGL::Config;
- use Time::HiRes 'sleep';
- use feature 'state';
- STDOUT->autoflush(1);
-
- our $file = "Year_USD.txt";
- our $hash = {};
- our @dates;
- our $rx = 0.0;
- our $ry = 0.0;
- our $movex = 0;
- our @arr;
-
- loading();
-
- &Main();
-
- sub printstr
- {
- for my $i ( split("", $_[0]) )
- {
- glutBitmapCharacter(GLUT_BITMAP_9_BY_15, ord($i));
- }
- }
-
- sub display
- {
- our $movex;
- state $step = 120;
- our $ry;
- our $rx;
- our @array;
- our @dates;
- our @color_idx;
- our %hash;
-
- my $scale = 1.2;
-
- if ( ($movex + 15) > $#dates )
- {
- $movex = $#dates - 15;
- }
-
- if ( $movex < 0 )
- {
- $movex = 0;
- }
-
-
- my $i;
- my ($x, $y, $z);
-
- glClear(GL_COLOR_BUFFER_BIT);
-
- glPushMatrix();
- glTranslatef(60.0, 60.0, 0.0);
- glRotatef($rx, 1.0, 0.0, 0.0);
- glRotatef($ry, 0.0, 1.0, 0.0);
- glColor3f(1.0, 1.0, 1.0);
-
- #汇率轴
- for (my $i = 600.0; $i<=645.0; $i+=1.0)
- {
- glColor3f( @{$color_idx[ int ( ($i-600)*100*0.02 ) ]}{'R','G','B'} );
- glRasterPos3f( -20.0, ($i-600)*10*$scale, 0.0);
- printstr( sprintf("%.1f", $i) );
- }
-
-
- glColor3f(1.0, 1.0, 1.0);
- glRasterPos3f(0, 0 , 0.0);
- $dates[$movex] =~ /^(\d+\.\d+)/;
- printstr( $1 );
-
- $z=0.0;
-
- for my $day ((0+$movex) .. (15+$movex))
- {
- my $d = $dates[ $day ];
-
- glBegin(GL_LINE_STRIP);
- for my $i (sort keys %{$hash{ $d }} )
- {
- $i =~/(\d+):(\d+)/;
- $x = int("$1$2")/10;
- $y = ${$hash{ $d }{$i}}[0];
-
- glColor3f( @{$color_idx[ int ( ($y-600)*100*0.02 ) ]}{'R','G','B'} );
- glVertex3f( $x, ($y-600)*10*$scale , $z);
- }
-
- glEnd();
- glRasterPos3f(-10.0, ($y-600)*10*$scale+10.0 , $z);
- glColor3f(0.0, 0.0, $z/5000.0);
- $d=~/(\d+)\.(\d+)\.(\d+)/;
- printstr( int($3) );
-
- $z += 20.0;
- }
-
- glPopMatrix();
- glutSwapBuffers();
-
- #sleep 1.0;
- #OVER();
- }
-
- sub OVER
- {
- our $WinID;
- glutDestroyWindow($WinID);
- exit;
- }
-
- sub init {
- glClearColor(0.0, 0.0, 0.0, 1.0);
- glPointSize(1.0);
- glLineWidth(1.0);
- }
-
- sub idle
- {
- sleep 0.05;
- $movex += 1;
- glutPostRedisplay();
- }
-
- sub Reshape
- {
- my $half = 200.0;
- glViewport(0.0,0.0,800.0,800.0);
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- glOrtho(-30.0, 800.0,-30.0, 800.0,0.0, 5000.0);
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
- gluLookAt(0.0,0.0, 2500.0,0.0,0.0,0.0, 0.0, 1.0,2500.0);
- }
-
- sub hitkey
- {
- our $rx;
- our $movex;
- our $WinID;
- my $keychar = lc(chr(shift));
-
- given ($keychar)
- {
- when ('q')
- {
- glutDestroyWindow($WinID);
- }
- when ('w')
- {
- $rx+=2.0;
- glutPostRedisplay();
- }
- when ('s')
- {
- $rx-=2.0;
- glutPostRedisplay();
- }
- when ('a')
- {
- $ry+=2.0;
- glutPostRedisplay();
- }
- when ('d')
- {
- $ry-=2.0;
- glutPostRedisplay();
- }
- when ('o')
- {
- $movex-=1;
- glutPostRedisplay();
- }
- when ('p')
- {
- $movex+=1;
- glutPostRedisplay();
- }
- when ('r')
- {
- $movex=0;
-
- glutPostRedisplay();
- }
-
- }
- }
-
- sub Main
- {
- glutInit();
- glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE |GLUT_MULTISAMPLE );
- glutInitWindowSize(800, 800);
- glutInitWindowPosition(1,1);
- our $WinID = glutCreateWindow("title");
- &init();
- glutDisplayFunc(\&display);
- glutReshapeFunc(\&Reshape);
- glutKeyboardFunc(\&hitkey);
- glutIdleFunc(\&idle);
- glutMainLoop();
- }
-
- sub loading
- {
- our @dates;
- our $file;
- our %hash;
-
- my @data;
-
- open READ,"<:raw", $file or die "$!";
- for my $line (<READ>)
- {
- next if ($line =~/^\r?\n$/);
- @data = split(/\s/, $line);
- $hash{ $data[7] }{ $data[8] } = [ @data[1..6] ];
- }
-
- for my $d (sort keys %hash)
- {
- push @dates, $d;
- }
-
- close READ;
- }
-
- BEGIN
- {
- my $size = 100 - 1;
-
- our @color_idx;
-
- #初始化RGB
- for my $i (0 .. $size)
- {
- push @color_idx, {
- 'R' => 0.0,
- 'G' => 0.0,
- 'B' => 0.0,
- };
- }
-
- #填充颜色(线性延伸)
- fill_color(30, 30, 1.0, 0.0, 0.0);
- fill_color(50, 40, 0.0, 1.0, 0.0);
- fill_color(70, 40, 0.0, 0.0, 1.0);
- fill_color(100, 30, 1.0, 0.2, 0.2);
-
- sub fill_color
- {
- my %insert;
- @{insert}{'offset', 'length', 'R', 'G', 'B'} = @_;
- my $site;
- my $ref;
- my $tc;
-
- for my $i ( -$insert{length} .. $insert{length} )
- {
- $site = $i + $insert{offset};
- next if ($site < 0 or $site > $size);
-
- $ref = $color_idx[$site];
-
- for my $c ('R', 'G', 'B')
- {
- $tc = $insert{$c} - abs( $insert{$c} / $insert{length} * $i), #等量划分 * step
- $ref->{$c} = $ref->{$c} > $tc ? $ref->{$c} : $tc ;
- }
- }
- }
-
- }
-
- __END__
- 参考
-
- 货币名称 美元
- 现汇买入价 637.72
- 现钞买入价 632.61
- 现汇卖出价 640.28
- 现钞卖出价 640.28
- 中行折算价 639.75
- 发布日期 2015-08-16
- 发布时间 10:30:00
复制代码
作者: 523066680 时间: 2017-10-13 16:21
本帖最后由 523066680 于 2017-10-13 16:23 编辑
多线程版,提取速度比以前快很多。代码怎么写都觉得难看 。。。- =info
- 获取中行外汇牌价-美元栏目的信息
- Auth: 523066680
- Date: 2017-10
- https://github.com/vicyang/Exchange-Rates
- =cut
-
- use Encode;
- use threads;
- use threads::shared;
- use Time::HiRes qw/sleep/;
- use Time::Local;
- use File::Slurp;
- use Data::Dump qw/dump/;
- use Data::Dumper;
- use LWP::UserAgent;
- use HTML::TableExtract;
-
- use IO::Handle;
- STDOUT->autoflush(1);
- $Data::Dumper::Indent = 1;
- $Data::Dump::INDENT = " ";
-
-
- our $URL = "http://srh.bankofchina.com/search/whpj/search.jsp";
- our $ua = LWP::UserAgent->new(
- timeout => 5, keep_alive => 1, agent => 'Mozilla/5.0',
- );
-
- our %hash :shared;
- our @task :shared;
- $hash = shared_clone( {} );
-
- my $from = time_to_date(time() - 24*3600*1);
- my $to = time_to_date(time());
-
- my $pageid = 1;
- my @ths;
- grep { push @ths, threads->create( \&func, $from, $to, $_ ) } ( 0 .. 5 );
-
- #循环插入任务,等待线程结束
- while ( threads->list( threads::running ) )
- {
- grep
- {
- $task[$_] = $pageid++ if ( $task[$_] == 0 );
- }
- (0..5);
- }
-
- #分离线程
- grep { $_->detach() } @ths;
-
- write_file( "hash.perldb", { binmode => ":raw" }, Dumper \%hash );
- printf("Done\n");
-
- sub func
- {
- my ($from, $to, $idx) = @_;
- my $content;
-
- while (1)
- {
- if ( $task[$idx] == 0 ) { sleep 0.1; next; }
-
- $content = get_page( $from, $to, $task[$idx] );
- $content =~/var m_nCurrPage = (\d+)/;
- last if ( $1 != $task[$idx] );
-
- printf "[%d] mission: %d\n", $idx, $task[$idx];
- get_info( $content );
-
- #归零
- $task[$idx] = 0;
- }
- }
-
- sub get_info
- {
- our %hash;
- my $html_str = shift;
-
- # count => 1 表示选择第二个表格。
- my $obj = HTML::TableExtract->new( depth => 0, count => 1 );
- $obj->parse($html_str);
-
- my $table;
- grep { $table = $_ } $obj->tables;
-
- my $timestamp;
- for my $row ( $table->rows )
- {
- =info
- 去掉第一行抬头
- 去掉第一列货币类型
- 表格最后一行为空
- =cut
- shift @$row;
- next if ( $row->[1] eq '' );
- next if ( not $row->[1] =~/\d/ );
-
- $timestamp = pop @$row;
- $hash{ $timestamp } = shared_clone([ @$row ]);
- }
- }
-
- sub get_page
- {
- our $ua;
- my ($from, $to, $pageid) = @_;
- my $res;
- $res = $ua->post(
- $URL,
- [
- erectDate => $from,
- nothing => $to,
- pjname => "1316",
- page => $pageid
- ]
- );
- return $res->content();
- }
-
- sub time_to_date
- {
- my ($sec, $min, $hour, $day, $mon, $year) = localtime( shift );
- $mon += 1;
- $year += 1900;
- return sprintf "%d-%02d-%02d", $year,$mon,$day;
- }
复制代码
作者: 523066680 时间: 2017-10-22 21:45 标题: 高清重置版
本帖最后由 523066680 于 2017-10-22 21:50 编辑
高清重置版 。。。俗称“炒冷饭”。
作者: happy886rr 时间: 2017-10-23 21:50
回复 5# 523066680
还是统计图好看。 你设计天赋很强,总是能找到最佳的呈现方式,去打动坛友。
作者: 523066680 时间: 2017-10-24 18:09
本帖最后由 523066680 于 2017-10-24 20:41 编辑
只为花俏。要说直观,我工作中用了几天还是单纯的线条图更通透。
欢迎光临 批处理之家 (http://www.bathome.net/) |
Powered by Discuz! 7.2 |