SlideShare uma empresa Scribd logo
1 de 22
微博#cpan#机器人
Where is Perl?
老版本不可用!
let's DIY!
申请微博应用
获取应用密钥
设置授权回调页
Dancer -a weiboexp
• package WeiboExp;
• use Dancer ':syntax';
• use Dancer::Plugin::Deferred;
• use Net::OAuth2::Client;
• get '/user/login' => sub {
• redirect &client->authorize;
• };
• true;
• sub client {
• Net::OAuth2::Profile::WebServer->new(
• name => 'weibo',
• site => 'https://api.weibo.com',
• client_id => config->{app_key},
• client_secret => config->{app_secret},
• authorize_path => '/oauth2/authorize',
• access_token_path => '/oauth2/access_token',
• access_token_method => 'POST',
• token_scheme => 'uri-query:access_token',
• redirect_uri => uri_for('/user/profile'),
• );
• };
• get '/user/profile' => sub {
• my $session = &client->get_access_token(params->{code});
• deferred error => $session->error_description if $session->error;
• my $uid_res = $session->get('/2/account/get_uid.json');
• if ( $uid_res->is_success ) {
• my $uid = (decode_json $uid_res->decoded_content)->{'uid'};
• my $ushow_res = $session->get("/2/users/show.json?uid=${uid}");
• if ( $ushow_res->is_success ) {
• my $user = decode_json $ushow_res->decoded_content;
• session user => { name => $user->{'name'}, hdimg => $user-
>{'profile_image_url'} };
• deferred success => sprintf "Welcome back, %s", $user->{name};
• template 'profile', { user => $user };
• }
• } else {
• deferred error => $uid_res->status_line . 'get_uid';
• redirect '/';
• };
• };
weiboexp/views/profile.tx
• <img src="<: $user.avatar_large :>"/><br/>
• 微博地址:<a href="http://weibo.com/<: $user.domain :>">http://weibo.com/<:
$user.domain :></a><br/>
• 签名档:<: $user.description :><br/>
• 住址:<: $user.location :><br/>
• 个人网站:<a href="<: $user.url :>"><: $user.url :></a><br/>
• 最新微博:<: $user.status.text :>
Great, But where is the
bot?
应用授权信息
SO Easy now!
• #!/usr/bin/env perl
• use JSON;
• use 5.010;
• use HTTP::Request;
• use LWP::UserAgent;
• use URI::Escape qw(uri_escape);
• # read from $session->access_token()
• my $token = '2.00kSQGIB1Q6J9C3d32741b********';
• my $session = LWP::UserAgent->new;
• my $api_base = 'https://api.weibo.com';
• while(1) {
• get_mention();
• sleep 30;
• };
• sub get_mention {
• my $mention_res = $session-
>get("${api_base}/2/statuses/mentions.json?access_token=${token}");
• if ( $mention_res->is_success ) {
• my $statuses = ( decode_json $mention_res->decoded_content )-
>{'statuses'};
• my $regexstr = q(#cpan#);
• for my $status ( @{ $statuses } ) {
• my $mid = $status->{'id'};
• my $msg = $status->{'text'};
• if ( $msg =~ s{$regexstr}{}i and $msg =~ s{@ARGVs+?}{}i ) {
• my $ret = uri_escape(mcpan_query($msg));
• my $create_res = $session-
>post("${api_base}/2/comments/create.json?access_token=${token}&id=${
mid}&comment=${ret}");
• if ( $create_res->is_success and ! ( decode_json $create_res-
>decoded_content )->{'error'} ) {
• say "Create Comments OK!";
• }
• }
• }
• }
• }
• sub mcpan_query {
• my $modulename = shift;
• my $ua = LWP::UserAgent->new;
• my $req = HTTP::Request->new( 'POST',
"http://api.metacpan.org/v0/module/_search" );
• $req->header( 'Content-Type' => 'application/json' );
• $req->content(encode_json({
• query => { query_string => { query => $modulename, } },
• filter => { term => { status => 'latest', } },
• fields => [ 'release', 'author' ]
• }));
• my $res = $ua->request( $req );
• return $res->status_line unless $res->is_success;
• my $hits = decode_json $res->decoded_content;
• my @url = keys { map { 'https://metacpan.org/release/' . $_-
>{fields}->{author} . '/' . $_->{fields}->{release} => 1 } @{ $hits-
>{hits}->{hits} } };
• my $short_url = shorten(@url);
• return join ' ', @$short_url;
• }
• sub shorten {
• my $url = shift;
• my $shorten_res = $session-
>get( "${api_base}/2/short_url/shorten.json?access_toke
n=${token}&url_long=" . join('&url_long=', @{$url}) );
• if ( $shorten_res->is_success ) {
• my $urls = ( decode_json $shorten_res-
>decoded_content )->{'urls'};
• my @short_url = map { $_->{url_short} } @{$urls};
• return @short_url;
• } else {
• say $shorten_res->status_line;
• }
• }
结果
see More
• https://github.com/CPAN-API/metacpan-developer
• https://metacpan.org/pod/Net::OAuth2::Client
• https://metacpan.org/pod/Search::Elasticsearch
• http://www.elasticsearch.org/guide/
• http://open.weibo.com/wiki/授权机制说明
• http://open.weibo.com/wiki/微博API
谢谢!

Mais conteúdo relacionado

Mais procurados

ApacheCon NA11 - Apache Celix, Universal OSGi?
ApacheCon NA11 - Apache Celix, Universal OSGi?ApacheCon NA11 - Apache Celix, Universal OSGi?
ApacheCon NA11 - Apache Celix, Universal OSGi?
abroekhuis
 
Twib in Yokoahma.pm 2010/3/5
Twib in Yokoahma.pm 2010/3/5Twib in Yokoahma.pm 2010/3/5
Twib in Yokoahma.pm 2010/3/5
Yusuke Wada
 
High-level Web Testing
High-level Web TestingHigh-level Web Testing
High-level Web Testing
petersergeant
 

Mais procurados (20)

Blog Hacks 2011
Blog Hacks 2011Blog Hacks 2011
Blog Hacks 2011
 
Perl5i
Perl5iPerl5i
Perl5i
 
ApacheCon NA11 - Apache Celix, Universal OSGi?
ApacheCon NA11 - Apache Celix, Universal OSGi?ApacheCon NA11 - Apache Celix, Universal OSGi?
ApacheCon NA11 - Apache Celix, Universal OSGi?
 
エロサイト管理者の憂鬱3 - Hokkaiodo.pm#4 -
エロサイト管理者の憂鬱3 - Hokkaiodo.pm#4 -エロサイト管理者の憂鬱3 - Hokkaiodo.pm#4 -
エロサイト管理者の憂鬱3 - Hokkaiodo.pm#4 -
 
Twib in Yokoahma.pm 2010/3/5
Twib in Yokoahma.pm 2010/3/5Twib in Yokoahma.pm 2010/3/5
Twib in Yokoahma.pm 2010/3/5
 
High-level Web Testing
High-level Web TestingHigh-level Web Testing
High-level Web Testing
 
SQL Injection Part 2
SQL Injection Part 2SQL Injection Part 2
SQL Injection Part 2
 
Drupal, meet Assetic
Drupal, meet AsseticDrupal, meet Assetic
Drupal, meet Assetic
 
Mojolicious - A new hope
Mojolicious - A new hopeMojolicious - A new hope
Mojolicious - A new hope
 
InnoDB Magic
InnoDB MagicInnoDB Magic
InnoDB Magic
 
Mojolicious. Веб в коробке!
Mojolicious. Веб в коробке!Mojolicious. Веб в коробке!
Mojolicious. Веб в коробке!
 
RESTful web services
RESTful web servicesRESTful web services
RESTful web services
 
Bag Of Tricks From Iusethis
Bag Of Tricks From IusethisBag Of Tricks From Iusethis
Bag Of Tricks From Iusethis
 
16.mysql stored procedures in laravel
16.mysql stored procedures in laravel16.mysql stored procedures in laravel
16.mysql stored procedures in laravel
 
Mashing up JavaScript – Advanced Techniques for modern Web Apps
Mashing up JavaScript – Advanced Techniques for modern Web AppsMashing up JavaScript – Advanced Techniques for modern Web Apps
Mashing up JavaScript – Advanced Techniques for modern Web Apps
 
Silex Cheat Sheet
Silex Cheat SheetSilex Cheat Sheet
Silex Cheat Sheet
 
PhoneGap: Local Storage
PhoneGap: Local StoragePhoneGap: Local Storage
PhoneGap: Local Storage
 
Mojolicious on Steroids
Mojolicious on SteroidsMojolicious on Steroids
Mojolicious on Steroids
 
Keep It Simple Security (Symfony cafe 28-01-2016)
Keep It Simple Security (Symfony cafe 28-01-2016)Keep It Simple Security (Symfony cafe 28-01-2016)
Keep It Simple Security (Symfony cafe 28-01-2016)
 
Absolute Beginners Guide to Puppet Through Types - PuppetConf 2014
Absolute Beginners Guide to Puppet Through Types - PuppetConf 2014Absolute Beginners Guide to Puppet Through Types - PuppetConf 2014
Absolute Beginners Guide to Puppet Through Types - PuppetConf 2014
 

Destaque (6)

Queue your work
Queue your workQueue your work
Queue your work
 
Distributed app development with nodejs and zeromq
Distributed app development with nodejs and zeromqDistributed app development with nodejs and zeromq
Distributed app development with nodejs and zeromq
 
Php Inspections (EA Extended): if-conditions optimization
Php Inspections (EA Extended): if-conditions optimizationPhp Inspections (EA Extended): if-conditions optimization
Php Inspections (EA Extended): if-conditions optimization
 
Jenkins Acceleration
Jenkins AccelerationJenkins Acceleration
Jenkins Acceleration
 
Distributed Logging System Using Elasticsearch Logstash,Beat,Kibana Stack and...
Distributed Logging System Using Elasticsearch Logstash,Beat,Kibana Stack and...Distributed Logging System Using Elasticsearch Logstash,Beat,Kibana Stack and...
Distributed Logging System Using Elasticsearch Logstash,Beat,Kibana Stack and...
 
Zero mq logs
Zero mq logsZero mq logs
Zero mq logs
 

Semelhante a Perl调用微博API实现自动查询应答

Simple blog wall creation on Java
Simple blog wall creation on JavaSimple blog wall creation on Java
Simple blog wall creation on Java
Max Titov
 
Introduction to CloudForecast / YAPC::Asia 2010 Tokyo
Introduction to CloudForecast / YAPC::Asia 2010 TokyoIntroduction to CloudForecast / YAPC::Asia 2010 Tokyo
Introduction to CloudForecast / YAPC::Asia 2010 Tokyo
Masahiro Nagano
 
Intro To Moose
Intro To MooseIntro To Moose
Intro To Moose
cPanel
 

Semelhante a Perl调用微博API实现自动查询应答 (20)

Perl web app 테스트전략
Perl web app 테스트전략Perl web app 테스트전략
Perl web app 테스트전략
 
Dutch PHP Conference - PHPSpec 2 - The only Design Tool you need
Dutch PHP Conference - PHPSpec 2 - The only Design Tool you needDutch PHP Conference - PHPSpec 2 - The only Design Tool you need
Dutch PHP Conference - PHPSpec 2 - The only Design Tool you need
 
The Zen of Lithium
The Zen of LithiumThe Zen of Lithium
The Zen of Lithium
 
PHPSpec - the only Design Tool you need - 4Developers
PHPSpec - the only Design Tool you need - 4DevelopersPHPSpec - the only Design Tool you need - 4Developers
PHPSpec - the only Design Tool you need - 4Developers
 
Simple blog wall creation on Java
Simple blog wall creation on JavaSimple blog wall creation on Java
Simple blog wall creation on Java
 
Mashing up JavaScript
Mashing up JavaScriptMashing up JavaScript
Mashing up JavaScript
 
Add loop shortcode
Add loop shortcodeAdd loop shortcode
Add loop shortcode
 
Paypal REST api ( Japanese version )
Paypal REST api ( Japanese version )Paypal REST api ( Japanese version )
Paypal REST api ( Japanese version )
 
HappyKardashian.com for #FVCP
HappyKardashian.com for #FVCPHappyKardashian.com for #FVCP
HappyKardashian.com for #FVCP
 
QA for PHP projects
QA for PHP projectsQA for PHP projects
QA for PHP projects
 
I Don't Care About Security (And Neither Should You)
I Don't Care About Security (And Neither Should You)I Don't Care About Security (And Neither Should You)
I Don't Care About Security (And Neither Should You)
 
An introduction to Laravel Passport
An introduction to Laravel PassportAn introduction to Laravel Passport
An introduction to Laravel Passport
 
Perl Web Client
Perl Web ClientPerl Web Client
Perl Web Client
 
Introduction to CloudForecast / YAPC::Asia 2010 Tokyo
Introduction to CloudForecast / YAPC::Asia 2010 TokyoIntroduction to CloudForecast / YAPC::Asia 2010 Tokyo
Introduction to CloudForecast / YAPC::Asia 2010 Tokyo
 
ApacheCon 2005
ApacheCon 2005ApacheCon 2005
ApacheCon 2005
 
Intro To Moose
Intro To MooseIntro To Moose
Intro To Moose
 
How to build a High Performance PSGI/Plack Server
How to build a High Performance PSGI/Plack Server How to build a High Performance PSGI/Plack Server
How to build a High Performance PSGI/Plack Server
 
WordPress Plugin & Theme Security - WordCamp Melbourne - February 2011
WordPress Plugin & Theme Security - WordCamp Melbourne - February 2011WordPress Plugin & Theme Security - WordCamp Melbourne - February 2011
WordPress Plugin & Theme Security - WordCamp Melbourne - February 2011
 
Becoming a better WordPress Developer
Becoming a better WordPress DeveloperBecoming a better WordPress Developer
Becoming a better WordPress Developer
 
Using WordPress as your application stack
Using WordPress as your application stackUsing WordPress as your application stack
Using WordPress as your application stack
 

Mais de 琛琳 饶 (11)

{{more}} Kibana4
{{more}} Kibana4{{more}} Kibana4
{{more}} Kibana4
 
ELK stack at weibo.com
ELK stack at weibo.comELK stack at weibo.com
ELK stack at weibo.com
 
More kibana
More kibanaMore kibana
More kibana
 
Monitor is all for ops
Monitor is all for opsMonitor is all for ops
Monitor is all for ops
 
Add mailinglist command to gitolite
Add mailinglist command to gitoliteAdd mailinglist command to gitolite
Add mailinglist command to gitolite
 
Skyline 简介
Skyline 简介Skyline 简介
Skyline 简介
 
How ElasticSearch lives in my DevOps life
How ElasticSearch lives in my DevOps lifeHow ElasticSearch lives in my DevOps life
How ElasticSearch lives in my DevOps life
 
Logstash
LogstashLogstash
Logstash
 
DNS协议与应用简介
DNS协议与应用简介DNS协议与应用简介
DNS协议与应用简介
 
Mysql测试报告
Mysql测试报告Mysql测试报告
Mysql测试报告
 
Perl在nginx里的应用
Perl在nginx里的应用Perl在nginx里的应用
Perl在nginx里的应用
 

Último

Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
Joaquim Jorge
 

Último (20)

[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024
 
Tech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdfTech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdf
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 

Perl调用微博API实现自动查询应答

  • 2.
  • 9. Dancer -a weiboexp • package WeiboExp; • use Dancer ':syntax'; • use Dancer::Plugin::Deferred; • use Net::OAuth2::Client; • get '/user/login' => sub { • redirect &client->authorize; • }; • true;
  • 10. • sub client { • Net::OAuth2::Profile::WebServer->new( • name => 'weibo', • site => 'https://api.weibo.com', • client_id => config->{app_key}, • client_secret => config->{app_secret}, • authorize_path => '/oauth2/authorize', • access_token_path => '/oauth2/access_token', • access_token_method => 'POST', • token_scheme => 'uri-query:access_token', • redirect_uri => uri_for('/user/profile'), • ); • };
  • 11. • get '/user/profile' => sub { • my $session = &client->get_access_token(params->{code}); • deferred error => $session->error_description if $session->error; • my $uid_res = $session->get('/2/account/get_uid.json'); • if ( $uid_res->is_success ) { • my $uid = (decode_json $uid_res->decoded_content)->{'uid'}; • my $ushow_res = $session->get("/2/users/show.json?uid=${uid}"); • if ( $ushow_res->is_success ) { • my $user = decode_json $ushow_res->decoded_content; • session user => { name => $user->{'name'}, hdimg => $user- >{'profile_image_url'} }; • deferred success => sprintf "Welcome back, %s", $user->{name}; • template 'profile', { user => $user }; • } • } else { • deferred error => $uid_res->status_line . 'get_uid'; • redirect '/'; • }; • };
  • 12. weiboexp/views/profile.tx • <img src="<: $user.avatar_large :>"/><br/> • 微博地址:<a href="http://weibo.com/<: $user.domain :>">http://weibo.com/<: $user.domain :></a><br/> • 签名档:<: $user.description :><br/> • 住址:<: $user.location :><br/> • 个人网站:<a href="<: $user.url :>"><: $user.url :></a><br/> • 最新微博:<: $user.status.text :>
  • 13. Great, But where is the bot?
  • 16. • #!/usr/bin/env perl • use JSON; • use 5.010; • use HTTP::Request; • use LWP::UserAgent; • use URI::Escape qw(uri_escape); • # read from $session->access_token() • my $token = '2.00kSQGIB1Q6J9C3d32741b********'; • my $session = LWP::UserAgent->new; • my $api_base = 'https://api.weibo.com'; • while(1) { • get_mention(); • sleep 30; • };
  • 17. • sub get_mention { • my $mention_res = $session- >get("${api_base}/2/statuses/mentions.json?access_token=${token}"); • if ( $mention_res->is_success ) { • my $statuses = ( decode_json $mention_res->decoded_content )- >{'statuses'}; • my $regexstr = q(#cpan#); • for my $status ( @{ $statuses } ) { • my $mid = $status->{'id'}; • my $msg = $status->{'text'}; • if ( $msg =~ s{$regexstr}{}i and $msg =~ s{@ARGVs+?}{}i ) { • my $ret = uri_escape(mcpan_query($msg)); • my $create_res = $session- >post("${api_base}/2/comments/create.json?access_token=${token}&id=${ mid}&comment=${ret}"); • if ( $create_res->is_success and ! ( decode_json $create_res- >decoded_content )->{'error'} ) { • say "Create Comments OK!"; • } • } • } • } • }
  • 18. • sub mcpan_query { • my $modulename = shift; • my $ua = LWP::UserAgent->new; • my $req = HTTP::Request->new( 'POST', "http://api.metacpan.org/v0/module/_search" ); • $req->header( 'Content-Type' => 'application/json' ); • $req->content(encode_json({ • query => { query_string => { query => $modulename, } }, • filter => { term => { status => 'latest', } }, • fields => [ 'release', 'author' ] • })); • my $res = $ua->request( $req ); • return $res->status_line unless $res->is_success; • my $hits = decode_json $res->decoded_content; • my @url = keys { map { 'https://metacpan.org/release/' . $_- >{fields}->{author} . '/' . $_->{fields}->{release} => 1 } @{ $hits- >{hits}->{hits} } }; • my $short_url = shorten(@url); • return join ' ', @$short_url; • }
  • 19. • sub shorten { • my $url = shift; • my $shorten_res = $session- >get( "${api_base}/2/short_url/shorten.json?access_toke n=${token}&url_long=" . join('&url_long=', @{$url}) ); • if ( $shorten_res->is_success ) { • my $urls = ( decode_json $shorten_res- >decoded_content )->{'urls'}; • my @short_url = map { $_->{url_short} } @{$urls}; • return @short_url; • } else { • say $shorten_res->status_line; • } • }
  • 21. see More • https://github.com/CPAN-API/metacpan-developer • https://metacpan.org/pod/Net::OAuth2::Client • https://metacpan.org/pod/Search::Elasticsearch • http://www.elasticsearch.org/guide/ • http://open.weibo.com/wiki/授权机制说明 • http://open.weibo.com/wiki/微博API