Saya ingin membuat layanan penyingkat URL di mana Anda dapat menulis URL panjang ke dalam kolom input dan layanan mempersingkat URL menjadi " http://www.example.org/abcdef
".
Alih-alih " abcdef
" bisa ada string lain dengan enam karakter yang mengandung a-z, A-Z and 0-9
. Itu membuat 56 ~ 57 miliar string mungkin.
Pendekatan saya:
Saya memiliki tabel database dengan tiga kolom:
- id, integer, peningkatan otomatis
- long, string, URL panjang yang dimasukkan pengguna
- pendek, string, URL singkat (atau hanya enam karakter)
Saya kemudian akan memasukkan URL panjang ke tabel. Lalu saya akan memilih nilai kenaikan-otomatis untuk " id
" dan membangun hashnya. Hash ini kemudian harus dimasukkan sebagai " short
". Tapi hash macam apa yang harus saya bangun? Algoritma hash seperti MD5 membuat string terlalu panjang. Saya tidak menggunakan algoritma ini, saya pikir. Algoritma yang dibangun sendiri akan bekerja juga.
Ide saya:
Untuk " http://www.google.de/
" saya mendapatkan id kenaikan-otomatis 239472
. Lalu saya melakukan langkah-langkah berikut:
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.
Itu bisa diulang sampai jumlahnya tidak habis dibagi lagi. Apakah Anda pikir ini pendekatan yang baik? Apakah Anda punya ide yang lebih baik?
Karena minat yang sedang berlangsung dalam topik ini, saya telah menerbitkan solusi yang efisien untuk GitHub , dengan implementasi untuk JavaScript , PHP , Python , dan Java . Tambahkan solusi Anda jika Anda suka :)
encode()
dandecode()
fungsinya. Oleh karena itu langkah-langkahnya adalah: (1) Simpan URL dalam basis data (2) Dapatkan ID baris unik untuk URL tersebut dari basis data (3) Konversikan ID integer ke string pendek denganencode()
, misalnya273984
kef5a4
(4) Gunakan string pendek (mis.f4a4
) Di URL sharable (5) Saat menerima permintaan untuk string pendek (mis.20a8
), dekode string ke ID integer dengandecode()
(6) Cari URL dalam database untuk ID yang diberikan. Untuk konversi, gunakan: github.com/delight-im/ShortURLJawaban:
Saya akan melanjutkan pendekatan "convert number to string" Anda. Namun, Anda akan menyadari bahwa algoritma yang Anda usulkan gagal jika ID Anda adalah yang utama dan lebih besar dari 52 .
Latar belakang teoritis
Anda membutuhkan Fungsi Bijektif f . Ini diperlukan agar Anda dapat menemukan fungsi terbalik g ('abc') = 123 untuk fungsi f Anda (123) = 'abc' . Ini berarti:
Cara mengonversi ID ke URL yang disingkat
[a-zA-Z0-9]
. Ini berisi 62 huruf .Ambil kunci numerik unik yang dibuat secara otomatis (
id
misalnya tabel MySQL yang ditambahkan secara otomatis ).Untuk contoh ini, saya akan menggunakan 125 10 (125 dengan basis 10).
Sekarang Anda harus mengonversi 125 10 ke X 62 (basis 62).
125 10 = 2 × 62 1 + 1 × 62 0 =
[2,1]
Ini membutuhkan penggunaan pembagian integer dan modulo. Contoh kode pseudo:
Sekarang petakan indeks 2 dan 1 ke alfabet Anda. Beginilah tampilan pemetaan Anda (dengan array misalnya):
Dengan 2 → c dan 1 → b, Anda akan menerima cb 62 sebagai URL singkat.
Cara mengatasi URL singkat ke ID awal
Kebalikannya bahkan lebih mudah. Anda hanya melakukan pencarian terbalik di alfabet Anda.
e9a 62 akan diselesaikan menjadi "huruf ke-4, ke-61, dan ke-0 dalam alfabet".
e9a 62 =
[4,61,0]
= 4 × 62 2 + 61 × 62 1 + 0 × 62 0 = 19158 10Sekarang temukan database-record Anda dengan
WHERE id = 19158
dan lakukan redirect.Contoh implementasi (disediakan oleh komentator)
sumber
3792586=='F_ck'
dengan Anda menggantikan _). Saya akan mengecualikan beberapa karakter seperti u / U untuk meminimalkan ini.Mengapa Anda ingin menggunakan hash?
Anda bisa menggunakan terjemahan sederhana dari nilai kenaikan otomatis Anda ke nilai alfanumerik. Anda dapat melakukannya dengan mudah dengan menggunakan beberapa konversi basis. Say you space karakter (AZ, az, 0-9, dll.) Memiliki 40 karakter, konversikan id ke nomor base-40 dan gunakan karakter sebagai digit.
sumber
sumber
Bukan jawaban untuk pertanyaan Anda, tetapi saya tidak akan menggunakan URL singkat yang peka terhadap huruf besar-kecil. Mereka sulit untuk diingat, biasanya tidak dapat dibaca (banyak font membuat 1 dan l, 0 dan O dan karakter lainnya sangat mirip sehingga mereka hampir tidak mungkin untuk mengetahui perbedaannya) dan rawan kesalahan. Coba gunakan huruf kecil atau huruf besar saja.
Juga, cobalah memiliki format tempat Anda mencampur angka dan karakter dalam bentuk yang telah ditentukan. Ada penelitian yang menunjukkan bahwa orang cenderung mengingat satu bentuk lebih baik daripada yang lain (pikirkan nomor telepon, di mana jumlahnya dikelompokkan dalam bentuk tertentu). Cobalah sesuatu seperti num-char-char-num-char-char. Saya tahu ini akan menurunkan kombinasi, terutama jika Anda tidak memiliki huruf besar dan kecil, tetapi akan lebih bermanfaat dan karenanya berguna.
sumber
Pendekatan saya: Ambil ID Database, lalu Base36 Encode . Saya TIDAK akan menggunakan kedua huruf besar dan huruf kecil, karena itu membuat pengiriman URL tersebut melalui telepon menjadi mimpi buruk, tetapi tentu saja Anda dapat dengan mudah memperluas fungsi menjadi basis 62 en / decoder.
sumber
Ini kelas PHP 5 saya.
sumber
Solusi Node.js dan MongoDB
Karena kita tahu format yang digunakan MongoDB untuk membuat ObjectId baru dengan 12 byte.
Contoh (saya memilih urutan acak) a1b2c3d4e5f6g7h8i9j1k2l3
Karena penghitung akan menjadi unik jika kita menyimpan data di mesin yang sama kita bisa mendapatkannya tanpa ragu bahwa itu akan duplikat.
Jadi URL pendek akan menjadi penghitung dan di sini ada potongan kode dengan asumsi server Anda berjalan dengan baik.
sumber
Versi C #:
sumber
Anda dapat meng-hash seluruh URL, tetapi jika Anda hanya ingin mempersingkat id, lakukan seperti yang disarankan marcel. Saya menulis implementasi Python ini:
https://gist.github.com/778542
sumber
Saya terus menambahkan urutan integer per domain dalam database dan menggunakan Hashids untuk menyandikan integer ke jalur URL.
Saya menjalankan skrip untuk melihat berapa lama sampai panjang karakter habis. Untuk enam karakter dapat melakukan
164,916,224
tautan dan kemudian naik hingga tujuh karakter. Sedikit menggunakan tujuh karakter. Di bawah lima karakter terlihat aneh bagiku.Hashids dapat mendekode jalur URL kembali ke integer tetapi solusi yang lebih sederhana adalah dengan menggunakan seluruh tautan pendek
sho.rt/ka8ds3
sebagai kunci utama.Inilah konsep lengkapnya:
sumber
Jika Anda tidak ingin menemukan kembali roda ... http://lilurl.sourceforge.net/
sumber
sumber
Inilah versi saya untuk siapa pun yang membutuhkannya.
sumber
Mengapa tidak menerjemahkan id Anda ke string saja? Anda hanya perlu fungsi yang memetakan digit antara, katakanlah, 0 dan 61 ke satu huruf (huruf besar / kecil) atau digit. Kemudian terapkan ini untuk membuat, katakanlah, kode 4 huruf, dan Anda mendapatkan 14,7 juta URL.
sumber
Berikut adalah fungsi penyandian URL yang layak untuk PHP ...
sumber
Tidak tahu apakah ada yang akan menemukan ini berguna - ini lebih dari metode 'hack n slash', namun sederhana dan berfungsi dengan baik jika Anda hanya menginginkan karakter tertentu.
sumber
Apakah Anda sengaja menghilangkan O, 0, dan saya?
Saya baru saja membuat kelas PHP berdasarkan pada solusi Ryan.
sumber
Lihatlah https://hashids.org/ ini adalah open source dan dalam banyak bahasa.
Halaman mereka menguraikan beberapa jebakan dari pendekatan lain.
sumber
Inilah yang saya gunakan:
Ini sangat cepat dan bisa memakan waktu lama.
sumber
Untuk proyek serupa, untuk mendapatkan kunci baru, saya membuat fungsi pembungkus di sekitar generator string acak yang memanggil generator sampai saya mendapatkan string yang belum pernah digunakan dalam hashtable saya. Metode ini akan melambat begitu ruang nama Anda mulai penuh, tetapi seperti yang telah Anda katakan, bahkan dengan hanya 6 karakter, Anda memiliki banyak ruang nama untuk digunakan.
sumber
Saya memiliki varian masalah, yaitu saya menyimpan halaman web dari banyak penulis yang berbeda dan perlu mencegah penemuan halaman dengan menebak. Jadi URL pendek saya menambahkan beberapa digit tambahan ke string Base-62 untuk nomor halaman. Digit tambahan ini dihasilkan dari informasi dalam catatan halaman itu sendiri dan mereka memastikan bahwa hanya 1 dari 3844 URL yang valid (dengan asumsi 2-digit Base-62). Anda dapat melihat uraian garis besar di http://mgscan.com/MBWL .
sumber
Jawaban yang sangat bagus, saya telah membuat implementasi Golang bjf:
Diinangi di github: https://github.com/xor-gate/go-bjf
sumber
sumber
Implementasi dalam Scala:
Contoh uji dengan uji Scala:
sumber
Fungsi berbasis di Kelas Xeoncross
sumber
Berikut ini adalah implementasi Node.js yang cenderung bit.ly. menghasilkan string tujuh karakter yang sangat acak.
Ini menggunakan Node.js crypto untuk menghasilkan charset 25 yang sangat acak daripada secara acak memilih tujuh karakter.
sumber
Versi Python 3 saya
sumber
Untuk solusi Node.js / JavaScript yang berkualitas, lihat modul id-shortener , yang diuji secara menyeluruh dan telah digunakan dalam produksi selama berbulan-bulan.
Ini menyediakan id / pemendek efisien yang didukung oleh penyimpanan pluggable default ke Redis , dan Anda bahkan dapat menyesuaikan set karakter id pendek Anda dan apakah pemendekan idempoten atau tidak . Ini adalah perbedaan penting yang tidak diperhitungkan oleh semua penyingkat URL.
Sehubungan dengan jawaban lain di sini, modul ini mengimplementasikan jawaban yang diterima sangat baik oleh Marcel Jackwerth di atas.
Inti dari solusi disediakan oleh cuplikan Redis Lua berikut :
sumber
Mengapa tidak hanya membuat string acak dan menambahkannya ke URL dasar? Ini adalah versi yang sangat sederhana untuk melakukan ini di C # .
Kemudian cukup tambahkan append string acak ke baseURL:
Ingat ini adalah versi yang sangat sederhana untuk melakukan ini dan mungkin metode RandomString dapat membuat string duplikat. Dalam produksi, Anda ingin memperhitungkan string duplikat untuk memastikan Anda akan selalu memiliki URL unik. Saya memiliki beberapa kode yang memperhitungkan string duplikat dengan menanyakan tabel database yang bisa saya bagikan jika ada yang tertarik.
sumber
Ini adalah pemikiran awal saya, dan lebih banyak pemikiran dapat dilakukan, atau beberapa simulasi dapat dilakukan untuk melihat apakah itu bekerja dengan baik atau diperlukan perbaikan:
Jawaban saya adalah mengingat URL panjang dalam database, dan menggunakan ID
0
untuk9999999999999999
(atau seberapa besar jumlahnya diperlukan).Tetapi ID 0 untuk
9999999999999999
dapat menjadi masalah, karenaA
-Z
a
-z
0
-9
_
dan-
)0
menjadi9999999999999999
seragam, maka peretas dapat mengunjunginya dalam urutan itu dan mengetahui URL apa yang orang kirim satu sama lain, sehingga ini bisa menjadi masalah privasiKita bisa melakukan ini:
0
untuk999
satu server, Server A, jadi sekarang Server A memiliki 1000 ID tersebut. Jadi jika ada 20 atau 200 server terus-menerus menginginkan ID baru, itu tidak harus terus meminta setiap ID baru, tetapi meminta satu kali untuk 1000 ID000...00000001
menjadi10000...000
, sehingga ketika dikonversi ke base64, itu akan meningkatkan ID yang tidak seragam setiap kali.0xD5AA96...2373
(seperti kunci rahasia), dan beberapa bit akan dibalik. (setiap kali kunci rahasia diaktifkan 1 bit, itu akan membalik bit ID). Ini akan membuat ID semakin sulit ditebak dan tampak lebih acakMengikuti skema ini, server tunggal yang mengalokasikan ID dapat membentuk ID, dan begitu juga 20 atau 200 server yang meminta alokasi ID. Server pengalokasian harus menggunakan kunci / semafor untuk mencegah dua server yang meminta mendapatkan batch yang sama (atau jika menerima satu koneksi pada satu waktu, ini sudah memecahkan masalah). Jadi kami tidak ingin antrean terlalu lama menunggu untuk mendapatkan alokasi. Jadi itu sebabnya mengalokasikan 1000 atau 10.000 sekaligus dapat menyelesaikan masalah.
sumber