bigquery url 解码

Posted

技术标签:

【中文标题】bigquery url 解码【英文标题】:bigquery url decode 【发布时间】:2012-12-12 01:32:31 【问题描述】:

是否有一种简单的方法可以在 BigQuery 查询语言中进行 URL 解码?我正在使用一个表,该表有一列包含某些值中的 URL 编码字符串。例如:

http://xyz.com/example.php?url=http%3A%2F%2Fwww.example.com%2Fhello%3Fv%3D12345&foo=bar&abc=xyz

我像这样提取“url”参数:

SELECT REGEXP_EXTRACT(column_name, "url=([^&]+)") as url 
from [mydataset.mytable]

这给了我:

http%3A%2F%2Fwww.example.com%2Fhello%3Fv%3D12345

我想做的是这样的:

SELECT URL_DECODE(REGEXP_EXTRACT(column_name, "url=([^&]+)")) as url 
from [mydataset.mytable]

从而返回:

http://www.example.com/hello?v=12345

如果可能,我想避免使用多个 REGEXP_REPLACE() 语句(替换 %20、%3A 等...)。

想法?

【问题讨论】:

【参考方案1】:

下面是在@sigpwned 答案之上构建的,但稍微重构并用 SQL UDF 包装(没有限制,JS UDF 使用起来如此安全)

#standardSQL
CREATE TEMP FUNCTION URLDECODE(url STRING) AS ((
  SELECT SAFE_CONVERT_BYTES_TO_STRING(
    ARRAY_TO_STRING(ARRAY_AGG(
        IF(STARTS_WITH(y, '%'), FROM_HEX(SUBSTR(y, 2)), CAST(y AS BYTES)) ORDER BY i
      ), b''))
  FROM UNNEST(REGEXP_EXTRACT_ALL(url, r"%[0-9a-fA-F]2|[^%]+")) AS y WITH OFFSET AS i 
));
SELECT 
  column_name, 
  URLDECODE(REGEXP_EXTRACT(column_name, "url=([^&]+)")) AS url
FROM `project.dataset.table`

可以通过以下问题的示例进行测试

#standardSQL
CREATE TEMP FUNCTION URLDECODE(url STRING) AS ((
  SELECT SAFE_CONVERT_BYTES_TO_STRING(
    ARRAY_TO_STRING(ARRAY_AGG(
        IF(STARTS_WITH(y, '%'), FROM_HEX(SUBSTR(y, 2)), CAST(y AS BYTES)) ORDER BY i
      ), b''))
  FROM UNNEST(REGEXP_EXTRACT_ALL(url, r"%[0-9a-fA-F]2|[^%]+")) AS y WITH OFFSET AS i 
));
WITH `project.dataset.table` AS (
  SELECT 'http://example.com/example.php?url=http%3A%2F%2Fwww.example.com%2Fhello%3Fv%3D12345&foo=bar&abc=xyz' column_name
)
SELECT 
  URLDECODE(REGEXP_EXTRACT(column_name, "url=([^&]+)")) AS url,
  column_name
FROM `project.dataset.table`    

结果

Row url                                     column_name  
1   http://www.example.com/hello?v=12345    http://example.com/example.php?url=http%3A%2F%2Fwww.example.com%2Fhello%3Fv%3D12345&foo=bar&abc=xyz   

使用更优化的 SQL UDF 更新

CREATE TEMP FUNCTION URLDECODE(url STRING) AS ((
  SELECT STRING_AGG(
    IF(REGEXP_CONTAINS(y, r'^%[0-9a-fA-F]2'), 
      SAFE_CONVERT_BYTES_TO_STRING(FROM_HEX(REPLACE(y, '%', ''))), y), '' 
    ORDER BY i
    )
  FROM UNNEST(REGEXP_EXTRACT_ALL(url, r"%[0-9a-fA-F]2(?:%[0-9a-fA-F]2)*|[^%]+")) y
  WITH OFFSET AS i 
));

【讨论】:

【参考方案2】:

这是一个很好的功能请求,但目前没有提供 URL 解码的内置 BigQuery 功能。

【讨论】:

是否有此功能请求的链接?【参考方案3】:

另一种解决方法是使用用户定义的函数。

#standardSQL
CREATE TEMPORARY FUNCTION URL_DECODE(enc STRING)
RETURNS STRING
LANGUAGE js AS """
  try  
    return decodeURI(enc);;
   catch (e)  return null 
  return null;
""";

SELECT ven_session, 
  URL_DECODE(REGEXP_EXTRACT(para,r'&kw=(\w|[^&]*)')) AS q
FROM raas_system.weblog_20170327 
WHERE para like '%&kw=%'
LIMIT 10

【讨论】:

当您想将查询存储为视图时会出现问题【参考方案4】:

我同意这里的每个人的观点,URLDECODE 应该是一个原生函数。但是,在此之前,可以编写一个“原生”URLDECODE

SELECT id, SAFE_CONVERT_BYTES_TO_STRING(ARRAY_TO_STRING(ps, b'')) FROM (SELECT
  id,
  ARRAY_AGG(CASE
    WHEN REGEXP_CONTAINS(y, r"^%") THEN FROM_HEX(SUBSTR(y, 2))
    ELSE CAST(y AS bytes)
  END ORDER BY i) AS ps
  FROM (SELECT x AS id, REGEXP_EXTRACT_ALL(x, r"%[0-9a-fA-F]2|[^%]+") AS element FROM UNNEST(ARRAY['domodossola%e2%80%93locarno railway', 'gabu%c5%82t%c3%b3w']) AS x) AS x
  CROSS JOIN UNNEST(x.element) AS y WITH OFFSET AS i GROUP BY id);

在此示例中,我尝试并测试了使用来自 Wikipedia 的几个百分比编码的页面名称作为输入的实现。它也应该适用于您的输入。

显然,这非常笨拙!出于这个原因,我建议构建一个物化连接表,或者将它包装在一个视图中,而不是在查询中使用这个表达式“naked”。但是,它似乎确实完成了工作,并且没有达到 UDF 限制。

编辑:@MikhailBerylyant's post below 将这个繁琐的实现包装成一个漂亮、整洁的小型 SQL UDF。这是处理这个问题的更好方法!

【讨论】:

谢谢!作为 SQL UDF 的精美包装!已编辑。

以上是关于bigquery url 解码的主要内容,如果未能解决你的问题,请参考以下文章

数据流模板“Pub/Sub Avro to Bigquery”无法解码

用于读取 JSON 格式数据的 BigQuery 表 URL

从 Bigquery 中的 URL 中提取字符串

在 BigQuery 中更新结构

BigQuery REGEXP_EXTRACT from URL - 提取参数值

适用于 excel 的 BigQuery 连接器 - 请求失败:错误。无法执行查询。获取 URL 时超时