清华大佬耗费三个月吐血整理的几百G的资源,免费分享!....>>>
#!/usr/bin/env perl
use utf8;
use strict;
use warnings;
use 5.010001;
use WWW::Mechanize;
use WWW::Mechanize::Image;
use HTTP::Response;
use JSON::Tiny qw(decode_json encode_json);
$ENV {PERL_LWP_SSL_VERIFY_HOSTNAME} = 0;
binmode STDOUT, ":encoding(utf8)";
# 'http://stackoverflow.com/questions/6795030/how-to-ignore-certificate-verify-failed-error-in-perl'
# 'http://htmlparsing.com/perl.html'
# 'https://metacpan.org/pod/WWW::Mechanize#mech-put-uri-content-content'
# 'https://metacpan.org/pod/HTTP::Response'
# 'https://metacpan.org/pod/LWP::UserAgent'
# 'https://metacpan.org/pod/WWW::Mechanize::Image'
# 'http://www.perlmonks.org/?node_id=737473'
# 'http://stackoverflow.com/questions/10648754/how-do-i-simulate-this-particular-post-request-in-mechanize'
# 'https://kyfw.12306.cn/otn/login/init'
# 'http://dict.youdao.com'
my %url = (
'unlogin' => {
'init' => 'https://kyfw.12306.cn/otn/login/init',
'getcode' => 'https://kyfw.12306.cn/otn/passcodeNew/getPassCodeNew?module=login&rand=sjrand&0.9890632561546399',
'verifycode' => 'https://kyfw.12306.cn/otn/passcodeNew/checkRandCodeAnsyn',
'login' => 'https://kyfw.12306.cn/otn/login/loginAysnSuggest',
},
'logined' => {
'login' => 'https://kyfw.12306.cn/otn/login/userLogin',
'init' => 'https://kyfw.12306.cn/otn/index/initMy12306',
'queryinit' => 'https://kyfw.12306.cn/otn/lcxxcx/init',
'logout' => 'https://kyfw.12306.cn/otn/login/loginOut',
},
);
# query need fill in query data, such as date, from station ..
my $t = 'https://kyfw.12306.cn/otn/lcxxcx/query?purpose_codes=%s&queryDate=%s&from_station=%s&to_station=%s',
my %info = (
'account' => '',
'password' => '',
);
my %train = (
one => {
pc => 'ADULT',
qd => '2016-02-06',
fs => 'BJP',
ts => 'JNK',
rg => 'G\d+',
},
two => {
pc => 'ADULT',
qd => '2016-02-06',
fs => 'JNK',
ts => 'JIK',
rg => '.*',
}
);
my @train = getquery($t, \%train);
my $curr = undef;
our $localpath = 'password/';
#
#
if (! -e $localpath ) {
mkdir($localpath);
}
# read password
{
my $pwdata = slurp($ARGV[0]);
my $pwj = decode_json($pwdata);
$info{password} = $pwj->{password};
$info{account} = $pwj->{account};
}
#
# may be disconnect because of network..
#
###############################################################
my $mech = mechanize();
$mech->get($url{unlogin}{init});
check($mech->success(), "can not access homepage.");
my $localfile = localtime() .".jpg";
downloadImage($url{unlogin}{getcode}, $localfile, $mech);
my $size = -s $localpath.$localfile; # get picture size
if ($size <= 3 * 1024) {
check (0, "picture size -> $size . try latter ..");
}
note("ready input verify code ");
# input such as 1,1 or 2,3 [cell's coordinate you want click on picture ] .
my $randcode = randGet();
note("Verify Code => ".$randcode);
sleep(5);
note("Post to verify");
my $content;
my $res = $mech->post($url{unlogin}{verifycode}, [ 'randCode' => $randcode, 'rand' => 'sjrand' ]);
if ($mech->success && $res->is_success) {
$content = $res->decoded_content;
if ($content =~ /TRUE/) {
note("verify ok");
} else {
note("verify error -> " . $content);
check(0, " quit");
}
} else {
check(0, "can not get respone");
}
sleep(3);
note ("start login");
$res = $mech->post($url{unlogin}{login}, [ 'loginUserDTO.user_name' => $info{account}, 'userDTO.password' => $info{password}, 'randCode' => $randcode ]);
if ($mech->success && $res->is_success) {
$content = $res->decoded_content;
} else {
check(0, "can not get respone");
}
sleep(3);
note("login !!");
$res = $mech->post($url{logined}{login}, [ '_json_attr' => '' ]);
if ($mech->success && $res->is_success) {
$content = $res->decoded_content;
} else {
check(0, "can not get respone");
}
sleep(3);
note("init my 12306");
$mech->get($url{logined}{init});
check($mech->success(), "can not access ".$url{logined}{init});
sleep(3);
note("init lcxxcx");
$mech->get($url{logined}{queryinit});
check($mech->success(), "can not access ".$url{logined}{queryinit});
while (1) {
if (! -e "run.flag") {
last;
}
if (!defined($curr)) {
$curr = shift @train;
} else {
sleep(5);
note("query ...");
$mech->get($curr);
check($mech->success(), "can not access ".$curr);
my @tickets = gettickets(decode_json($mech->content));
say join("\t", ("车次", "始发", "终点", "出发", "目的", "开车", "到站", "历时", "二等座", "硬座"));
for my $ticket (@tickets) {
say join("\t", (
$ticket->{station_train_code},
$ticket->{start_station_name},
$ticket->{end_station_name},
$ticket->{from_station_name},
$ticket->{from_station_name},
$ticket->{to_station_name},
$ticket->{from_station_name},
$ticket->{to_station_name},
$ticket->{lishi},
$ticket->{'ze_num'},
$ticket->{'yz_num'},
));
}
}
}
sleep(3);
note("loginOut");
$mech->get($url{logined}{logout});
check($mech->success(), "can not access ".$url{logined}{logout});
exit;
#####################################
#$info{train} = $term->{station_train_code};
#$info{start} = $term->{start_station_name};
#$info{end} = $term->{end_station_name};
#$info{from} = $term->{from_station_name};
#$info{to} = $term->{to_station_name};
#$info{start_time} = $term->{from_station_name};
#$info{arrive_time} = $term->{to_station_name};
#$info{time} = $term->{lishi};
#$info{'seat-g'} = $term->{'ze_num'};
#$info{'seat-y'} = $term->{'yz_num'};
sub gettickets {
my $json = shift;
if (! $json->{status}) {
return undef;
}
my $data = $json->{data};
my @all;
for my $term (@{$data->{datas}}) {
push @all, $term;
}
return @all;
}
sub getquery {
my $template = shift;
my $train = shift;
my @all;
for (keys %{$train}) {
my $o = $train->{$_};
my $str = sprintf $t, $o->{pc}, $o->{qd}, $o->{fs}, $o->{ts};
push @all, $str;
}
return @all;
}
sub slurp {
my $file = shift;
open my $fh, '<', $file or die "Open $file failed!";
local $/ = undef;
my $data = <$fh>;
close $fh;
return $data;
}
sub getline {
while(<STDIN>) {
chomp;
return $_;
}
}
sub randGet {
my $verify_code = "";
while (<STDIN>) {
chomp;
if (/\A\Z/) {
return $verify_code;
} else {
if ($verify_code =~ /\A\Z/) {
$verify_code = point(split(/,/, $_));
} else {
$verify_code = $verify_code . ',' . point(split(/,/, $_));
}
}
}
}
sub point {
my ($y, $x) = @_;
my $rx = ($x - 1) * 73 + 36;
my $ry = ($y - 1) * 95 + 47;
return "$rx,$ry";
}
sub downloadImage {
my ($url, $local, $mech) = @_;
if (!defined($mech)) {
$mech = mechanize();
}
if ($url) {
$mech->get($url, ':content_file' => $localpath.$local);
check($mech->success(), "can not get image -> ".$url);
} else {
check(0, "image is null");
}
}
sub mechanize {
my $mech = WWW::Mechanize->new('ssl_opts' => { 'verify_hostname' => 0, SSL_verify_mode => 'SSL_VERIFY_NONE' });
### settings
$mech->agent_alias('Windows Mozilla');
return $mech;
}
sub note {
my $str = shift;
say "+ -> $str";
}
sub check {
my ($bool, $msg) = @_;
unless ($bool) {
print $msg."\n";
exit(1);
}
}