392 lines
12 KiB
PHP
392 lines
12 KiB
PHP
<?php
|
|
|
|
$config = parse_ini_file("config.php", true);
|
|
$db = $config['general']['db'];
|
|
$queryurl = $config['general']['url'];
|
|
|
|
// make backup of database
|
|
$db_bak = $db . ".bak_" . date('Y-m-d');
|
|
if (! file_exists($db_bak)) {
|
|
copy($db, $db_bak);
|
|
}
|
|
|
|
// Called via CLI or web?
|
|
if (defined('STDIN')) {
|
|
$do = $argv[1];
|
|
} else {
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
$do = isset($_POST['do']) ? $_POST['do'] : false;
|
|
} else {
|
|
$do = isset($_GET['do']) ? $_GET['do'] : false;
|
|
}
|
|
}
|
|
|
|
// define action via "do" parameter
|
|
if ($do === "download") {
|
|
immo_download($db);
|
|
} else if ($do === "update") {
|
|
immo_update($db);
|
|
} else if ($do === "show" || $do == "") {
|
|
immo_show($db);
|
|
} else {
|
|
echo "No valid do action defined";
|
|
}
|
|
|
|
/////////////////////
|
|
/// do = DOWNLOAD ///
|
|
/////////////////////
|
|
function immo_download($db) {
|
|
global $data;
|
|
global $queryurl;
|
|
global $config;
|
|
read_db($db);
|
|
|
|
$site = xsite($queryurl); // load and transform URL (page 1) to queryable $site
|
|
|
|
// get amount of available pages
|
|
$searchPages = $site->query('//div[@id="pageSelection"]/select');
|
|
if($searchPages->length == 0) {
|
|
$pages=1;
|
|
} else {
|
|
$pages = $searchPages->item(0)->childNodes->length;
|
|
}
|
|
// create a dynamic url in which the current page number can be set in
|
|
$queryurldyn = preg_replace("/\/Suche\//", "/Suche/P-%page%/", $queryurl);
|
|
|
|
// loop through available pages
|
|
for ($page = 1; $page <= $pages; $page++) {
|
|
$queryurlcur = str_replace("%page%", $page, $queryurldyn);
|
|
echo "Current search page: " . $queryurlcur . "<br />\n";
|
|
|
|
$site = xsite($queryurlcur); // load and transform URL of current page
|
|
// get all links to expose pages
|
|
$searchResult = $site->query('//a[@class="result-list-entry__brand-title-container"]/@href');
|
|
|
|
// loop through web search results
|
|
foreach($searchResult as $result){
|
|
global $data;
|
|
$new = "y"; // is the search entry new?
|
|
// extract ID of link
|
|
preg_match("/\d+$/",$result->textContent, $matches);
|
|
$id = $matches[0];
|
|
$id = (int)$id; // convert to int value
|
|
|
|
$total = count($data);
|
|
for ($row = 0; $row < $total; $row++) {
|
|
if ($id === $data[$row]['id']) {
|
|
$new = "n"; // entry isn't new anymore
|
|
}
|
|
}
|
|
|
|
if ($new === "y") { // entry is new
|
|
|
|
// load and transform expose URL
|
|
$site = xsite("https://www.immobilienscout24.de/expose/" . $id);
|
|
|
|
// description
|
|
$searchResult = $site->query('//h1[@id="expose-title"]');
|
|
$desc = trim($searchResult->item(0)->nodeValue);
|
|
$desc = mb_convert_encoding($desc, 'UTF-8', 'UTF-8'); // remove/replace invalid characters
|
|
$descs = substr($desc, 0, 15);
|
|
$descs = mb_convert_encoding($descs, 'UTF-8', 'UTF-8');
|
|
|
|
// flat available from
|
|
$searchResult = $site->query('//dd[@class="is24qa-bezugsfrei-ab grid-item three-fifths"]');
|
|
$bezug = trim($searchResult->item(0)->nodeValue);
|
|
|
|
// warm rent
|
|
$searchResult = $site->query('//dd[@class="is24qa-gesamtmiete grid-item three-fifths font-bold"]');
|
|
$mietew = trim($searchResult->item(0)->nodeValue);
|
|
|
|
// cold rent
|
|
$searchResult = $site->query('//dd[@class="is24qa-kaltmiete grid-item three-fifths"]');
|
|
$mietek = trim($searchResult->item(0)->nodeValue);
|
|
|
|
// rooms
|
|
$searchResult = $site->query('//dd[@class="is24qa-zimmer grid-item three-fifths"]');
|
|
$zimmer = trim($searchResult->item(0)->nodeValue);
|
|
|
|
// size
|
|
$searchResult = $site->query('//dd[@class="is24qa-wohnflaeche-ca grid-item three-fifths"]');
|
|
$qm = trim($searchResult->item(0)->nodeValue);
|
|
|
|
// location
|
|
$searchResult = $site->query('//div[@class="address-block"]');
|
|
$ort = trim($searchResult->item(0)->nodeValue);
|
|
$ort = str_replace("(zur Karte) ", "", $ort);
|
|
$ort = str_replace("Die vollständige Adresse der Immobilie erhalten Sie vom Anbieter.", "", $ort);
|
|
|
|
// append new array entry
|
|
$data[] = array("id" => $id,
|
|
"date" => date('d.m. H:i'),
|
|
"desc" => $desc,
|
|
"descs" => $descs,
|
|
"bezug" => $bezug,
|
|
"mietew" => $mietew,
|
|
"mietek" => $mietek,
|
|
"ort" => $ort,
|
|
"zimmer" => $zimmer,
|
|
"qm" => $qm,
|
|
"rating" => 0,
|
|
"status" => "NEU",
|
|
"note" => "");
|
|
|
|
// send mail for new item
|
|
$mailcontent = "*" . $desc . "* \r\n\r\n" .
|
|
"Bezug: " . $bezug . "\r\n" .
|
|
"Miete: " . $mietew . "/" . $mietek . "\r\n" .
|
|
"Größe: " . $qm . "\r\n" .
|
|
"Zimmer: " . $zimmer . "\r\n" .
|
|
"Ort: " . $ort . "\r\n" .
|
|
"Link: https://www.immobilienscout24.de/expose/" . $id . "\r\n\r\n" .
|
|
"Übersicht: https://" . $_SERVER["SERVER_NAME"] . $_SERVER["PHP_SELF"];
|
|
mail($config['mail']['to'], "Neues Wohnungsinserat: " . $descs . "...", $mailcontent, "From: " . $config['mail']['from'] . "\r\nMIME-Version: 1.0\r\nContent-Type: text/plain; charset=UTF-8");
|
|
|
|
echo $id . " is new and has been downloaded.<br />\n";
|
|
|
|
} else { // entry is old
|
|
echo $id . " already exists.<br />\n";
|
|
}
|
|
|
|
} // END foreach &searchResult
|
|
} // END for loop through pages
|
|
|
|
|
|
echo "<p><a href='.'>Back to overview</a></p>\n";
|
|
|
|
write_db($db, $data);
|
|
}
|
|
|
|
/////////////////
|
|
/// do = SHOW ///
|
|
/////////////////
|
|
function immo_show($db) {
|
|
global $data;
|
|
global $queryurl;
|
|
read_db($db);
|
|
|
|
$hide = isset($_GET['hide']) ? $_GET['hide'] : "yes";
|
|
?>
|
|
|
|
<!DOCTYPE html>
|
|
<html lang="de-DE">
|
|
<head>
|
|
<title>Immobilienscout Search Helper</title>
|
|
<meta charset="UTF-8" />
|
|
<style type="text/css">
|
|
table {
|
|
border-collapse: collapse;
|
|
width: 100%;
|
|
}
|
|
table, th, td {
|
|
border: 1px solid orange;
|
|
}
|
|
th, td {
|
|
padding: 3px 2px;
|
|
}
|
|
tr:nth-child(even) {
|
|
background-color: #f2f2f2
|
|
}
|
|
tr:hover {background-color: #FFECBA}
|
|
textarea, input, select {
|
|
vertical-align: middle;
|
|
height: 3em;
|
|
}
|
|
input[type="submit"] {
|
|
border: 1px solid #888;
|
|
height: 20px;
|
|
padding: 0;
|
|
width: 2em;
|
|
}
|
|
a.btn {
|
|
background-color: #98b879;
|
|
color: #fff;
|
|
font-weight: 700;
|
|
padding: 10px;
|
|
text-decoration: none;
|
|
text-transform: uppercase;
|
|
}
|
|
#message {
|
|
background-color: #FFE990;
|
|
margin-bottom: 8px;
|
|
padding-left: 20px;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div id="message">
|
|
<?php
|
|
session_start();
|
|
if ( ! empty($_SESSION['message'])) {
|
|
echo $_SESSION['message'];
|
|
$_SESSION['message'] = NULL;
|
|
}
|
|
?>
|
|
</div>
|
|
<table>
|
|
<tr>
|
|
<th>Datum</th>
|
|
<th>Beschreibung</th>
|
|
<th>Status</th>
|
|
<th>Bezug</th>
|
|
<th>Miete warm (kalt)</th>
|
|
<th>Zi</th>
|
|
<th>Größe</th>
|
|
<th>Ort</th>
|
|
<th style="min-width:140px">Notiz</th>
|
|
<th style="min-width:140px">Status ändern</th>
|
|
</tr>
|
|
<?php
|
|
|
|
// Sort for date descending when displaying
|
|
foreach ($data as $key => $row) {
|
|
$date[$key] = $row['date'];
|
|
$id[$key] = $row['id'];
|
|
}
|
|
array_multisort($date, SORT_DESC, $id, SORT_DESC, $data);
|
|
|
|
$total = count($data);
|
|
for ($row = 0; $row < $total; $row++) {
|
|
$id = $data[$row]['id'];
|
|
$date = $data[$row]['date'];
|
|
$desc = $data[$row]['desc'];
|
|
$descs = $data[$row]['descs'];
|
|
$bezug = $data[$row]['bezug'];
|
|
$mietew = $data[$row]['mietew'];
|
|
$mietek = $data[$row]['mietek'];
|
|
$zimmer = $data[$row]['zimmer'];
|
|
$qm = $data[$row]['qm'];
|
|
$ort = $data[$row]['ort'];
|
|
$status = $data[$row]['status'];
|
|
$note = $data[$row]['note'];
|
|
$link = "https://www.immobilienscout24.de/expose/" . $id;
|
|
|
|
if ($status !== "del" || $hide === "no") {
|
|
echo "<tr>";
|
|
echo "<td>" . $date . "</td>";
|
|
echo "<td><span title='" . $desc . "'><em><a target='_blank' href='" . $link . "'>" . $descs . "...</a></em></span></td>";
|
|
echo "<td>" . $status . "</td>";
|
|
echo "<td>" . $bezug . "</td>";
|
|
echo "<td>" . $mietew . " (<em>" . $mietek . "</em>)" . "</td>";
|
|
echo "<td>" . $zimmer . "</td>";
|
|
echo "<td>" . $qm . "</td>";
|
|
echo "<td><a target='_blank' href='https://www.openstreetmap.org/search?query=" . $ort . "'>" . $ort . "</a></td>";
|
|
|
|
echo "<td>";
|
|
?>
|
|
<form action="" method="POST">
|
|
<input name="do" value="update" type="hidden" />
|
|
<input name="id" value="<?php echo $id; ?>" type="hidden" />
|
|
<textarea name="note" rows="1" cols="14"><?php echo $note; ?></textarea>
|
|
<input type="submit" value="OK">
|
|
</form>
|
|
<?php
|
|
echo "</td>";
|
|
|
|
echo "<td>";
|
|
?>
|
|
<form action="" method="POST">
|
|
<input name="do" value="update" type="hidden" />
|
|
<input name="id" value="<?php echo $id; ?>" type="hidden" />
|
|
<select name="status">
|
|
<option value="del">löschen</option>
|
|
<option value="alt">alt</option>
|
|
<option value="NEU">NEU</option>
|
|
<option value="kontaktiert">kontaktiert</option>
|
|
<option value="abgelehnt">abgelehnt</option>
|
|
<option value="termin">termin</option>
|
|
</select>
|
|
<input type="submit" value="OK">
|
|
</form>
|
|
<?php
|
|
echo "</td>";
|
|
|
|
echo "</tr>\n";
|
|
}
|
|
}
|
|
|
|
?>
|
|
</table>
|
|
|
|
<p>Letztes Update: <?php echo date('d.m.Y H:i:s', filemtime($db)); ?></p>
|
|
<p>Gelöschte Inserate <a href="?hide=no">einblenden</a> / <a href=".">ausblenden</a></p>
|
|
<p>Suchlink: <a target="_blank" href="<?php echo $queryurl; ?>">Klick</a></p>
|
|
<p><a class="btn" href="?do=download">Update</a></p>
|
|
</body>
|
|
</html>
|
|
|
|
<?php
|
|
}
|
|
|
|
///////////////////
|
|
/// do = UPDATE ///
|
|
///////////////////
|
|
function immo_update($db) {
|
|
global $data;
|
|
read_db($db);
|
|
|
|
$id = isset($_POST['id']) ? $_POST['id'] : false;
|
|
$status = isset($_POST['status']) ? $_POST['status'] : "NONE";
|
|
$note = isset($_POST['note']) ? $_POST['note'] : "NONE";
|
|
|
|
$key = array_search($id, array_column($data, 'id'));
|
|
|
|
if (strlen($key) === 0) {
|
|
echo $id . " does not exist.<br />";
|
|
echo "<br />";
|
|
echo "<a href='.'>Back to overview</a>\n";
|
|
} else {
|
|
session_start(); // start Sessions
|
|
if ($status != "NONE") {
|
|
$data[$key]['status'] = $status;
|
|
save_return_page("Changed status of " . $id . " to \"". $status . "\".");
|
|
}
|
|
if ($note != "NONE") {
|
|
$data[$key]['note'] = $note;
|
|
save_return_page("Changed note of " . $id . " to \"". $note . "\".");
|
|
}
|
|
}
|
|
}
|
|
|
|
////////////////////////
|
|
/// HELPER FUNCTIONS ///
|
|
////////////////////////
|
|
// load database from file and decode it to array $data
|
|
function read_db($db) {
|
|
global $data; // declare $data a global variable to access it outside this function
|
|
if (! file_exists($db)) {
|
|
touch($db);
|
|
}
|
|
$file = file_get_contents($db, true);
|
|
$data = json_decode($file, true);
|
|
unset($file);
|
|
}
|
|
|
|
// Encode $data array and write database to file
|
|
function write_db($db, $data) {
|
|
// encode and write file
|
|
$encoded = json_encode($data, JSON_PRETTY_PRINT);
|
|
file_put_contents($db, $encoded, LOCK_EX);
|
|
}
|
|
|
|
// load URL and transform it to a XPath-searchable document
|
|
function xsite($url) {
|
|
libxml_use_internal_errors(true); // suppress errors
|
|
$dl = file_get_contents($url);
|
|
$site = new DOMDocument();
|
|
$site->loadHTML($dl);
|
|
$xpathvar = new Domxpath($site);
|
|
return $xpathvar;
|
|
}
|
|
|
|
// save database, put message to session, and load refering page which shows the message
|
|
function save_return_page($output) {
|
|
global $db;
|
|
global $data;
|
|
write_db($db, $data);
|
|
$_SESSION['message'] = "Update: " . $output;
|
|
header('Location: ' . $_SERVER['HTTP_REFERER']);
|
|
exit;
|
|
}
|
|
?>
|