| Server IP : 173.209.174.21 / Your IP : 216.73.216.89 Web Server : Apache/2.4.58 (Ubuntu) System : Linux wcfs-server 6.8.0-124-generic #124-Ubuntu SMP PREEMPT_DYNAMIC Tue May 26 13:00:45 UTC 2026 x86_64 User : nodor ( 1000) PHP Version : 8.3.6 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : OFF Directory : /var/www/wcfs/warrent/ |
Upload File : |
<?php
/**
* Warrant Search scraper → CSV exporter (browser + CLI, with path + permission checks)
*/
ini_set('memory_limit', '512M');
set_time_limit(0);
$isCli = (php_sapi_name() === 'cli');
// === CONFIG: where to put the CSV ===
// It will save IN THE SAME FOLDER as this script.
$baseDir = __DIR__;
$timestamp = date('Ymd_His');
$outputCsv = $baseDir . "/warrants_export_$timestamp.csv";
$debugText0 = $baseDir . "/debug_page0.txt";
$baseUrl = "https://doc.wa.gov/records/incarcerated-data-search/warrant-search";
$outputCsvUrl = basename($outputCsv); // URL relative to this script
$userAgent = "Mozilla/5.0 (compatible; WCFS-scraper/1.0; +you@example.com)";
// -------------- Simple logger -------------------
function logmsg($msg)
{
global $isCli;
if ($isCli) {
echo $msg . "\n";
} else {
echo htmlspecialchars($msg, ENT_QUOTES, 'UTF-8') . "\n";
}
}
// -------------- HTTP FETCH -------------------
function fetchPage($url, $pageNum, $userAgent)
{
$ch = curl_init();
$params = ['page' => $pageNum];
$fullUrl = $url . '?' . http_build_query($params);
curl_setopt_array($ch, [
CURLOPT_URL => $fullUrl,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_USERAGENT => $userAgent,
CURLOPT_TIMEOUT => 30,
CURLOPT_SSL_VERIFYPEER => true,
]);
$html = curl_exec($ch);
if ($html === false) {
$err = curl_error($ch);
curl_close($ch);
throw new RuntimeException("cURL error fetching $fullUrl: $err");
}
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($status >= 400) {
throw new RuntimeException("HTTP $status fetching $fullUrl");
}
return $html;
}
// -------------- PARSER -------------------
function parseWarrantPage($html, $debugFile = null, $pageNum = 0)
{
// Strip HTML tags and decode entities
$text = html_entity_decode(strip_tags($html));
// For debugging: write raw text of first page once
if ($debugFile && $pageNum === 0 && !file_exists($debugFile)) {
file_put_contents($debugFile, $text);
}
// Normalize all whitespace to single spaces
$normalized = preg_replace('/\s+/', ' ', $text);
$normalized = trim($normalized);
$records = [];
$pattern = '/(\d{2}\/\d{2}\/\d{4})\s+([^0-9]+?)\s+([A-Z0-9 ,\'\-\/]+?)\s+([A-Za-z ]+?)\s+Name:/';
$matches = [];
preg_match_all($pattern, $normalized, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE);
if (!$matches) {
return [];
}
$numMatches = count($matches);
$textLen = strlen($normalized);
for ($i = 0; $i < $numMatches; $i++) {
$m = $matches[$i];
$start = $m[0][1];
$end = ($i + 1 < $numMatches) ? $matches[$i + 1][0][1] : $textLen;
$chunk = substr($normalized, $start, $end - $start);
$record = [
'warrant_date_header' => $m[1][0],
'name_header' => trim($m[2][0]),
'crime_header' => trim($m[3][0]),
'county_header' => trim($m[4][0]),
'name' => '',
'doc_number' => '',
'supervision_county' => '',
'crime_type' => '',
'warrant_issue_date' => '',
'age' => '',
'birthdate' => '',
'height' => '',
'weight' => '',
'eye_color' => '',
'hair_color' => '',
'race' => '',
'hispanic' => '',
];
if (preg_match('/Name:\s*(.+?)\s*DOC Number:/', $chunk, $m2)) {
$record['name'] = trim($m2[1]);
}
if (preg_match('/DOC Number:\s*(.+?)\s*Supervision County:/', $chunk, $m2)) {
$record['doc_number'] = trim($m2[1]);
}
if (preg_match('/Supervision County:\s*(.+?)\s*Crime Type:/', $chunk, $m2)) {
$record['supervision_county'] = trim($m2[1]);
}
if (preg_match('/Crime Type:\s*(.+?)\s*Secretary\'?s Warrant/', $chunk, $m2)) {
$record['crime_type'] = trim($m2[1]);
}
if (preg_match('/Date Issued:\s*(.+?)\s+Submit a Tip/', $chunk, $m2)) {
$record['warrant_issue_date'] = trim($m2[1]);
}
if (preg_match('/Age:\s*([^ ]+)\s+Birthdate:/', $chunk, $m2)) {
$record['age'] = trim($m2[1]);
}
if (preg_match('/Birthdate:\s*(.+?)\s+Height:/', $chunk, $m2)) {
$record['birthdate'] = trim($m2[1]);
}
if (preg_match('/Height:\s*(.+?)\s+Weight:/', $chunk, $m2)) {
$record['height'] = trim($m2[1]);
}
if (preg_match('/Weight:\s*(.+?)\s+Eye Color:/', $chunk, $m2)) {
$record['weight'] = trim($m2[1]);
}
if (preg_match('/Eye Color:\s*(.+?)\s+Hair Color:/', $chunk, $m2)) {
$record['eye_color'] = trim($m2[1]);
}
if (preg_match('/Hair Color:\s*(.+?)\s+Race:/', $chunk, $m2)) {
$record['hair_color'] = trim($m2[1]);
}
if (preg_match('/Race:\s*(.+?)\s+Hispanic:/', $chunk, $m2)) {
$record['race'] = trim($m2[1]);
}
if (preg_match('/Hispanic:\s*(Yes|No)/i', $chunk, $m2)) {
$record['hispanic'] = trim($m2[1]);
}
$records[] = $record;
}
return $records;
}
// -------------- MAIN -------------------
if (!$isCli) {
header('Content-Type: text/html; charset=utf-8');
echo "<!DOCTYPE html><html><head><title>Warrant Export</title></head><body>";
echo "<h1>Warrant Export</h1>";
echo "<p><strong>Script directory (where files are written):</strong><br><code>" .
htmlspecialchars($baseDir, ENT_QUOTES, 'UTF-8') . "</code></p>";
echo "<pre>";
}
logmsg("Starting scrape...");
logmsg("Output CSV will be: $outputCsv");
$page = 0;
$allRecords = [];
$maxPages = 500;
while ($page < $maxPages) {
logmsg("Fetching page $page...");
try {
$html = fetchPage($baseUrl, $page, $userAgent);
} catch (Exception $e) {
logmsg("Error fetching page $page: " . $e->getMessage());
break;
}
$pageRecords = parseWarrantPage($html, $debugText0, $page);
$countPage = count($pageRecords);
logmsg(" Parsed $countPage records on this page.");
if ($countPage === 0) {
logmsg("No more records found. Stopping.");
break;
}
$allRecords = array_merge($allRecords, $pageRecords);
$page++;
sleep(1);
}
// -------------- WRITE CSV -------------------
if (empty($allRecords)) {
logmsg("No records collected. Nothing to write.");
if (!$isCli) {
echo "</pre><p>No CSV was generated.</p></body></html>";
}
exit(0);
}
// Try to open file
$fp = @fopen($outputCsv, 'w');
if (!$fp) {
$dirPerms = substr(sprintf('%o', fileperms($baseDir)), -4);
logmsg("ERROR: Unable to open CSV for writing: $outputCsv");
logmsg("Directory permissions for $baseDir are: $dirPerms");
logmsg("The web server user probably does NOT have write permission here.");
if (!$isCli) {
echo "</pre><p><strong>ERROR:</strong> Cannot write CSV. Check folder permissions.</p></body></html>";
}
exit(1);
}
// Determine columns from keys
$headers = array_keys($allRecords[0]);
// Header row
fputcsv($fp, $headers);
// Data
foreach ($allRecords as $row) {
$line = [];
foreach ($headers as $h) {
$line[] = isset($row[$h]) ? $row[$h] : '';
}
fputcsv($fp, $line);
}
fclose($fp);
// Verify existence
clearstatcache();
if (file_exists($outputCsv)) {
$real = realpath($outputCsv);
logmsg("Done. Wrote " . count($allRecords) . " records.");
logmsg("CSV file exists at: $real");
} else {
logmsg("ERROR: After writing, CSV file DOES NOT EXIST. Something is wrong with filesystem/permissions.");
}
if ($isCli) {
exit(0);
} else {
echo "</pre>";
if (file_exists($outputCsv)) {
echo "<p><strong>CSV ready:</strong> ";
echo "<a href=\"" . htmlspecialchars($outputCsvUrl, ENT_QUOTES, 'UTF-8') . "\">Download " .
htmlspecialchars($outputCsvUrl, ENT_QUOTES, 'UTF-8') . "</a></p>";
} else {
echo "<p><strong>ERROR:</strong> CSV file was not found on disk. Check permissions on:<br><code>" .
htmlspecialchars($baseDir, ENT_QUOTES, 'UTF-8') . "</code></p>";
}
echo "</body></html>";
}