#!/usr/bin/perl -w
use
if
DEBUG,
'Smart::Comments'
;
our
$VERSION
=
'1.64_03'
;
our
$DISPLAY
=
'Euronext'
;
our
@LABELS
=
qw/name symbol price last date time p_change bid ask offer open high low close volume currency method exchange/
;
our
$METHODHASH
= {
subroutine
=> \
&aex
,
display
=>
$DISPLAY
,
labels
=> \
@LABELS
};
sub
labels {
my
%m
= methodinfo();
return
map
{
$_
=> [@{
$m
{
$_
}{labels}}] }
keys
%m
;
}
sub
methodinfo {
return
(
euronext
=>
$METHODHASH
,
dutch
=>
$METHODHASH
,
aex
=>
$METHODHASH
,
);
}
sub
methods {
my
%m
= methodinfo();
return
map
{
$_
=>
$m
{
$_
}{subroutine} }
keys
%m
;
}
sub
aex {
my
$quoter
=
shift
;
my
$ua
=
$quoter
->user_agent();
my
$agent
=
$ua
->agent;
$ua
->agent(
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36'
);
my
%info
;
my
$url
;
my
$reply
;
foreach
my
$symbol
(
@_
) {
my
(
$isin
,
$mic
);
my
$search
=
$EURONEXT_URL
.
$symbol
;
$reply
=
$ua
->get(
$search
);
if
(not
defined
$reply
->previous) {
my
$widget
= scraper {
process
'table#awl-lookup-instruments-directory-table a'
,
'link[]'
=>
'@href'
;
};
my
$result
=
$widget
->scrape(
$reply
);
unless
(
exists
$result
->{
link
} and @{
$result
->{
link
}} > 0) {
$info
{
$symbol
,
'success'
} = 0;
$info
{
$symbol
,
'errormsg'
} =
'Cannot find symbol '
.
$symbol
;
next
;
}
for
my
$newlink
(@{
$result
->{
link
}}) {
if
(
$newlink
!~ /product\/indices/i ) {
$url
=
$newlink
;
last
;
}
}
unless
(
defined
(
$url
) &&
$url
->as_string =~ m|/([A-Za-z0-9]{12})-([A-Za-z]+\b)|) {
$info
{
$symbol
,
'success'
} = 0;
$info
{
$symbol
,
'errormsg'
} =
'Cannot find ISIN for '
.
$symbol
;
next
;
}
else
{
$isin
=
uc
($1);
$mic
=
uc
($2);
}
}
else
{
my
$widget
= scraper {
process
'a'
,
'redirect'
=>
'@href'
;
};
my
$result
=
$widget
->scrape(
$reply
->previous->content);
unless
(
exists
$result
->{redirect}) {
$info
{
$symbol
,
'success'
} = 0;
$info
{
$symbol
,
'errormsg'
} =
'Cannot find symbol '
.
$symbol
.
' in redirect'
;
next
;
}
my
$url
=
$result
->{redirect};
unless
(
$url
=~ m|/([A-Za-z0-9]{12})-([A-Za-z]+\b)|) {
$info
{
$symbol
,
'success'
} = 0;
$info
{
$symbol
,
'errormsg'
} =
'Cannot find ISIN for '
.
$symbol
.
' in redirect'
;
next
;
}
$isin
=
uc
($1);
$mic
=
uc
($2);
}
unless
(
defined
$isin
) {
$info
{
$symbol
,
'success'
} = 0;
$info
{
$symbol
,
'errormsg'
} =
'No ISIN set for '
.
$symbol
;
next
;
}
if
($@) {
my
$error
=
"Search failed: $@"
;
$info
{
$symbol
,
'success'
} = 0;
$info
{
$symbol
,
'errormsg'
} = trim(
$error
);
next
;
}
my
%form
= (
theme_name
=>
'euronext_live'
);
$reply
=
$ua
->post(
$url
, \
%form
);
my
$widget
= scraper {
process
'h1#header-instrument-name strong'
,
'name'
=> [
'TEXT'
,
sub
{trim(
$_
)}];
process
'span#header-instrument-price'
,
'last'
=> [
'TEXT'
,
sub
{trim(
$_
)}];
process
'div.ml-2.last-price-date-time'
,
'date'
=> [
'TEXT'
,
sub
{trim(
$_
)}];
};
my
$header
=
$widget
->scrape(
$reply
);
$reply
=
$ua
->get(
$url
);
$widget
= scraper {
process
'div.table-responsive td:first-child, div.table-responsive td:first-child + td'
,
'data[]'
=> [
'TEXT'
,
sub
{trim(
$_
)}];
};
my
$body
=
$widget
->scrape(
$reply
);
unless
(
exists
$body
->{data}) {
$info
{
$symbol
,
'success'
} = 0;
$info
{
$symbol
,
'errormsg'
} =
'Failed to find detailed quote table'
;
next
;
}
my
%table
= @{
$body
->{data}};
$info
{
$symbol
,
'success'
} = 1;
$info
{
$symbol
,
'currency'
} =
$table
{Currency};
$info
{
$symbol
,
'volume'
} =
$table
{Volume};
$info
{
$symbol
,
'volume'
} =~ s/,//g;
$info
{
$symbol
,
'open'
} =
$table
{Open};
$info
{
$symbol
,
'close'
} =
$table
{
"Previous Close"
};
$info
{
$symbol
,
'high'
} =
$table
{High};
$info
{
$symbol
,
'low'
} =
$table
{Low};
$info
{
$symbol
,
'name'
} =
$header
->{name};
$info
{
$symbol
,
'isin'
} =
$isin
;
$info
{
$symbol
,
'last'
} =
$header
->{
last
};
$quoter
->store_date(\
%info
,
$symbol
, {
eurodate
=> $1})
if
$header
->{date} =~ m|([0-9]{2}/[0-9]{2}/[0-9]{4}) - ([0-2][0-9]:[0-5][0-9])|;
$info
{
$symbol
,
'time'
} = $2
if
$2;
my
%mic2location
= (
"XAMS"
=>
"Amsterdam"
,
"XBRU"
=>
"Brussels"
,
"ALXB"
=>
"Brussels"
,
"MLXB"
=>
"Brussels"
,
"XMSM"
=>
"Dublin"
,
"XESM"
=>
"Dublin"
,
"XLIS"
=>
"Lisbon"
,
"ENXL"
=>
"Lisbon"
,
"ALXL"
=>
"Lisbon"
,
"MTAA"
=>
"Milan"
,
"BGEM"
=>
"Milan"
,
"MTAH"
=>
"Milan"
,
"ETLX"
=>
"Milan"
,
"ETFP"
=>
"Milan"
,
"XOSL"
=>
"Oslo"
,
"XOAS"
=>
"Oslo"
,
"MERK"
=>
"Oslo"
,
"XPAR"
=>
"Paris"
,
"ALXP"
=>
"Paris"
,
"XMLI"
=>
"Paris"
,
);
$info
{
$symbol
,
'exchange'
} =
exists
(
$mic2location
{
$mic
}) ?
$mic2location
{
$mic
} :
$mic
;
if
($@) {
my
$error
=
"Fetch/Parse failed: $@"
;
$info
{
$symbol
,
'success'
} = 0;
$info
{
$symbol
,
'errormsg'
} = trim(
$error
);
next
;
}
}
$ua
->agent(
$agent
);
return
wantarray
() ?
%info
: \
%info
;
}
1;