Skip to content

Instantly share code, notes, and snippets.

@agusibrahim
Last active June 30, 2025 08:10
Show Gist options
  • Save agusibrahim/03a20d2ec1164d137c1460529fd5cec6 to your computer and use it in GitHub Desktop.
Save agusibrahim/03a20d2ec1164d137c1460529fd5cec6 to your computer and use it in GitHub Desktop.
get pelni ports
var token = document.querySelector("input[name='_token']").value;
var options = Array.from(document.querySelectorAll("select[name='ticket_org'] option")).filter(x => x.getAttribute("value") != "");
var results = [];
for (const option of options) {
var ids = option.getAttribute("value");
var b = option.innerText;
var dest=""
try {
var f = await fetch("https://pelni.co.id/getdes", {
"headers": {
"content-type": "application/x-www-form-urlencoded;",
},
"referrer": "https://pelni.co.id/",
"referrerPolicy": "strict-origin-when-cross-origin",
"body": "ticket_org=" + ids + "&_token=" + token,
"method": "POST",
"mode": "cors",
"credentials": "include"
});
var div = document.createElement('div');
div.innerHTML = await f.text();
var dest = Array.from(div.querySelectorAll("option")).filter(x => x.getAttribute("value") != "").map(x => x.getAttribute("value")).join(",");
await new Promise(resolve => setTimeout(resolve, 100));
} catch (e) {
}
var result = {
"name": b.split("|")[1].split("-")[1].trim(),
"code": b.split("|")[1].split("-")[0].trim(),
"city": b.split("|")[0].trim(),
"id": parseInt(ids),
"dest": dest
};
results.push(result);
}
document.body.outerText=JSON.stringify(results)
@agusibrahim
Copy link
Author

scrapper

function showProgressOverlay(message){let overlay=document.getElementById('pelni-progress-overlay');if(!overlay){overlay=document.createElement('div');overlay.id='pelni-progress-overlay';Object.assign(overlay.style,{position:'fixed',top:'0',left:'0',width:'100%',height:'100%',backgroundColor:'rgba(255, 255, 255, 0.95)',display:'flex',flexDirection:'column',justifyContent:'center',alignItems:'center',zIndex:'99999',fontSize:'24px',fontFamily:'Arial, sans-serif',color:'#333'});const progressBarContainer=document.createElement('div');Object.assign(progressBarContainer.style,{width:'300px',height:'20px',backgroundColor:'#eee',borderRadius:'10px',overflow:'hidden',marginBottom:'15px'});const progressBar=document.createElement('div');progressBar.id='pelni-progress-bar';Object.assign(progressBar.style,{width:'0%',height:'100%',backgroundColor:'#007bff',borderRadius:'10px',transition:'width 0.2s ease-in-out'});progressBarContainer.appendChild(progressBar);overlay.appendChild(progressBarContainer);const progressText=document.createElement('div');progressText.id='pelni-progress-text';progressText.innerText=message;overlay.appendChild(progressText);document.body.appendChild(overlay)}else{document.getElementById('pelni-progress-text').innerText=message}
document.body.style.overflow='hidden'}
function updateProgress(current,total,message){const progressBar=document.getElementById('pelni-progress-bar');const progressText=document.getElementById('pelni-progress-text');if(progressBar&&progressText){const percentage=(current/total)*100;progressBar.style.width=percentage+'%';progressText.innerText=`Memproses: ${message} (${current}/${total})`}}
function hideProgressOverlay(){const overlay=document.getElementById('pelni-progress-overlay');if(overlay){overlay.remove()}
document.body.style.overflow=''}
function displayJsonResult(data){document.body.innerHTML='';document.body.style.backgroundColor='#f5f5f5';document.body.style.margin='0';document.body.style.padding='20px';document.body.style.fontFamily='monospace';document.body.style.whiteSpace='pre-wrap';document.body.style.wordWrap='break-word';document.body.style.color='#333';const pre=document.createElement('pre');pre.textContent=JSON.stringify(data,null,2);document.body.appendChild(pre);const copyButton=document.createElement('button');copyButton.textContent='Salin JSON';Object.assign(copyButton.style,{position:'fixed',top:'10px',right:'10px',padding:'10px 20px',fontSize:'16px',backgroundColor:'#28a745',color:'white',border:'none',borderRadius:'5px',cursor:'pointer',zIndex:'100000'});copyButton.onclick=()=>{navigator.clipboard.writeText(JSON.stringify(data,null,2)).then(()=>{copyButton.textContent='Tersalin!';setTimeout(()=>copyButton.textContent='Salin JSON',2000)}).catch(err=>{console.error('Gagal menyalin:',err);alert('Gagal menyalin JSON ke clipboard.')})};document.body.appendChild(copyButton)}(async()=>{document.body.innerHTML='';showProgressOverlay("Memulai scraping data...");let token;let tempDiv;try{const originalBody=await fetch(window.location.href).then(res=>res.text());tempDiv=document.createElement('div');tempDiv.innerHTML=originalBody;const tokenInput=tempDiv.querySelector("input[name='_token']");if(tokenInput){token=tokenInput.value}else{throw new Error("Token CSRF tidak ditemukan. Pastikan Anda menjalankan script ini di halaman Pelni yang memiliki formulir.")}}catch(error){hideProgressOverlay();displayJsonResult({error:error.message});console.error(error);return}
if(!tempDiv){hideProgressOverlay();displayJsonResult({error:"Gagal mendapatkan elemen halaman asli untuk scraping."});return}
const options=Array.from(tempDiv.querySelectorAll("select[name='ticket_org'] option")).filter(x=>x.getAttribute("value")!=="");const totalOptions=options.length;const results=[];for(let i=0;i<totalOptions;i++){const option=options[i];const ids=option.getAttribute("value");const b=option.innerText;let dest="";updateProgress(i+1,totalOptions,`Pelabuhan ${b.split('|')[1].split('-')[1].trim()}`);try{const f=await fetch("https://pelni.co.id/getdes",{"headers":{"content-type":"application/x-www-form-urlencoded;",},"referrer":"https://pelni.co.id/","referrerPolicy":"strict-origin-when-cross-origin","body":"ticket_org="+ids+"&_token="+token,"method":"POST","mode":"cors","credentials":"include"});const div=document.createElement('div');div.innerHTML=await f.text();dest=Array.from(div.querySelectorAll("option")).filter(x=>x.getAttribute("value")!=="").map(x=>x.getAttribute("value")).join(",");await new Promise(resolve=>setTimeout(resolve,100))}catch(e){console.error(`Gagal mengambil data untuk ID ${ids}:`,e)}
const result={"name":b.split("|")[1].split("-")[1].trim(),"code":b.split("|")[1].split("-")[0].trim(),"city":b.split("|")[0].trim(),"id":parseInt(ids),"dest":dest};results.push(result)}
hideProgressOverlay();displayJsonResult(results);console.log("Scraping Selesai!");console.log(results)})()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment