Files
banik_scraper/src/scrapers/scraper_realingo.py
2025-02-21 20:46:50 +01:00

112 lines
6.7 KiB
Python

import json
import logging
from urllib.parse import urljoin
import requests
from disposition import Disposition
from scrapers.rental_offer import RentalOffer
from scrapers.scraper_base import ScraperBase
from scrapers.rental_offer import RentalOffer
import requests
class ScraperRealingo(ScraperBase):
name = "realingo"
logo_url = "https://www.realingo.cz/_next/static/media/images/android-chrome-144x144-cf1233ce.png"
color = 0x00BC78
base_url = "https://www.realingo.cz/graphql"
disposition_mapping = {
Disposition.FLAT_1KK: "FLAT1_KK",
Disposition.FLAT_1: "FLAT11",
Disposition.FLAT_2KK: "FLAT2_KK",
Disposition.FLAT_2: "FLAT21",
Disposition.FLAT_3KK: "FLAT3_KK",
Disposition.FLAT_3: "FLAT31",
Disposition.FLAT_4KK: "FLAT4_KK",
Disposition.FLAT_4: "FLAT41",
Disposition.FLAT_5_UP: ("FLAT5_KK", "FLAT51", "FLAT6_AND_MORE"),
Disposition.FLAT_OTHERS: "OTHERS_FLAT",
}
def build_response(self) -> requests.Response:
json_request = {
"query": "query SearchOffer($purpose: OfferPurpose, $property: PropertyType, $saved: Boolean, $categories: [OfferCategory!], $area: RangeInput, $plotArea: RangeInput, $price: RangeInput, $bounds: GpsBoundsInput, $address: String, $transportType: TransportType, $toleration: Float, $buildingTypes: [BuildingType!], $buildingStatuses: [BuildingStatus!], $buildingPositions: [BuildingPosition!], $houseTypes: [HouseType!], $floor: RangeInput, $ownershipStatuses: [OwnershipStatus!], $furnitureStatuses: [FurnitureStatus!], $maxAge: Int, $contactType: ContactType, $geometry: GeoJSONGeometry, $sort: OfferSort = NEWEST, $first: Int = 20, $skip: Int = 0) {\n addressGeometry(\n address: $address\n geometry: $geometry\n toleration: $toleration\n transportType: $transportType\n ) {\n geometry\n mask\n }\n searchOffer(\n filter: {purpose: $purpose, property: $property, saved: $saved, address: $address, transportType: $transportType, toleration: $toleration, categories: $categories, area: $area, plotArea: $plotArea, price: $price, bounds: $bounds, buildingTypes: $buildingTypes, buildingStatuses: $buildingStatuses, buildingPositions: $buildingPositions, houseTypes: $houseTypes, floor: $floor, ownershipStatuses: $ownershipStatuses, furnitureStatuses: $furnitureStatuses, maxAge: $maxAge, contactType: $contactType, geometry: $geometry}\n sort: $sort\n first: $first\n skip: $skip\n save: true\n ) {\n location {\n id\n type\n url\n name\n neighbours {\n id\n type\n url\n name\n }\n breadcrumbs {\n url\n name\n }\n relatedSearch {\n ...SearchParametersAttributes\n }\n center\n }\n items {\n ...SearchOfferAttributes\n }\n total\n }\n}\n\nfragment FilterAttributes on OfferFilter {\n purpose\n property\n categories\n address\n location {\n name\n }\n toleration\n transportType\n bounds {\n northEast {\n latitude\n longitude\n }\n southWest {\n latitude\n longitude\n }\n }\n saved\n geometry\n area {\n from\n to\n }\n plotArea {\n from\n to\n }\n price {\n from\n to\n }\n buildingTypes\n buildingStatuses\n buildingPositions\n houseTypes\n floor {\n from\n to\n }\n ownershipStatuses\n furnitureStatuses\n maxAge\n contactType\n}\n\nfragment SearchParametersAttributes on SearchParameters {\n filter {\n ...FilterAttributes\n }\n page\n priceMap\n sort\n}\n\nfragment SearchOfferAttributes on Offer {\n id\n url\n purpose\n property\n visited\n liked\n reserved\n createdAt\n category\n purpose\n property\n price {\n total\n canonical\n currency\n }\n area {\n main\n plot\n }\n photos {\n main\n }\n location {\n address\n addressUrl\n locationPrecision\n latitude\n longitude\n }\n}\n",
"operationName": "SearchOffer",
"variables": {
"purpose": "RENT",
"property": "FLAT",
"address": "Brno",
"saved": False,
"categories": self.get_dispositions_data(),
"sort": "NEWEST",
"first": 300,
"skip": 0
}
}
logging.debug("realingo request: %s", json.dumps(json_request))
return requests.post(self.base_url, headers=self.headers, json=json_request)
def category_to_string(self, id) -> str:
return {
"FLAT1_KK": "Byt 1+kk",
"FLAT11": "Byt 1+1",
"FLAT2_KK": "Byt 2+kk",
"FLAT21": "Byt 2+1",
"FLAT3_KK": "Byt 3+kk",
"FLAT31": "Byt 3+1",
"FLAT4_KK": "Byt 4+kk",
"FLAT41": "Byt 4+1",
"FLAT5_KK": "Byt 5+kk",
"FLAT51": "Byt 5+1",
"FLAT6_AND_MORE": "Byt 6+kk a v\u011bt\u0161\xed",
"HOUSE_FAMILY": "Rodinn\xfd dům",
"HOUSE_APARTMENT": "\u010cin\u017eovn\xed",
"HOUSE_MANSION": "Vila",
"LAND_COMMERCIAL": "Komer\u010dn\xed",
"LAND_HOUSING": "Bydlen\xed",
"LAND_GARDEN": "Zahrady",
"LAND_AGRICULTURAL": "Zem\u011bd\u011blsk\xfd",
"LAND_MEADOW": "Louka",
"LAND_FOREST": "Les",
"COMMERCIAL_OFFICE": "Kancel\xe1\u0159",
"COMMERCIAL_STORAGE": "Sklad",
"COMMERCIAL_MANUFACTURING": "V\xfdrobn\xed prostor",
"COMMERCIAL_BUSINESS": "Obchod",
"COMMERCIAL_ACCOMMODATION": "Ubytov\xe1n\xed",
"COMMERCIAL_RESTAURANT": "Restaurace",
"COMMERCIAL_AGRICULTURAL": "Zem\u011bd\u011blsk\xfd objekt",
"OTHERS_HUT": "Chata",
"OTHERS_COTTAGE": "Chalupa",
"OTHERS_GARAGE": "Gar\xe1\u017e",
"OTHERS_FARMHOUSE": "Zem\u011bd\u011blsk\xe1 usedlost",
"OTHERS_POND": "Rybn\xedk",
"OTHERS_FLAT": "Atypick\xfd",
"OTHERS_OTHERS": "Pam\xe1tka",
"OTHERS_MONUMENTS": "Ostatn\xed"
}.get(id, "")
def get_latest_offers(self) -> list[RentalOffer]:
response = self.build_response().json()
items: list[RentalOffer] = []
for offer in response["data"]["searchOffer"]["items"]:
items.append(RentalOffer(
scraper = self,
link = urljoin(self.base_url, offer["url"]),
title = self.category_to_string(offer["category"]) + ", " + str(offer["area"]["main"]) + "",
location = offer["location"]["address"],
price = offer["price"]["total"],
image_url = urljoin(self.base_url, "/static/images/" + (offer["photos"]["main"] or ""))
))
return items