2012-12-05 4 views
5

Ho trovato questa risposta, ma volevo espandere la domanda e non ho trovato nessuna soluzione qui in pila o tramite la ricerca su google.Parse Domain da un determinato URL in T-SQL

Substring domainname from URL SQL

Fondamentalmente il link qui sopra risolve il mio problema con un semplice URL parsing come "www.google.com", con il risultato di google.

Quello che sto cercando di espandere su questa è la soluzione dal link sopra non aiuta con url come 'www.maps.google.com' che restituisce solo mappe.

Quello che vorrei è restituirlo "google" dall'URL "www.maps.google.com" o restituire "esempio" da "www.test.example.com".

Se qualcuno ha una soluzione a questo, lo apprezzerei molto.

Update: Per essere più precisi mi avrà bisogno anche analisi su domini di secondo livello, ecc 'www.maps.google.com.au' tornare 'google'

Ecco la mia funzione SQL.

CREATE FUNCTION [dbo].[parseURL] (@strURL varchar(1000)) 
RETURNS varchar(1000) 
AS 
BEGIN 

IF CHARINDEX('.', REPLACE(@strURL, 'www.','')) > 0 
SELECT @strURL = LEFT(REPLACE(@strURL, 'www.',''), CHARINDEX('.',REPLACE(@strURL,    'www.',''))-1) 
Else 
SELECT @strURL = REPLACE(@strURL, 'www.','') 

RETURN @strURL 
END 
+1

