【问题标题】:Extract domain from url using PostgreSQL使用 PostgreSQL 从 url 中提取域
【发布时间】:2019-09-24 22:45:02
【问题描述】:

我需要使用 PostgreSQL 提取 url 列表的域名。在第一个版本中,我尝试使用 REGEXP_REPLACE 替换不需要的字符,如 www.、biz.、sports. 等,以获取域名。

 SELECT REGEXP_REPLACE(url, ^((www|www2|www3|static1|biz|health|travel|property|edu|world|newmedia|digital|ent|staging|cpelection|dev|m-staging|m|maa|cdnnews|testing|cdnpuc|shipping|sports|life|static01|cdn|dev1|ad|backends|avm|displayvideo|tand|static03|subscriptionv3|mdev|beta)\.)?', '') AS "Domain", 
 COUNT(DISTINCT(user)) AS "Unique Users"
 FROM db
 GROUP BY 1
 ORDER BY 2 DESC;

这似乎不利,因为查询需要不断更新以获取不需要的单词列表。

我确实尝试https://stackoverflow.com/a/21174423/10174021 使用 PostgreSQL REGEXP_SUBSTR 从行尾提取,但是,我得到了空白行作为回报。有没有更好的方法来做到这一点?

尝试使用的数据集示例:

 CREATE TABLE sample (
 url VARCHAR(100) NOT NULL);

 INSERT INTO sample url) 
 VALUES 
 ("sample.co.uk"),
 ("www.sample.co.uk"),
 ("www3.sample.co.uk"),
 ("biz.sample.co.uk"),
 ("digital.testing.sam.co"),
 ("sam.co"),
 ("m.sam.co");

期望的输出

+------------------------+--------------+
|    url                 |  domain      |
+------------------------+--------------+
| sample.co.uk           | sample.co.uk |
| www.sample.co.uk       | sample.co.uk |
| www3.sample.co.uk      | sample.co.uk |
| biz.sample.co.uk       | sample.co.uk |
| digital.testing.sam.co | sam.co       |
| sam.co                 | sam.co       |
| m.sam.co               | sam.co       |
+------------------------+--------------+

【问题讨论】:

  • 你能列出像 co.uk 这样的“双倍顶级域名”吗?
  • 意义?您希望我在示例数据中创建更多的双 TLD 变体吗?
  • 不,不在样本数据中,就我而言,没关系。但我可以想象的一个可能的解决方案是匹配 DNS 名称的结尾。但这可能只给你 co.uk 而不是 sample.co.uk。因此,这些“双 TLD”需要特殊处理。这就是为什么我好像你可以列出他们。毕竟计算机无法“知道” co.uk 实际上被视为一个 TLD。
  • 这正是我卡住的地方。 TLD 可以是 .co.uk、.co 或 .uk。
  • 这比乍看起来要复杂得多(我过去曾尝试过这样做)。查看一些执行此操作的 python 库(tld 或 tldextract)。它们通常从此处提供的完整 tld 列表开始:publicsuffix.org/list。好长啊……

标签: regex postgresql url


【解决方案1】:

所以,我使用 Jeremy 和 Rémy Baron 的回答找到了解决方案。

  1. public suffix中提取所有公共后缀并存储到 我标记为 tlds 的表。

  2. 获取数据集中的唯一网址并匹配其 TLD。

  3. 使用 regexp_replace(在此查询中使用)或替代 regexp_substr(t1.url, '([a-z]+)(.)'||t1."tld") 提取域名。最终输出:

SQL查询如下:

WITH stored_tld AS(
SELECT 
DISTINCT(s.url),
FIRST_VALUE(t.domain) over (PARTITION BY s.url ORDER BY length(t.domain) DESC
                            rows between unbounded preceding and unbounded following) AS "tld" 
FROM sample s 
JOIN tlds t 
ON (s.url like '%%'||domain))

SELECT 
t1.url,
CASE WHEN t1."tld" IS NULL THEN t1.url ELSE regexp_replace(t1.url,'(.*\.)((.[a-z]*).*'||replace(t1."tld",'.','\.')||')','\2') 
END AS "extracted_domain" 
FROM(
    SELECT a.url,st."tld"
    FROM sample a
    LEFT JOIN stored_tld st
    ON a.url = st.url
    )t1

尝试链接:SQL Tester

【讨论】:

    【解决方案2】:

    你可以试试这个:

    with tlds as (
         select * from (values('.co.uk'),('.co'),('.uk')) a(tld)
    ) ,
    sample as (
        select * from (values ('sample.co.uk'),
                              ('www.sample.co.uk'),
                              ('www3.sample.co.uk'),
                              ('biz.sample.co.uk'),
                              ('digital.testing.sam.co'),
                              ('sam.co'),
                              ('m.sam.co')
                       ) a(url)
         ) 
      select url,regexp_replace(url,'(.*\.)(.*'||replace(tld,'.','\.')||')','\2') "domain" from (
                select distinct url,first_value(tld) over (PARTITION BY url order by length(tld) DESC) tld 
                   from sample join tlds on (url like '%'||tld) 
             ) a
    

    【讨论】:

      【解决方案3】:

      我为此使用 split_part(url,'/',3)

      select split_part('https://stackoverflow.com/questions/56019744', '/', 3) ;
      

      输出

      stackoverflow.com
      

      【讨论】:

        猜你喜欢
        • 2022-01-16
        • 1970-01-01
        • 2018-09-08
        • 2015-03-08
        • 2021-04-12
        • 2010-10-24
        • 2013-09-17
        • 2015-11-14
        • 1970-01-01
        相关资源
        最近更新 更多