Как извлечь доменное имя с помощью динамического регулярного выражения в Redshift? - PullRequest
0 голосов
/ 13 мая 2019

Мне нужно извлечь доменное имя из URL, используя Redshift PostgreSQL.Пример: извлеките «google.com» из «www.google.com».Каждый URL в моем наборе данных имеет свой домен верхнего уровня (TLD).Мой подход состоял в том, чтобы сначала присоединить соответствующий TLD к набору данных и использовать регулярное выражение для извлечения first_string.TLD.В Redshift я получаю сообщение об ошибке «Шаблон должен быть действительным литеральным выражением UTF-8».Есть ли способ обойти это?

Образец моего набора данных:

 +---+------------------------+--------------+
 | id|    trimmed_domain      |  tld         |
 +---+------------------------+--------------+
 | 1 | sample.co.uk           | co.uk        |
 | 2 | www.sample.co.uk       | co.uk        |
 | 3 | www3.sample.co.uk      | co.uk        |
 | 4 | biz.sample.co.uk       | co.uk        |
 | 5 | digital.testing.sam.co | co           |
 | 6 | sam.co                 | co           |
 | 7 | www.google.com         | com          |
 | 8 | 1.11.220               |              |
 +---+------------------------+--------------+ 

Мой код:

 SELECT t1.extracted_domain, COUNT(DISTINCT(t1.id))
 FROM(
     SELECT 
     d.id,
     d.trimmed_domain,
     CASE 
     WHEN d.tld IS null THEN d.trimmed_domain ELSE 
      regexp_replace(d.trimmed_domain,'(.*\.)((.[a-z]*).*'||replace(tld,'.','\.')||')','\2') 
     END AS "extracted_domain" 
     FROM dataset d
     )t1
  GROUP BY 1
  ORDER BY 2;

Ожидаемый результат:

 +------------------------+--------------+
 |    extracted_domain    |  count       |
 +------------------------+--------------+
 | sample.co.uk           | 4            |
 | sam.co                 | 2            |
 | google.com             | 1            |
 | 1.11.220               | 1            |
 +------------------------+--------------+

Ответы [ 3 ]

0 голосов
/ 14 мая 2019

Итак, я нашел решение.Redshift не поддерживает регулярные выражения на основе столбцов, поэтому альтернативой является использование Python UDF.

  1. Измените столбец tld на регулярное выражение. part1

  2. Идите строка за строкой и извлекайте имя доменаиспользуя столбец шаблона регулярного выражения.part2

  3. Группировка по извлеченному домену и подсчет пользователей.

SQL-запрос выглядит следующим образом:

CREATE OR REPLACE function extractor(col_domain varchar)
RETURNS varchar
IMMUTABLE AS $$
    import re
    _regex = ''
    for domain in col_domain:
        if domain is None:
           continue
        else:
           _regex += r'{}'.format(domain)
    domain_regex = r'([^/.]+\.({}))'.format(_regex)
    return domain_regex
$$ LANGUAGE plpythonu;

CREATE OR REPLACE FUNCTION regex_match(in_pattern varchar, input_str varchar)
RETURNS varchar
IMMUTABLE AS $$
    import re
    if in_pattern == '':
        a = str(input_str)
    else: 
        a= str(re.search(in_pattern, input_str).group())
    return a
$$ LANGUAGE plpythonu;

SELECT 
t2.extracted_domain,
COUNT(DISTINCT(t2.id)) AS "Unique Users"
FROM(
    SELECT 
    t1.id,
    t1.trimmed_domain,
    regex_match(t1.regex_pattern, t1.trimmed_domain) AS "extracted_domain"
    FROM(
        SELECT 
        id,
        trimmed_domain,
        CASE WHEN tld is null THEN '' ELSE extractor(tld) END AS "regex_pattern"
        FROM dataset
        )t1
    )t2
GROUP BY 1
ORDER BY 2 DESC
LIMIT 10;  

Кажется, что Python UDF работает медленно на большом наборе данных.Итак, я открыт для предложений по улучшению запроса.

0 голосов
/ 14 мая 2019

Если вам известны префиксы, которые вы хотите удалить из доменов, то почему бы просто не исключить их? Следующий запрос просто удаляет известные префиксы www / http / etc из доменных имен и считает нормализованные доменные имена.

SELECT COUNT(*) from 
  (select REGEXP_REPLACE(domain, '^(https|http|www|biz)') FROM domains) 
GROUP BY regexp_replace;
0 голосов
/ 13 мая 2019

Я так уверен насчет запроса.Однако вы можете использовать этот инструмент и создать любое выражение, которое вы хотите изменить в своем запросе.

Я предполагаю, что, возможно, это поможет:

^(?!d|b|www3).*

Вы можете перечислить любой домен, который вы хотите исключить из списка, используя ИЛИ (?!d|b|www3).

enter image description here

RegEx Circuit

Вы можете визуализировать свои выражения в этой ссылке :

enter image description here


Возможно, вы захотите добавить нужные URL-адреса к выражению, аналогичному :

^(sam|www.google|1.11|www.sample|www3.sample).*

enter image description here

...