Come ti vogliono trattare con [domini di secondo livello] (http://en.wikipedia.org/wiki/Second-level_domain), ad esempio, 'www.google.com.sg' o' bbc.co.uk'? – ig0774

+0

Sì, ho appena aggiornato la mia domanda per includere domini di secondo livello. Vorrei anche restituire "google" da "www.google.com.sg" –

risposta

6

Io suggerirei questo

DECLARE @URL nvarchar(max) = 'www.maps.google.com' 

DECLARE @X xml = CONVERT(xml,'<root><part>' + REPLACE(@URL, '.','</part><part>') + '</part></root>') 

SELECT [Domain] = T.c.value('.','varchar(20)') 
FROM @X.nodes('/root/part[position() = last() - 1]') T(c) 

L'approccio è quello di convertire l'URL per XML e quindi utilizzare XPath per trovare il dominio.

UPDATE

Per quanto riguarda domini di secondo livello, credo che l'unico modo affidabile per avere tutti in una tabella (domini di primo livello dovrebbero probabilmente essere in una tabella di troppo) e quindi si potrebbe utilizzare questo query:

DECLARE @URL nvarchar(max) = 'www.maps.google.com' 

DECLARE @X xml = CONVERT(xml,'<root><part>' + REPLACE(REVERSE(@URL), '.','</part><part>') + '</part></root>') 

;WITH SplitCTE AS 
(
    SELECT 
     (SELECT REVERSE(T.c.value('.', 'nvarchar(256)')) FROM @X.nodes('/root/part[. = ../part[position() = 1]]') T(c)) AS TLD, 
     (SELECT REVERSE(T.c.value('.', 'nvarchar(256)')) FROM @X.nodes('/root/part[. = ../part[position() = 2]]') T(c)) AS D2, 
     (SELECT REVERSE(T.c.value('.', 'nvarchar(256)')) FROM @X.nodes('/root/part[. = ../part[position() = 3]]') T(c)) AS D3 
) 
SELECT 
    CASE 
     WHEN SLD.Domain IS NULL THEN S.D2 ELSE S.D3 
    END AS Domain 
FROM 
    SplitCTE AS S 
    LEFT JOIN TLD ON TLD.Domain = S.TLD 
    LEFT JOIN SLD ON SLD.Domain = S.D2 

Il TLD/tavoli SLD che ho usato per questo esempio sono al di sotto. L'elenco completo dei domini è in questo wiki. Fai attenzione a usare NVARCHAR poiché alcuni sono localizzati.

+0

Questo è quello che dovevo fare. Ho ottenuto tutti i TLD in una tabella, poi ho compilato un elenco di domini di secondo livello e l'ho inserito in una tabella e ho usato la tua query sopra. Dolore alla ricerca di un elenco di domini di secondo livello. Grazie per la tua risposta e aiuto su questo. –

3

Qualcuno probabilmente ha una soluzione migliore, ma qui è quello che ho ottenuto:

LEFT(RIGHT(@strURL, CHARINDEX('.', REVERSE(@strURL)) + CHARINDEX('.', SUBSTRING(REVERSE(@strURL), CHARINDEX('.', REVERSE(@strURL)) + 1, LEN(@strURL))) - 1), CHARINDEX('.', SUBSTRING(REVERSE(@strURL), CHARINDEX('.', REVERSE(@strURL)) + 1, LEN(@strURL))) - 1) 

io non sono il migliore a manipolazione delle stringhe, quindi sono sicuro che è possibile abbreviare il mio davvero lunga fila di codice. Fondamentalmente, userei la funzione REVERSE per ottenere l'ultimo periodo e poi andare da lì. Il mio codice inserisce i caratteri tra la penultima e la penultima.

Tenere presente che l'utilizzo di un sito Web come www.test.co.uk non funzionerà con la mia soluzione. Proporrei che fosse solo un punto di partenza, e dovresti codificare per i valori anomali.

+0

che funzioni perfettamente per qualcosa che ha una sola estensione. Che cosa se e dovrei essere stato più specifico nella mia domanda, quindi di 'l'URL è' www.maps.google.com.au '. La tua risposta restituisce "com". Oltre a questo, questa risposta ha funzionato benissimo e ti ringrazio per la tua risposta. –

+0

Hai assolutamente ragione. Il problema che avrai sono tutti i possibili valori anomali. Vorrei raccomandare qualcosa di simile a ciò che Serge suggerisce, e mettere i valori anomali in una tabella a cui fare riferimento. Noi come esseri umani possiamo facilmente identificare i dati di cui hai bisogno, ma sfortunatamente un computer non può. Dipende davvero da quanto preciso è necessario essere. Inoltre, per quanto riguarda la scalabilità, suggerirei nuovamente di provare a capire cosa sta facendo Serge nel suo post. Il mio metodo è veloce e sporco, ma se hai bisogno di aggiungere più logica probabilmente non è la strada migliore. – Neil

2

PARSENAME dividerà fino a quattro elementi separati da "." marchio. Parsename conta dalla destra. Se object_name per analizzare ha più di quattro parti, NULL verrà riorganizzato.

select PARSENAME (REPLACE('www.maps.google.com.au', 'www.','') , 3) 
select PARSENAME (REPLACE('www.maps.google.com', 'www.','') , 2) 
+0

questo funziona in alcuni casi ma non al livello di cui ho bisogno, grazie per la risposta però –

4

La questione TLD può realmente rallentare il codice e aggiungere un requisito di manutenzione, così ho deciso di includere sottodomini.Ecco cosa uso:

ALTER FUNCTION dbo.spExtractDomainFromURL (@strURL NVARCHAR(1000)) 
RETURNS NVARCHAR(100) 
AS 
BEGIN 
    --Strip Protocol 
    SELECT @strURL = SUBSTRING(@strURL, CHARINDEX('://', @strURL) + 3, 999) 

    -- Strip www subdomain 
    IF LEFT(@strURL, 4) = 'www.' 
     SELECT @strURL = SUBSTRING(@strURL, 5, 999) 

    -- Strip Path 
    IF CHARINDEX('/', @strURL) > 0 
     SELECT @strURL = LEFT(@strURL, CHARINDEX('/', @strURL) - 1) 

    RETURN @strURL 
END 
2

Quello che ho fatto qui è la sottostringa dell'URL dopo il protocollo ': //'.

Poi prendo quella stringa e sottostringa tutto il testo fino alla prima barra.

Puoi farlo anche in una riga, se ne hai bisogno per una query, o usarlo come una funzione scalare come vorrei.

Inoltre, sarebbe una buona idea aggiungere un codice per verificare null o solo stringhe errate in generale. Se vuoi mantenerlo come una singola riga di codice, prova a utilizzare le funzioni ISNULL e NULLIF.

DECLARE @urlSansProtocol VARCHAR(MAX) 
SET @urlSansProtocol = Substring(@url, CharIndex('://', @url)+3 ,LEN(@url)) 
RETURN Substring(@urlSansProtocol, 0 ,CharIndex('/', @urlSansProtocol)) 
+2

Si dovrebbe aggiungere qualche spiegazione. –