Обработка ошибки 404–Not Found функцией Web.Contents() в Power Query и Power BI

Текст представляет собой адаптированный перевод статьи Chris Webb (Крис Вебб), оригинал – Handling 404–Not Found Errors With Web.Contents() In Power Query And Power BI. Рассматривается англоязычный Power Query.

Об авторе

Крис Вебб (Chris Webb) — независимый эксперт, консультант по технологиям Analysis Services, MDX, Power Pivot, DAX, Power Query и Power BI. Его блог — это кладезь информации на тему перечисленных технологий. Вот уже более 10 лет он пишет про BI-решения от Microsoft. Количество его статей перевалило за 1000! Также Крис выступает на большом количестве различных конференций вроде SQLBits, PASS Summit, PASS BA Conference, SQL Saturdays и участвует в различных сообществах.
Крис любезно разрешил нам переводить его статьи на русский язык. И это одна из них.

Обработка ошибки 404–Not Found функцией Web.Contents() в Power Query и Power BI

Одно из странных свойств функции Web.Contents() в Power Query и Power BI это то, что она не обрабатывает стандартные ошибки привычным в языке М способом. Трудно сказать баг это или фича, но подобная ситуация встречается довольно часто. Поэтому мы решили поделиться описанием проблемы и способом обойти её.

Во-первых, так в чём проблема? Представим, что мы хотим импортировать в Power Query или список курсов UK Microsoft BI and SQL Server компании Technitrain. Для этого можно воспользоваться функцией Web.Contents() и получить данные с RSS feed. Например, так:

let  
   Source = Web.Contents("http://technitrain.com/feed/")  
in  
   Source  

Но что произойдёт, если будет ошибка в адресе URL или другие проблемы на сайте? Следующая ссылка вернёт ошибку 404 – Not Found, т.к. страница не существует:

http://technitrain.com/blahblah

Если мы сделаем такой запрос:

let  
   Source = Web.Contents("http://technitrain.com/blahblah")  
in  
   Source  

Естественно, получим ошибку:

DataSource.Error: Web.Contents failed to get contents from ‘http://technitrain.com/blahblah’ (404): Not Found

(Ошибка источника данных: Web.Contents не удалось получить данные с ‘http://technitrain.com/blahblah’ (404): Не найдено)

p1.png

Хоть это и реальная проблема, попробуем обработать ошибку с помощью оператора try/otherwise:

let  
   Source = try  
               Web.Contents("http://technitrain.com/blahblah")  
            otherwise  
               "Error!"  
in  
   Source  

И это не работает, мы получаем ту же самую ошибку. Что удивительно, в некоторых случаях с более сложным кодом блок try/otherwise срабатывает. Например, здесь:

let  
   Source = try  
               Xml.Tables(  
                Web.Contents("http://technitrain.com/blahblah")  
               )  
            otherwise  
               "Error!"  
in  
   Source  

Ошибка перехватывается:

p2.png

На этом форуме высказывается предположение, что это связано с ленивыми вычислениями. Но мы так и не смогли определить в каких ситуациях это работает, а в каких нет.

Вместо этого, можно обрабатывать конкретные ошибки HTTP, используя опцию ManualStatusHandling функции Web.Contents():

let  
   Source = Web.Contents(  
        "http://technitrain.com/blahblah",  
        [ManualStatusHandling={404}])  
in  
   Source  

Опция ManualStatusHandling принимает список кодов HTTP ошибок. Если запустить пример выше, то мы увидим, что запрос перестал генерировать ошибку.

Следующая проблема – как узнать сработал запрос или нет? Оказывается, определить это можно, просматривая метаданные, связанные с переменной Source. Вот пример как использовать функцию Value.Metadata() применительно к переменной Source:

let  
   Source = Web.Contents(  
       "http://technitrain.com/blahblah",  
       [ManualStatusHandling={404}]),  
   GetMetadata = Value.Metadata(Source)  
in  
   GetMetadata  

Запрос возвращает запись, которая среди прочего содержит HTTP код ответа:

p3.png

Подытожим, для перехвата ошибки 404 можно использовать такой шаблон:

let  
   Source = Web.Contents(  
       "http://technitrain.com/blahblah",  
       [ManualStatusHandling={404}]),  
   GetMetadata = Value.Metadata(Source),  
   GetResponseStatus = GetMetadata[Response.Status],  
   Output = if GetResponseStatus=404 then "Error!" else Source  
in  
   Output
Следующая статья
Предыдущая статья

Комментирование закрыто.

Идет набор на курс “Power BI для интернет-маркетинга”

Набор на новый поток курса по Power BI

Подпишитесь на нашу рассылку, чтобы не пропустить новые статьи!

Подписка на рассылку NeedForData

Бесплатная шпаргалка по визуализации
Плакат Как что визуализировать
Сертификаты студентов курсов NeedForData.ru

© 2018    NeedForData