Je veux créer un service de raccourcissement d'URL où vous pouvez écrire une longue URL dans un champ de saisie et le service raccourcit l'URL en " http://www.example.org/abcdef
".
Au lieu de " abcdef
", il peut y avoir toute autre chaîne contenant six caractères a-z, A-Z and 0-9
. Cela fait 56 ~ 57 milliards de chaînes possibles.
Mon approche:
J'ai une table de base de données avec trois colonnes:
- id, entier, incrémentation automatique
- long, string, l'URL longue saisie par l'utilisateur
- court, chaîne, l'URL raccourcie (ou seulement les six caractères)
Je voudrais ensuite insérer l'URL longue dans le tableau. Ensuite, je sélectionnerais la valeur d'incrémentation automatique pour " id
" et j'en créerais un hachage. Ce hachage doit ensuite être inséré en tant que " short
". Mais quelle sorte de hachage dois-je créer? Les algorithmes de hachage comme MD5 créent des chaînes trop longues. Je n'utilise pas ces algorithmes, je pense. Un algorithme auto-construit fonctionnera également.
Mon idée:
Pour " http://www.google.de/
", j'obtiens l'ID d'incrémentation automatique 239472
. Ensuite, je fais les étapes suivantes:
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.
Cela pourrait être répété jusqu'à ce que le nombre ne soit plus divisible. Pensez-vous que c'est une bonne approche? As-tu une meilleure idée?
En raison de l'intérêt continu pour ce sujet, j'ai publié une solution efficace pour GitHub , avec des implémentations pour JavaScript , PHP , Python et Java . Ajoutez vos solutions si vous le souhaitez :)
encode()
etdecode()
. Les étapes sont donc les suivantes: (1) Enregistrer l'URL dans la base de données (2) Obtenir l'ID de ligne unique pour cette URL à partir de la base de données (3) Convertir l'ID entier en chaîne courte avecencode()
, par exemple273984
enf5a4
(4) Utilisez la chaîne courte (par exemplef4a4
) dans votre URL partageables (5) Lors de la réception d'une demande de chaîne courte (par exemple20a8
), décodez la chaîne en un ID entier avecdecode()
(6) Recherchez l'URL dans la base de données pour l'ID donné. Pour la conversion, utilisez: github.com/delight-im/ShortURLRéponses:
Je continuerais votre approche "convertir le nombre en chaîne". Cependant, vous vous rendrez compte que l'algorithme proposé échoue si votre ID est un nombre premier supérieur à 52 .
Contexte théorique
Vous avez besoin d'une fonction bijective f . Ceci est nécessaire pour que vous puissiez trouver une fonction inverse g ('abc') = 123 pour votre fonction f (123) = 'abc' . Ça signifie:
Comment convertir l'ID en une URL raccourcie
[a-zA-Z0-9]
. Il contient 62 lettres .Prenez une clé numérique unique générée automatiquement (l'incrémentation automatique
id
d'une table MySQL par exemple).Pour cet exemple, je vais utiliser 125 10 (125 avec une base de 10).
Vous devez maintenant convertir 125 10 en X 62 (base 62).
125 10 = 2 × 62 1 + 1 × 62 0 =
[2,1]
Cela nécessite l'utilisation de la division entière et du modulo. Un exemple de pseudo-code:
Mappez maintenant les indices 2 et 1 à votre alphabet. Voici à quoi pourrait ressembler votre mappage (avec un tableau par exemple):
Avec 2 → c et 1 → b, vous recevrez cb 62 comme URL raccourcie.
Comment résoudre une URL raccourcie vers l'ID initial
L'inverse est encore plus facile. Vous effectuez simplement une recherche inversée dans votre alphabet.
e9a 62 sera résolu en "4e, 61e et 0e lettre de l'alphabet".
e9a 62 =
[4,61,0]
= 4 × 62 2 + 61 × 62 1 + 0 × 62 0 = 19158 10Maintenant, trouvez votre enregistrement de base de données avec
WHERE id = 19158
et faites la redirection.Exemples d'implémentations (fournies par les commentateurs)
la source
3792586=='F_ck'
avec u à la place de _). J'exclurais certains caractères comme u / U afin de minimiser cela.Pourquoi voudriez-vous utiliser un hachage?
Vous pouvez simplement utiliser une simple traduction de votre valeur d'incrémentation automatique en une valeur alphanumérique. Vous pouvez le faire facilement en utilisant une conversion de base. Supposons que votre espace de caractères (AZ, az, 0-9, etc.) comporte 40 caractères, convertissez l'identifiant en un nombre de base 40 et utilisez les caractères comme chiffres.
la source
la source
Pas une réponse à votre question, mais je n'utiliserais pas d'URL raccourcies sensibles à la casse. Ils sont difficiles à retenir, généralement illisibles (de nombreuses polices affichent 1 et l, 0 et O et d'autres caractères très très similaires qu'ils sont presque impossibles à faire la différence) et carrément sujets aux erreurs. Essayez d'utiliser uniquement des minuscules ou des majuscules.
Essayez également d'avoir un format dans lequel vous mélangez les chiffres et les caractères sous une forme prédéfinie. Il existe des études qui montrent que les gens ont tendance à se souvenir d'une forme mieux que d'autres (pensez aux numéros de téléphone, où les numéros sont regroupés sous une forme spécifique). Essayez quelque chose comme num-char-char-num-char-char. Je sais que cela réduira les combinaisons, surtout si vous n'avez pas de majuscules et de minuscules, mais ce serait plus utilisable et donc utile.
la source
Mon approche: prendre l'ID de base de données, puis encoder en Base36 . Je n'utiliserais PAS les deux lettres majuscules ET minuscules, car cela fait de la transmission de ces URL par téléphone un cauchemar, mais vous pouvez bien sûr facilement étendre la fonction pour en faire un décodeur / base 62.
la source
Voici ma classe PHP 5.
la source
Une solution Node.js et MongoDB
Puisque nous connaissons le format utilisé par MongoDB pour créer un nouvel ObjectId avec 12 octets.
Exemple (je choisis une séquence aléatoire) a1b2c3d4e5f6g7h8i9j1k2l3
Étant donné que le compteur sera unique si nous stockons les données dans la même machine, nous pouvons l'obtenir sans aucun doute qu'il sera dupliqué.
Ainsi, l'URL courte sera le compteur et voici un extrait de code en supposant que votre serveur fonctionne correctement.
la source
Version C #:
la source
Vous pouvez hacher l'intégralité de l'URL, mais si vous souhaitez simplement raccourcir l'ID, faites comme Marcel l'a suggéré. J'ai écrit cette implémentation Python:
https://gist.github.com/778542
la source
Je continue à incrémenter une séquence entière par domaine dans la base de données et j'utilise Hashids pour coder l'entier dans un chemin URL.
J'ai exécuté un script pour voir combien de temps cela prend jusqu'à ce qu'il épuise la longueur du personnage. Pour six caractères, il peut faire des
164,916,224
liens puis monter jusqu'à sept caractères. Bitly utilise sept caractères. Moins de cinq personnages me semble bizarre.Les Hashids peuvent décoder le chemin URL vers un entier, mais une solution plus simple consiste à utiliser le lien court entier
sho.rt/ka8ds3
comme clé primaire.Voici le concept complet:
la source
Si vous ne voulez pas réinventer la roue ... http://lilurl.sourceforge.net/
la source
la source
Voici ma version pour qui en a besoin.
la source
Jetez un œil à https://hashids.org/ il est open source et dans de nombreuses langues.
Leur page décrit certains des pièges d'autres approches.
la source
Pourquoi ne pas simplement traduire votre identifiant en une chaîne? Vous avez juste besoin d'une fonction qui mappe un chiffre entre, disons, 0 et 61 à une seule lettre (majuscule / minuscule) ou chiffre. Ensuite, appliquez-le pour créer, disons, des codes à 4 lettres, et vous avez couvert 14,7 millions d'URL.
la source
Voici une fonction de codage d'URL décente pour PHP ...
la source
Je ne sais pas si quelqu'un trouvera cela utile - il s'agit plutôt d'une méthode 'hack n slash', mais elle est simple et fonctionne bien si vous ne voulez que des caractères spécifiques.
la source
Avez-vous omis O, 0 et i exprès?
Je viens de créer une classe PHP basée sur la solution de Ryan.
la source
Voici ce que j'utilise:
C'est très rapide et peut prendre de longs entiers.
la source
Pour un projet similaire, pour obtenir une nouvelle clé, je crée une fonction wrapper autour d'un générateur de chaîne aléatoire qui appelle le générateur jusqu'à ce que j'obtienne une chaîne qui n'a pas déjà été utilisée dans ma table de hachage. Cette méthode ralentira une fois que votre espace de noms commencera à être plein, mais comme vous l'avez dit, même avec seulement 6 caractères, vous avez beaucoup d'espace de noms avec lequel travailler.
la source
J'ai une variante du problème, en ce sens que je stocke des pages Web de nombreux auteurs différents et que je dois empêcher la découverte de pages par conjecture. Donc, mes URL courtes ajoutent quelques chiffres supplémentaires à la chaîne Base-62 pour le numéro de page. Ces chiffres supplémentaires sont générés à partir des informations contenues dans l'enregistrement de page lui-même et garantissent que seules 1 URL sur 3844 sont valides (en supposant une base-62 à 2 chiffres). Vous pouvez voir une description générale sur http://mgscan.com/MBWL .
la source
Très bonne réponse, j'ai créé une implémentation Golang du bjf:
Hébergé sur github: https://github.com/xor-gate/go-bjf
la source
la source
Mise en œuvre à Scala:
Exemple de test avec test Scala:
la source
Fonction basée sur la classe Xeoncross
la source
Voici une implémentation Node.js qui est susceptible de bit.ly. générer une chaîne de sept caractères hautement aléatoire.
Il utilise la cryptographie Node.js pour générer un jeu de caractères 25 très aléatoire plutôt que de sélectionner au hasard sept caractères.
la source
Ma version Python 3
la source
Pour une solution Node.js / JavaScript de qualité, consultez le module id-shortener , qui est minutieusement testé et utilisé en production depuis des mois.
Il fournit un raccourcisseur id / URL efficace soutenu par un stockage enfichable par défaut sur Redis , et vous pouvez même personnaliser votre jeu de caractères id court et si le raccourcissement est idempotent ou non . Il s'agit d'une distinction importante que tous les raccourcisseurs d'URL ne prennent pas en compte.
Par rapport aux autres réponses ici, ce module implémente l'excellente réponse acceptée de Marcel Jackwerth ci-dessus.
Le cœur de la solution est fourni par l' extrait de code Redis Lua suivant :
la source
Pourquoi ne pas simplement générer une chaîne aléatoire et l'ajouter à l'URL de base? Il s'agit d'une version très simplifiée de cette opération en C # .
Ensuite, ajoutez simplement la chaîne aléatoire à l'URL de base:
N'oubliez pas qu'il s'agit d'une version très simplifiée de cette opération et qu'il est possible que la méthode RandomString puisse créer des chaînes en double. En production, vous voudrez tenir compte des chaînes en double pour vous assurer d'avoir toujours une URL unique. J'ai du code qui prend en compte les chaînes en double en interrogeant une table de base de données que je pourrais partager si quelqu'un est intéressé.
la source
Voici mes premières réflexions, et plus de réflexion peut être faite, ou une simulation peut être faite pour voir si cela fonctionne bien ou si une amélioration est nécessaire:
Ma réponse est de se souvenir de l'URL longue dans la base de données et d'utiliser l'ID
0
pour9999999999999999
(ou quel que soit le nombre requis).Mais l'ID 0
9999999999999999
peut être un problème, carA
-Z
a
-z
0
-9
_
et-
)0
à9999999999999999
uniformément, les pirates peuvent les visiter dans cet ordre et savoir quelles URL les gens s'envoient, ce qui peut donc être un problème de confidentialitéNous pouvons le faire:
0
à999
un serveur, le serveur A, donc maintenant le serveur A a 1000 de ces ID. Donc, s'il y a 20 ou 200 serveurs qui veulent constamment de nouveaux identifiants, il ne doit pas continuer à demander chaque nouvel identifiant, mais plutôt à demander une fois 1000 identifiants000...00000001
devient10000...000
, de sorte que lorsqu'il est converti en base64, il sera de plus en plus ID non uniforme à chaque fois.0xD5AA96...2373
(comme une clé secrète), et les quelques bits seront retournés. (chaque fois que la clé secrète a le bit 1, elle retournera le bit de l'ID). Cela rendra les ID encore plus difficiles à deviner et apparaîtra plus aléatoireSuivant ce schéma, le serveur unique qui alloue les ID peut former les ID, tout comme les 20 ou 200 serveurs qui demandent l'allocation des ID. Le serveur d'allocation doit utiliser un verrou / sémaphore pour empêcher deux serveurs demandeurs d'obtenir le même lot (ou s'il accepte une connexion à la fois, cela résout déjà le problème). Nous ne voulons donc pas que la ligne (file d'attente) soit trop longue pour attendre d'obtenir une allocation. C'est pourquoi l'allocation de 1 000 ou 10 000 à la fois peut résoudre le problème.
la source