Попытка ввода переменной в URL и проблемы с кодировкой - PullRequest
0 голосов
/ 09 июня 2018

Я новичок в Perl и пытаюсь создать сценарий, который принимает ввод от пользователя, а затем получает данные XML с веб-сайта на основе этого ввода вместе с URL-адресом, а затем передает его обратно пользователю.

Но теперь у меня возникли некоторые проблемы с созданием полезной ссылки на основе ввода от пользователя.

Это мой код полностью:

use strict;
use warnings;

my $row = 0;

use XML::LibXML;

print "\n\n\nOn what place do you need a weather report for? -> ";

chomp( my $ort = <> );

my $url = join('', "http://www.yr.no/place/Sweden/Västra_Götaland/",$ort,"/forecast_hour_by_hour.xml");

my $dom = XML::LibXML->load_xml(location => $url);

print "\n\nSee below the weather for ", $ort, ":\n\n";

foreach my $weatherdata ($dom->findnodes('//time')) {

    if($row != 10){ 

        my $temp = $weatherdata->findvalue('./temperature/@value');
        my $value = $weatherdata->findvalue('./@from');

        my $valuesub = substr $value, 11, 5;

        print "At ", $valuesub, " the temperature will be: ", $temp, "C\n";

        $row++;
    }
}

print "\n\n";

Если я напишу нужное местоинформация о погоде.Например:

Mellerud

Тогда это происходит, и я получаю ответ по ссылке с достоверными данными.Тем не мение.Если я напишу

Ом

Это не имеет никакого смысла для сценария.Теперь я получаю:

Не удалось создать контекст синтаксического анализатора для файла "http://www.yr.no/place/Sweden/V├ñstra_G├Âtaland/Åmål/forecast_hour_by_hour.xml": Нет ошибки в строке test4.pl 14

Если я заменил ",$ort," и просто добавьте Åmål Я получаю лучший результат. Я искал различные типы кодирования для этого, но я не нашел решения, которое работает.

Еще раз я хотел бы отметить, чтоЯ действительно новичок в этом. Я мог бы пропустить что-то действительно простое. Мои извинения за это.

:: EDIT 1 ::

После предложения от @zdim я добавил use open ':std', ':encoding(UTF-8)';

Это добавило несколько других результатов, но только генерирует больше ошибок, как показано здесь:

enter image description here

Также я запускаю это в Windows CMD под администраторомпривилегии. Согласно @zdim, он отлично работает в Linux с xterm для ввода, v5.16. Есть ли способ заставить его работать в Windows?

1 Ответ

0 голосов
/ 09 июня 2018

Проблема в том, что CMD.exe ограничен 8-битными кодовыми страницами.Символы "Å" и "å" отображаются (в шведской Windows) на позиции в верхнем 8-битном диапазоне кодовой страницы 850, которые являются недопустимыми кодовыми точками в Unicode.

Если вам нужновыводите не-7-битные символы ASCII, рассмотрите возможность запуска PowerShell ISE.Если вы установите его правильно, он может справиться с любым символом (в выводе), который поддерживает используемый вами шрифт.Большим недостатком является то, что PowerShell ISE не является консолью и поэтому не позволяет вводить данные с консоли / клавиатуры с использованием STDIN.Вы можете обойти это, предоставив свои входные данные в качестве аргументов, из конвейера, в файле настроек или через элементы запроса графического интерфейса пользователя.

Чтобы настроить Windows PowerShell ISE для работы с UTF8:

  1. Установите PowerShell, чтобы разрешить запуск локальных неподписанных пользовательских сценариев, запустив (в PowerShell с повышенными правами администратора):

    Set-ExecutionPolicy RemoteSigned
    
  2. Создание или редактирование файла "<Documents>\WindowsPowerShell\Microsoft.PowerShellISE_profile.ps1"и добавьте что-то вроде:

    perl -w -e 'print qq!Initializing with Perl...\n!;'
    [System.Console]::OutputEncoding = [System.Text.Encoding]::UTF8;
    

    (вам необходим бит Perl (или что-то эквивалентное) для изменения кодировки.)

  3. В PowerShellПараметры ISE, установите шрифт Consolas.

  4. В ваших сценариях perl всегда выполняйте:

    binmode(STDOUT, ':encoding(UTF-8)');
    binmode(STDERR, ':encoding(UTF-8)');
    

Мое решение проблемы ОП:

use strict;
use warnings;

my $row = 0;

use XML::LibXML;

binmode(STDOUT, ':encoding(UTF-8)');
binmode(STDERR, ':encoding(UTF-8)');

@ARGV  or  die "No arguments!\n";

my $ort = shift @ARGV;

print "\n\n\nGetting weather report for \"$ort\"\n";

my $url = join('', "http://www.yr.no/place/Sweden/Västra_Götaland/",$ort,"/forecast_hour_by_hour.xml");

my $dom = XML::LibXML->load_xml(location => $url);

print "\n\nSee below the weather for ", $ort, ":\n\n";

foreach my $weatherdata ($dom->findnodes('//time')) {

    if($row != 10){ 

        my $temp = $weatherdata->findvalue('./temperature/@value');
        my $value = $weatherdata->findvalue('./@from');

        my $valuesub = substr $value, 11, 5;

        print "At ", $valuesub, " the temperature will be: ", $temp, "C\n";

        $row++;
    }
}

print "\n\n";

Выход:

(работает около 2018-06-09T14: 05 UTC; 16:05 CEST (часовой пояс Швеции)):

PS (censored)> perl -w $env:perl5lib\Tests\Amal-Test.pl "Åmål"



Getting weather report for "Åmål"


See below the weather for Åmål:

At 17:00 the temperature will be: 27C
At 18:00 the temperature will be: 26C
At 19:00 the temperature will be: 25C
At 20:00 the temperature will be: 23C
At 21:00 the temperature will be: 22C
At 22:00 the temperature will be: 21C
At 23:00 the temperature will be: 20C
At 00:00 the temperature will be: 19C
At 01:00 the temperature will be: 18C
At 02:00 the temperature will be: 17C

Еще одно примечание:

Опора на данные, которые всегда находятся в точном положении в строке, может быть не лучшей идеей.

Вместо:

my $valuesub = substr $value, 11, 5;

, возможно, стоит вместо этого сопоставить его с регулярным выражением:

if ($value =~ /T((?:[01]\d|2[0-3]):[0-5]\d):/) {
    my $valuesub = $1;
    print "At ", $valuesub, " the temperature will be: ", $temp, "C\n";    }
else {
    warn "Malformed value: $value\n";
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...