구경만 하고 싶으면, '분류 결과'를 검색하거나 스크롤을 내리자
몇개월 전, 카카오톡에 '서양.한국' 등을 입력하면 성인 사이트가 나와 이슈가 됐었다. 사실 이는 한글로 만든 도메인으로, a.com 과 같이 그저 url이라서 그런 것 이었는데, 이런 비-알파벳 도메인은 어떤걸 만들 수 있을까?
우리가 보통 도메인을 만들게 되면
.com으로 끝날지, .net으로 끝날지 등 도메인의 마지막 .을 기준으로 오른쪽에 있는 최상위 도메인(TLD, Top Level Domain)또한 골라야한다. 사실 앞부분은 유니코드 문자면 어떤 것이든 상관 없으므로, TLD 중 비 알파벳 도메인을 찾아보자
TLD의 목록은 https://data.iana.org/TLD/tlds-alpha-by-domain.txt 에서 확인할 수 있다.
여기서 한국을 검색하면 나오질 않는다. 혹시 tlds-alpha-by-domain이라서 비 알파벳 도메인은 없는걸까?
사실 도메인에서 비 알파벳이 존재하면 퓨니코드(punycode)라는 인코딩으로 변환되는데, 흔히 url에 %20 과 같이 몇몇 문자를 %로 표기하는것(url encode)과 비슷하게 보면 된다.
퓨니코드는 xn--... 라는 방식으로 표시된다. 자세한 스팩이 궁금하다면 RFC 3492, RFC 5891을 참조하고, 변환해보고 싶다면 punycoder.com 를 확인하자.
예를 들어, hello서양.한국의 표니코드 표현은 xn--hello-7r5vh2u.xn--3e0b707e 인데, '.'을 제외하면 전부 바뀐것을 볼 수 있다.
즉, 우리는 https://data.iana.org/TLD/tlds-alpha-by-domain.txt 에서 xn--으로 시작하는 tld를 확인하면 된다. 프로그래밍을 통해 필터링후 디코드 해보자. 필자는 node를 이용했다.
const { readFile, writeFile } = require("fs/promises");
const punycode = require("punycode");
async function main()
{
const tlds_txt = (await readFile('./tlds-alpha-by-domain.txt')).toString();
writeFile('./tlds-parsed.txt', tlds_txt.split('\n').filter(tld => tld.startsWith('XN--')).map(v => {
return v + ': ' + punycode.toUnicode(v.toLowerCase());
}).join('\n'));
}
main()
*curl -LOJ https://data.iana.org/TLD/tlds-alpha-by-domain.txt를 통해 간단하게 파일을 다운로드 받을 수 있지만, 프로그래밍으로 fetch해와도 된다.
XN--11B4C3D: कॉम
XN--1CK2E1B: セール
..
*전문은 글의 말미에 첨부하겠다
1465개중 퓨니코드로 된 것은 152개 존재한다.
이를 언어별로 구분할 수 없을까? 처음엔 papago의 언어 감지 기능을 떠올렸지만, 귀찮으니 chatgpt보고 분류하라고 하자.
*이 글의 범위는 아니지만, chatgpt를 이용해 무언갈 자동화하고 싶다면, json 등의 이미 존재하는 구체적인 스팩을 명시하고 구조에 맞지 않으면 retry하는 방식이 좋다.
*끊기면 이어서 말해달라고 하면 된다.
하지만 gpt가 내는 결과는 오류가 꽤 있으므로, gpt를 두번 돌려 diff를 따서 수작업하자. 'diff'라는 명령을 이용해도 좋고, diffchecker.com 이런 사이트를 이용해도 편리하다.
이제 이를 국가별로 나눠 json으로 저장해보자
const { readFile, writeFile } = require("fs/promises");
const punycode = require("punycode");
async function main()
{
const tlds = (await readFile('./with-country.txt')).toString().trim().split('\n').map(v => ({
punycode: v.split(': ')[0],
decoded: v.split(': ').slice(1).join(': ').split(' - ')[0],
country: v.split(': ').slice(1).join(': ').split(' - ').slice(1).join(' - '),
}));
const countryToDomains = {};
for(const tld of tlds){
countryToDomains[tld.country] ??= [];
countryToDomains[tld.country].push(tld.punycode + '|' + tld.decoded);
}
writeFile('./res.json', JSON.stringify(countryToDomains, null, 4));
}
main();
===
분류 결과
{
"인도 (India)": [
"XN--11B4C3D|कॉम",
"XN--2SCRJ9C|ಭಾರತ",
"XN--3HCRJ9C|ଭାରତ",
"XN--45BR5CYL|ভাৰত",
"XN--45BRJ9C|ভারত",
"XN--FPCRJ9C3D|భారత్",
"XN--GECRJ9C|ભારત",
"XN--H2BREG3EVE|भारतम्",
"XN--H2BRJ9C|भारत",
"XN--H2BRJ9C8C|भारोत",
"XN--I1B6B1A6A2E|संगठन",
"XN--MGBBH1A71E|بھارت",
"XN--RVC1E0AM3E|ഭാരതം",
"XN--S9BRJ9C|ਭਾਰਤ",
"XN--XKC2DL3A5EE0H|இந்தியா"
],
"일본 (Japan)": [
"XN--1CK2E1B|セール",
"XN--BCK1B9A5DRE4C|ファッション",
"XN--CCK2B3B|ストア",
"XN--CCKWCXETD|アマゾン",
"XN--ECKVDTC9D|ポイント",
"XN--FCT429K|家電",
"XN--GCKR3F0F|クラウド",
"XN--GK3AT1E|通販",
"XN--Q9JYB4C|みんな",
"XN--TCKWE|コム",
"XN--QCKA1PMC|グーグル"
],
"중국 (China)": [
"XN--1QQW23A|佛山",
"XN--30RR7Y|慈善",
"XN--3BST00M|集团",
"XN--3DS443G|在线",
"XN--3PXU8K|点看",
"XN--45Q11C|八卦",
"XN--55QW42G|公益",
"XN--55QX5D|公司",
"XN--5SU34J936BGSG|香格里拉",
"XN--5TZM5G|网站",
"XN--6FRZ82G|移动",
"XN--6QQ986B3XL|我爱你",
"XN--8Y0A063A|联通",
"XN--9ET52U|时尚",
"XN--9KRT00A|微博",
"XN--CZR694B|商标",
"XN--CZRS0T|商店",
"XN--CZRU2D|商城",
"XN--EFVY88H|新闻",
"XN--FIQ228C5HS|中文网",
"XN--FIQ64B|中信",
"XN--FIQS8S|中国",
"XN--FIQZ9S|中國",
"XN--FJQ720A|娱乐",
"XN--FLW351E|谷歌",
"XN--G2XX48C|购物",
"XN--HXT814E|网店",
"XN--IMR513N|餐厅",
"XN--IO0A7I|网络",
"XN--JLQ480N2RG|亚马逊",
"XN--JVR189M|食品",
"XN--KCRX77D1X4A|飞利浦",
"XN--KPUT3I|手机",
"XN--MXTQ1M|政府",
"XN--NQV7F|机构",
"XN--NQV7FS00EMA|组织机构",
"XN--NYQY26A|健康",
"XN--OTU796D|招聘",
"XN--PSSY2U|大拿",
"XN--RHQV96G|世界",
"XN--ROVU88B|書籍",
"XN--SES554G|网址",
"XN--UNUP4Y|游戏",
"XN--VHQUV|企业",
"XN--VUQ861B|信息",
"XN--XHQ521B|广东",
"XN--ZFR164B|政务"
],
"대한민국 (South Korea)": [
"XN--3E0B707E|한국",
"XN--CG4BKI|삼성",
"XN--T60B56A|닷넷",
"XN--MK1BU44C|닷컴"
],
"태국 (Thailand)": [
"XN--42C2D9A|คอม",
"XN--O3CW4H|ไทย"
],
"이스라엘 (Israel)": [
"XN--4DBRK0CE|ישראל",
"XN--9DBQ2A|קום"
],
"아랍 (United Arab Emirates)": [
"XN--4GBRIM|موقع",
"XN--MGBAAKC7DVF|اتصالات",
"XN--MGBAAM7A8H|امارات",
"XN--MGBCA7DZDO|ابوظبي",
"XN--NGBRX|عرب"
],
"방글라데시 (Bangladesh)": [
"XN--54B7FTA0CC|বাংলা"
],
"러시아 (Russia)": [
"XN--80ADXHKS|москва",
"XN--80AQECDR1A|католик",
"XN--80ASEHDB|онлайн",
"XN--80ASWG|сайт",
"XN--C1AVG|орг",
"XN--D1ACJ3B|дети",
"XN--D1ALF|мкд",
"XN--P1ACF|рус",
"XN--P1AI|рф"
],
"카자흐스탄 (Kazakhstan)": [
"XN--80AO21A|қаз"
],
"세르비아 (Serbia)": [
"XN--90A3AC|срб"
],
"불가리아 (Bulgaria)": [
"XN--90AE|бг"
],
"벨라루스 (Belarus)": [
"XN--90AIS|бел"
],
"싱가포르 (Singapore)": [
"XN--B4W605FERD|淡马锡",
"XN--CLCHC0EA0B2G2A9GCD|சிங்கப்பூர்",
"XN--YFRO4I67O|新加坡"
],
"힌디어 (Hindi)": [
"XN--C2BR7G|नेट"
],
"유럽연합 (European Union)": [
"XN--E1A4C|ею"
],
"이집트 (Egypt)": [
"XN--FHBEI|كوم",
"XN--WGBH1C|مصر"
],
"스리랑카 (Sri Lanka)": [
"XN--FZC2C9E2C|ලංකා",
"XN--XKC2AL3HYE2A|இலங்கை"
],
"홍콩 (Hong Kong)": [
"XN--FZYS8D69UVGM|電訊盈科",
"XN--J6W193G|香港",
"XN--W4R85EL8FHU5DNRA|嘉里大酒店",
"XN--W4RS40L|嘉里"
],
"우크라이나 (Ukraine)": [
"XN--J1AEF|ком",
"XN--J1AMH|укр"
],
"대만 (Taiwan)": [
"XN--KPRW13D|台湾",
"XN--KPRY57D|台灣"
],
"몽골 (Mongolia)": [
"XN--L1ACC|мон"
],
"알제리 (Algeria)": [
"XN--LGBBAT1AD8J|الجزائر"
],
"오만 (Oman)": [
"XN--MGB9AWBF|عمان"
],
"사우디아라비아 (Saudi Arabia)": [
"XN--MGBA3A3EJT|ارامكو",
"XN--MGBA7C0BBN0A|العليان",
"XN--MGBERP4A5D4AR|السعودية",
"XN--NGBC5AZD|شبكة",
"XN--NGBE9E0A|بيتك"
],
"이란 (Iran)": [
"XN--MGBA3A4F16A|ایران",
"XN--MGBAB2BD|بازار",
"XN--MGBT3DHD|همراه"
],
"모리타니아 (Mauritania)": [
"XN--MGBAH1A3HJKRD|موريتانيا"
],
"파키스탄 (Pakistan)": [
"XN--MGBAI9AZGQP6J|پاکستان",
"XN--MGBGU82A|ڀارت"
],
"요르단 (Jordan)": [
"XN--MGBAYH7GPA|الاردن"
],
"바레인 (Bahrain)": [
"XN--MGBBH1A|بارت",
"XN--MGBCPQ6GPA1A|البحرين"
],
"모로코 (Morocco)": [
"XN--MGBC0A9AZCG|المغرب"
],
"교황청 (Vatican City)": [
"XN--MGBI4ECEXP|كاثوليك",
"XN--TIQ49XQYJ|天主教"
],
"수단 (Sudan)": [
"XN--MGBPL2FH|سودان"
],
"이라크 (Iraq)": [
"XN--MGBTX2B|عراق"
],
"말레이시아 (Malaysia)": [
"XN--MGBX4CD0AB|مليسيا"
],
"마카오 (Macao)": [
"XN--MIX891F|澳門"
],
"조지아 (Georgia)": [
"XN--NODE|გე"
],
"시리아 (Syria)": [
"XN--OGBPF8FL|سورية"
],
"튀니지 (Tunisia)": [
"XN--PGBS0DH|تونس"
],
"라오스 (Laos)": [
"XN--Q7CE6A|ລາວ"
],
"그리스 (Greece)": [
"XN--QXA6A|ευ",
"XN--QXAM|ελ"
],
"독일 (Germany)": [
"XN--VERMGENSBERATER-CTB|vermögensberater",
"XN--VERMGENSBERATUNG-PWB|vermögensberatung"
],
"카타르 (Qatar)": [
"XN--WGBL6A|قطر"
],
"아르메니아 (Armenia)": [
"XN--Y9A3AQ|հայ"
],
"팔레스타인 (Palestine)": [
"XN--YGBI2AMMX|فلسطين"
]
}
*누차 언급하지만, gpt에는 오류가 있을 수 있다.
한글 tld는 .삼성, .닷넷, .닷컴, .한국이 있음을 확인할 수 있다.
chatgpt의 XN--QCKA1PMC|グーグル 분류가 '국제' 길래 일본으로 수정 후 번역해봤는데, 우리가 아는 그 Google의 일본어 표기여서 독특했다
아까 생략했던 디코드된 데이터는 아래와 같다.
XN--11B4C3D: कॉम
XN--1CK2E1B: セール
XN--1QQW23A: 佛山
XN--2SCRJ9C: ಭಾರತ
XN--30RR7Y: 慈善
XN--3BST00M: 集团
XN--3DS443G: 在线
XN--3E0B707E: 한국
XN--3HCRJ9C: ଭାରତ
XN--3PXU8K: 点看
XN--42C2D9A: คอม
XN--45BR5CYL: ভাৰত
XN--45BRJ9C: ভারত
XN--45Q11C: 八卦
XN--4DBRK0CE: ישראל
XN--4GBRIM: موقع
XN--54B7FTA0CC: বাংলা
XN--55QW42G: 公益
XN--55QX5D: 公司
XN--5SU34J936BGSG: 香格里拉
XN--5TZM5G: 网站
XN--6FRZ82G: 移动
XN--6QQ986B3XL: 我爱你
XN--80ADXHKS: москва
XN--80AO21A: қаз
XN--80AQECDR1A: католик
XN--80ASEHDB: онлайн
XN--80ASWG: сайт
XN--8Y0A063A: 联通
XN--90A3AC: срб
XN--90AE: бг
XN--90AIS: бел
XN--9DBQ2A: קום
XN--9ET52U: 时尚
XN--9KRT00A: 微博
XN--B4W605FERD: 淡马锡
XN--BCK1B9A5DRE4C: ファッション
XN--C1AVG: орг
XN--C2BR7G: नेट
XN--CCK2B3B: ストア
XN--CCKWCXETD: アマゾン
XN--CG4BKI: 삼성
XN--CLCHC0EA0B2G2A9GCD: சிங்கப்பூர்
XN--CZR694B: 商标
XN--CZRS0T: 商店
XN--CZRU2D: 商城
XN--D1ACJ3B: дети
XN--D1ALF: мкд
XN--E1A4C: ею
XN--ECKVDTC9D: ポイント
XN--EFVY88H: 新闻
XN--FCT429K: 家電
XN--FHBEI: كوم
XN--FIQ228C5HS: 中文网
XN--FIQ64B: 中信
XN--FIQS8S: 中国
XN--FIQZ9S: 中國
XN--FJQ720A: 娱乐
XN--FLW351E: 谷歌
XN--FPCRJ9C3D: భారత్
XN--FZC2C9E2C: ලංකා
XN--FZYS8D69UVGM: 電訊盈科
XN--G2XX48C: 购物
XN--GCKR3F0F: クラウド
XN--GECRJ9C: ભારત
XN--GK3AT1E: 通販
XN--H2BREG3EVE: भारतम्
XN--H2BRJ9C: भारत
XN--H2BRJ9C8C: भारोत
XN--HXT814E: 网店
XN--I1B6B1A6A2E: संगठन
XN--IMR513N: 餐厅
XN--IO0A7I: 网络
XN--J1AEF: ком
XN--J1AMH: укр
XN--J6W193G: 香港
XN--JLQ480N2RG: 亚马逊
XN--JVR189M: 食品
XN--KCRX77D1X4A: 飞利浦
XN--KPRW13D: 台湾
XN--KPRY57D: 台灣
XN--KPUT3I: 手机
XN--L1ACC: мон
XN--LGBBAT1AD8J: الجزائر
XN--MGB9AWBF: عمان
XN--MGBA3A3EJT: ارامكو
XN--MGBA3A4F16A: ایران
XN--MGBA7C0BBN0A: العليان
XN--MGBAAKC7DVF: اتصالات
XN--MGBAAM7A8H: امارات
XN--MGBAB2BD: بازار
XN--MGBAH1A3HJKRD: موريتانيا
XN--MGBAI9AZGQP6J: پاکستان
XN--MGBAYH7GPA: الاردن
XN--MGBBH1A: بارت
XN--MGBBH1A71E: بھارت
XN--MGBC0A9AZCG: المغرب
XN--MGBCA7DZDO: ابوظبي
XN--MGBCPQ6GPA1A: البحرين
XN--MGBERP4A5D4AR: السعودية
XN--MGBGU82A: ڀارت
XN--MGBI4ECEXP: كاثوليك
XN--MGBPL2FH: سودان
XN--MGBT3DHD: همراه
XN--MGBTX2B: عراق
XN--MGBX4CD0AB: مليسيا
XN--MIX891F: 澳門
XN--MK1BU44C: 닷컴
XN--MXTQ1M: 政府
XN--NGBC5AZD: شبكة
XN--NGBE9E0A: بيتك
XN--NGBRX: عرب
XN--NODE: გე
XN--NQV7F: 机构
XN--NQV7FS00EMA: 组织机构
XN--NYQY26A: 健康
XN--O3CW4H: ไทย
XN--OGBPF8FL: سورية
XN--OTU796D: 招聘
XN--P1ACF: рус
XN--P1AI: рф
XN--PGBS0DH: تونس
XN--PSSY2U: 大拿
XN--Q7CE6A: ລາວ
XN--Q9JYB4C: みんな
XN--QCKA1PMC: グーグル
XN--QXA6A: ευ
XN--QXAM: ελ
XN--RHQV96G: 世界
XN--ROVU88B: 書籍
XN--RVC1E0AM3E: ഭാരതം
XN--S9BRJ9C: ਭਾਰਤ
XN--SES554G: 网址
XN--T60B56A: 닷넷
XN--TCKWE: コム
XN--TIQ49XQYJ: 天主教
XN--UNUP4Y: 游戏
XN--VERMGENSBERATER-CTB: vermögensberater
XN--VERMGENSBERATUNG-PWB: vermögensberatung
XN--VHQUV: 企业
XN--VUQ861B: 信息
XN--W4R85EL8FHU5DNRA: 嘉里大酒店
XN--W4RS40L: 嘉里
XN--WGBH1C: مصر
XN--WGBL6A: قطر
XN--XHQ521B: 广东
XN--XKC2AL3HYE2A: இலங்கை
XN--XKC2DL3A5EE0H: இந்தியா
XN--Y9A3AQ: հայ
XN--YFRO4I67O: 新加坡
XN--YGBI2AMMX: فلسطين
XN--ZFR164B: 政务
'헛소리' 카테고리의 다른 글
jekyll 테마 만들기 (0) | 2023.08.19 |
---|