Ich möchte einen URL-Shortener-Service erstellen, bei dem Sie eine lange URL in ein Eingabefeld schreiben können und der Service die URL auf " http://www.example.org/abcdef
" verkürzt .
Anstelle von " abcdef
" kann es auch eine andere Zeichenfolge mit sechs Zeichen geben a-z, A-Z and 0-9
. Das macht 56 bis 57 Milliarden mögliche Saiten möglich.
Mein Ansatz:
Ich habe eine Datenbanktabelle mit drei Spalten:
- ID, Ganzzahl, automatische Inkrementierung
- long, string, die lange URL, die der Benutzer eingegeben hat
- kurz, Zeichenfolge, die verkürzte URL (oder nur die sechs Zeichen)
Ich würde dann die lange URL in die Tabelle einfügen. Dann würde ich den Auto-Inkrement-Wert für " id
" auswählen und einen Hash davon erstellen. Dieser Hash sollte dann als " short
" eingefügt werden . Aber welche Art von Hash soll ich bauen? Hash-Algorithmen wie MD5 erzeugen zu lange Zeichenfolgen. Ich denke, ich benutze diese Algorithmen nicht. Ein selbst erstellter Algorithmus funktioniert ebenfalls.
Meine Idee:
Für " http://www.google.de/
" erhalte ich die Auto-Inkrement-ID 239472
. Dann mache ich folgende Schritte:
short = '';
if divisible by 2, add "a"+the result to short
if divisible by 3, add "b"+the result to short
... until I have divisors for a-z and A-Z.
Das könnte wiederholt werden, bis die Zahl nicht mehr teilbar ist. Halten Sie dies für einen guten Ansatz? Hast du eine bessere Idee?
Aufgrund des anhaltenden Interesses an diesem Thema habe ich eine effiziente Lösung für GitHub mit Implementierungen für JavaScript , PHP , Python und Java veröffentlicht . Fügen Sie Ihre Lösungen hinzu, wenn Sie möchten :)
encode()
unddecode()
Funktionen haben können. Die Schritte sind daher: (1) Speichern der URL in der Datenbank (2) Abrufen der eindeutigen Zeilen-ID für diese URL aus der Datenbank (3) Konvertieren der Ganzzahl-ID in eine kurze Zeichenfolge mitencode()
z. B.273984
inf5a4
(4) Verwenden Sie die kurze Zeichenfolge (z. B.f4a4
) in Ihrer gemeinsam nutzbare URLs (5) Wenn Sie eine Anforderung für eine kurze Zeichenfolge (z. B.20a8
) erhalten, dekodieren Sie die Zeichenfolge in eine ganzzahlige ID mitdecode()
(6) Suchen Sie die URL in der Datenbank nach der angegebenen ID. Verwenden Sie für die Konvertierung: github.com/delight-im/ShortURLAntworten:
Ich würde Ihren Ansatz "Nummer in Zeichenfolge konvertieren" fortsetzen. Sie werden jedoch feststellen, dass Ihr vorgeschlagener Algorithmus fehlschlägt, wenn Ihre ID eine Primzahl ist und größer als 52 ist .
Theoretischer Hintergrund
Sie benötigen eine bijektive Funktion f . Dies ist notwendig, damit Sie eine Umkehrfunktion g ('abc') = 123 für Ihre Funktion f (123) = 'abc' finden können. Das heisst:
So konvertieren Sie die ID in eine verkürzte URL
[a-zA-Z0-9]
. Es enthält 62 Buchstaben .Nehmen Sie einen automatisch generierten, eindeutigen numerischen Schlüssel (
id
z. B. den automatisch inkrementierten einer MySQL-Tabelle).In diesem Beispiel verwende ich 125 10 (125 mit einer Basis von 10).
Jetzt müssen Sie 125 10 in X 62 (Basis 62) konvertieren .
125 10 = 2 × 62 1 + 1 × 62 0 =
[2,1]
Dies erfordert die Verwendung von Integer Division und Modulo. Ein Pseudocode-Beispiel:
Ordnen Sie nun die Indizes 2 und 1 Ihrem Alphabet zu. So könnte Ihre Zuordnung (zum Beispiel mit einem Array) aussehen:
Mit 2 → c und 1 → b erhalten Sie cb 62 als verkürzte URL.
So lösen Sie eine verkürzte URL in die ursprüngliche ID auf
Das Gegenteil ist noch einfacher. Sie machen einfach eine umgekehrte Suche in Ihrem Alphabet.
e9a 62 wird in "4., 61. und 0. Buchstabe im Alphabet" aufgelöst.
e9a 62 =
[4,61,0]
= 4 × 62 2 + 61 × 62 1 + 0 × 62 0 = 19158 10Suchen Sie nun Ihren Datenbankeintrag mit
WHERE id = 19158
und führen Sie die Umleitung durch.Beispielimplementierungen (von Kommentatoren bereitgestellt)
quelle
3792586=='F_ck'
mit u anstelle von _). Ich würde einige Zeichen wie u / U ausschließen, um dies zu minimieren.Warum sollten Sie einen Hash verwenden wollen?
Sie können einfach eine einfache Übersetzung Ihres Auto-Inkrement-Werts in einen alphanumerischen Wert verwenden. Sie können dies einfach tun, indem Sie eine Basiskonvertierung verwenden. Angenommen, Ihr Zeichenraum (AZ, az, 0-9 usw.) besteht aus 40 Zeichen, konvertieren Sie die ID in eine Basis-40-Zahl und verwenden Sie die Zeichen als Ziffern.
quelle
quelle
Keine Antwort auf Ihre Frage, aber ich würde keine verkürzten URLs verwenden, bei denen zwischen Groß- und Kleinschreibung unterschieden wird. Sie sind schwer zu merken, normalerweise unlesbar (viele Schriftarten machen 1 und 1, 0 und O und andere Zeichen sehr ähnlich, so dass es nahezu unmöglich ist, den Unterschied zu erkennen) und geradezu fehleranfällig. Versuchen Sie, nur Klein- oder Großbuchstaben zu verwenden.
Versuchen Sie auch, ein Format zu haben, in dem Sie die Zahlen und Zeichen in einer vordefinierten Form mischen. Es gibt Studien, die zeigen, dass Menschen sich eine Form besser merken als andere (denken Sie an Telefonnummern, bei denen die Nummern in einer bestimmten Form gruppiert sind). Versuchen Sie etwas wie num-char-char-num-char-char. Ich weiß, dass dies die Kombinationen verringert, insbesondere wenn Sie keine Groß- und Kleinschreibung haben, aber es wäre benutzerfreundlicher und daher nützlich.
quelle
Mein Ansatz: Nehmen Sie die Datenbank-ID und codieren Sie sie dann von Base36 . Ich würde NICHT sowohl Groß- als auch Kleinbuchstaben verwenden, da dies das Übertragen dieser URLs über das Telefon zu einem Albtraum macht, aber Sie könnten die Funktion natürlich leicht zu einem Basis-62-En / Decoder erweitern.
quelle
Hier ist meine PHP 5 Klasse.
quelle
Eine Node.js- und MongoDB-Lösung
Bearbeiten: Es ist besser, eine relationale Datenbank zum Speichern solcher Daten (short_url und true url) zu verwenden und nicht MongoDB.
Da wir das Format kennen, mit dem MongoDB eine neue ObjectId mit 12 Bytes erstellt.
Beispiel (ich wähle eine zufällige Sequenz) a1b2c3d4e5f6g7h8i9j1k2l3
Da der Zähler eindeutig ist, wenn wir die Daten auf demselben Computer speichern, können wir sie ohne Zweifel abrufen, dass sie doppelt vorhanden sind.
Die kurze URL ist also der Zähler. Hier ist ein Codeausschnitt, der davon ausgeht, dass Ihr Server ordnungsgemäß ausgeführt wird.
quelle
C # -Version:
quelle
Sie könnten die gesamte URL hashen, aber wenn Sie nur die ID kürzen möchten, tun Sie, was marcel vorgeschlagen hat. Ich habe diese Python-Implementierung geschrieben:
https://gist.github.com/778542
quelle
Ich erhöhe ständig eine Ganzzahlsequenz pro Domäne in der Datenbank und verwende Hashids , um die Ganzzahl in einen URL-Pfad zu codieren.
Ich habe ein Skript ausgeführt, um zu sehen, wie lange es dauert, bis die Zeichenlänge erschöpft ist. Für sechs Zeichen kann es
164,916,224
Links erstellen und dann bis zu sieben Zeichen. Bitly verwendet sieben Zeichen. Unter fünf Zeichen sieht für mich komisch aus.Hashids können den URL-Pfad zurück in eine Ganzzahl dekodieren. Eine einfachere Lösung besteht jedoch darin, den gesamten Kurzlink
sho.rt/ka8ds3
als Primärschlüssel zu verwenden.Hier ist das vollständige Konzept:
quelle
Wenn Sie das Rad nicht neu erfinden möchten ... http://lilurl.sourceforge.net/
quelle
quelle
Hier ist meine Version für jeden, der sie braucht.
quelle
Warum übersetzen Sie Ihre ID nicht einfach in eine Zeichenfolge? Sie benötigen lediglich eine Funktion, die eine Ziffer zwischen beispielsweise 0 und 61 einem einzelnen Buchstaben (Groß- / Kleinbuchstaben) oder einer Ziffer zuordnet. Wenden Sie dies dann an, um beispielsweise 4-Buchstaben-Codes zu erstellen, und Sie haben 14,7 Millionen URLs abgedeckt.
quelle
Hier ist eine anständige URL-Codierungsfunktion für PHP ...
quelle
Ich weiß nicht, ob jemand dies nützlich finden wird - es ist eher eine "Hack n Slash" -Methode, aber einfach und funktioniert gut, wenn Sie nur bestimmte Zeichen möchten.
quelle
Haben Sie absichtlich O, 0 und i weggelassen?
Ich habe gerade eine PHP-Klasse basierend auf Ryans Lösung erstellt.
quelle
Schauen Sie sich https://hashids.org/ an, es ist Open Source und in vielen Sprachen.
Ihre Seite beschreibt einige der Fallstricke anderer Ansätze.
quelle
Das benutze ich:
Es ist sehr schnell und kann lange ganze Zahlen dauern.
quelle
Um für ein ähnliches Projekt einen neuen Schlüssel zu erhalten, erstelle ich eine Wrapper-Funktion um einen Zufallszeichenfolgengenerator , der den Generator aufruft, bis ich eine Zeichenfolge erhalte, die noch nicht in meiner Hashtabelle verwendet wurde. Diese Methode wird langsamer, sobald Ihr Namensraum voll wird, aber wie Sie bereits gesagt haben, haben Sie selbst mit nur 6 Zeichen genügend Namespace, mit dem Sie arbeiten können.
quelle
Ich habe eine Variante des Problems, indem ich Webseiten von vielen verschiedenen Autoren speichere und verhindern muss, dass Seiten durch Vermutungen entdeckt werden. Meine kurzen URLs fügen der Base-62-Zeichenfolge für die Seitenzahl ein paar zusätzliche Ziffern hinzu. Diese zusätzlichen Ziffern werden aus Informationen im Seitendatensatz selbst generiert und stellen sicher, dass nur 1 von 3844 URLs gültig sind (unter der Annahme einer zweistelligen Basis-62). Eine Gliederungsbeschreibung finden Sie unter http://mgscan.com/MBWL .
quelle
Sehr gute Antwort, ich habe eine Golang-Implementierung des bjf erstellt:
Gehostet bei github: https://github.com/xor-gate/go-bjf
quelle
quelle
Implementierung in Scala:
Testbeispiel mit Scala-Test:
quelle
Funktion basierend auf der Xeoncross-Klasse
quelle
Hier ist eine Node.js-Implementierung, die wahrscheinlich bit.ly ist. Generieren Sie eine sehr zufällige Zeichenfolge mit sieben Zeichen.
Es verwendet Node.js Krypto, um einen sehr zufälligen Zeichensatz von 25 zu generieren, anstatt zufällig sieben Zeichen auszuwählen.
quelle
Meine Python 3-Version
quelle
Eine hochwertige Node.js / JavaScript-Lösung finden Sie im ID-Shortener Modul, das gründlich getestet wurde und seit Monaten in der Produktion verwendet wird.
Es bietet einen effizienten ID / URL-Shortener, der durch einen steckbaren Speicher unterstützt wird, der standardmäßig auf Redis eingestellt ist , und Sie können sogar Ihren kurzen ID-Zeichensatz anpassen und festlegen, ob die Kürzung idempotent ist oder nicht . Dies ist eine wichtige Unterscheidung, die nicht alle URL-Shortender berücksichtigen.
In Bezug auf andere Antworten hier implementiert dieses Modul die oben akzeptierte ausgezeichnete Antwort von Marcel Jackwerth.
Den Kern der Lösung bildet das folgende Redis Lua- Snippet :
quelle
Warum nicht einfach eine zufällige Zeichenfolge generieren und an die Basis-URL anhängen? Dies ist eine sehr vereinfachte Version von C # .
Fügen Sie dann einfach die zufällige Zeichenfolge an die baseURL an:
Denken Sie daran, dass dies eine sehr vereinfachte Version ist und dass die RandomString-Methode möglicherweise doppelte Zeichenfolgen erstellt. In der Produktion sollten Sie doppelte Zeichenfolgen berücksichtigen, um sicherzustellen, dass Sie immer eine eindeutige URL haben. Ich habe einen Code, der doppelte Zeichenfolgen berücksichtigt, indem er eine Datenbanktabelle abfragt, die ich bei Interesse freigeben kann.
quelle
Dies sind meine ersten Gedanken, und es kann mehr nachgedacht werden, oder es kann eine Simulation durchgeführt werden, um festzustellen, ob es gut funktioniert oder Verbesserungen erforderlich sind:
Meine Antwort ist, sich die lange URL in der Datenbank zu merken und die ID
0
zu verwenden9999999999999999
(oder wie groß die Anzahl auch sein mag).Aber die ID 0 bis
9999999999999999
kann ein Problem sein, weilA
-Z
a
-z
0
-9
_
und-
)0
zu9999999999999999
gleichmäßig, dann kann Hacker sie in dieser Reihenfolge besucht und weiß , was URLs Menschen sich senden, so dass es ein Datenschutzproblem sein kannWir können das schaffen:
0
um999
auf einen Server, Server A, so dass nun Server Ein 1000 solchen IDs aufweist. Wenn also 20 oder 200 Server ständig neue IDs wünschen, muss sie nicht ständig nach jeder neuen ID fragen, sondern einmal nach 1000 IDs000...00000001
wird10000...000
, so dass bei der Konvertierung in base64 die IDs jedes Mal ungleichmäßig erhöht werden.0xD5AA96...2373
(wie ein geheimer Schlüssel) und einige Bits werden umgedreht. (Immer wenn der geheime Schlüssel das 1-Bit aktiviert hat, wird das Bit der ID umgedreht). Dadurch werden die IDs noch schwieriger zu erraten und erscheinen zufälligerNach diesem Schema können der einzelne Server, der die IDs zuweist, die IDs bilden, ebenso wie die 20 oder 200 Server, die die Zuweisung von IDs anfordern. Der zuweisende Server muss eine Sperre / ein Semaphor verwenden, um zu verhindern, dass zwei anfordernde Server denselben Stapel erhalten (oder wenn er jeweils eine Verbindung akzeptiert, ist das Problem bereits gelöst). Wir möchten also nicht, dass die Warteschlange zu lang ist, um auf eine Zuordnung zu warten. Deshalb kann das Problem durch Zuweisen von 1000 oder 10000 gleichzeitig behoben werden.
quelle