merging the visual query answering with the crawler. Monorepo go!

This commit is contained in:
Kadir 2024-03-01 16:42:48 +01:00
parent 85686a8b24
commit e2f7998ee9
32 changed files with 3449 additions and 0 deletions

47
crawler/GUIDE Normal file
View file

@ -0,0 +1,47 @@
package name: com.rightmove.android
frida --codeshare pcipolloni/universal-android-ssl-pinning-bypass-with-frida -f com.rightmove.android
1. install burp
2. Add listener 8282
3. Export certificate in the DER format
4. convert certificate with command
```
# converts from DER to PEM
openssl x509 -inform DER -in burp.der -out burp.pem
```
5. Copy cert to android with the proper name
```
# According to https://codeshare.frida.re/@pcipolloni/universal-android-ssl-pinning-bypass-with-frida/ the cert path is hardcoded
adb push burp.pem /data/local/tmp/cert-der.crt
```
6. Add the proxy in the android wifi settings
```
# find your own local network ip
ip addr
# Open the wifi you are connected to, edit and add port 8282 (from above) and the ip
```
192.168.0.211/24
1. Install frida server on android
4. run Frida
```
adb shell "/data/local/tmp/frida-server &"
```
5. Check if it runs with
```
frida-ps -U
```
6. pin rightmove
frida -U --codeshare pcipolloni/universal-android-ssl-pinning-bypass-with-frida -f com.rightmove.android

4
crawler/Makefile Normal file
View file

@ -0,0 +1,4 @@
dbremake:
rm sqlite.db
python db.py

19
crawler/TASKS Normal file
View file

@ -0,0 +1,19 @@
- [ ] Update capability of the database
- [ ] Check if the entry already exists in the database
- [ ] Crawl single entry
- [ ] Download pictures and map to database entry
# Distance measuring
- [ ] route api to find shortest path apartments
- [ ] Switch to distance matrix api. Evaluate if its the right one.
# sqm measure
- [ ] OCR to detect the area of the apartment

13
crawler/code/image.py Normal file
View file

@ -0,0 +1,13 @@
import requests
headers = {
'Host': 'media.rightmove.co.uk',
# 'Accept-Encoding': 'gzip, deflate, br',
'User-Agent': 'okhttp/4.10.0',
}
response = requests.get(
'https://media.rightmove.co.uk/47k/46001/138680705/46001_32532509_IMG_00_0000.jpeg',
headers=headers,
verify=False,
)

View file

@ -0,0 +1,305 @@
{
"property": {
"identifier": 138680705,
"updateDate": 1697679094000,
"development": false,
"onlineViewing": false,
"price": 375000.0,
"priceQualifier": "Offers in Excess of",
"shouldShowPrice": true,
"premiumDisplay": false,
"transactionTypeId": 1,
"visible": true,
"bedrooms": 2,
"photoCount": 11,
"address": "Clinger Court, Hobbs Place Estate, N1",
"status": null,
"outcode": "N1",
"summary": "An well presented, bright two bedroom apartment situated on the Fifth floor of this purpose built development. The property measures approximately 642 Sq. ft and has a bright and contemporary interior which comprises of a Large living room with balcony, a modern fully-fitted separate kitchen and...",
"fullDescription": "An well presented, bright two bedroom apartment situated on the Fifth floor of this purpose built development. The property measures approximately 642 Sq. ft and has a bright and contemporary interior which comprises of a Large living room with balcony, a modern fully-fitted separate kitchen and two generously sized double bedrooms and a contemporary finished bathroom.<br /><br />Located in trendy Hoxton and moments from the restaurants, bars and boutique shops of Hoxton Square and the Shoreditch Triangle. Approx. 0.8 miles to Old Street Station (Northern Line & National Rail), 0.6 miles to Hoxton Station (Overground) and 1.3 miles to Liverpool Street Station (Central, Circle, Metropolitan, Hammersmith & City Lines & National Rail).<br /><br />",
"branch": {
"identifier": 46001,
"updateDate": 1697679094000,
"name": "Stoke Newington",
"brandName": "Oakwood",
"branchLogo": "https://media.rightmove.co.uk/47k/46001/branch_logo_46001_0005.png",
"largeBranchLogo": "https://media.rightmove.co.uk/47k/46001/branch_logo_46001_0005.png",
"brandPlusResale": true,
"brandPlusLettings": true,
"address": "48 Stoke Newington Church Street,\r\nLondon,\r\nN16 0NB",
"development": false
},
"telephoneNumber": "020 3835 3657",
"listingUpdateReason": "Reduced on 11/10/2023",
"letFurnishType": null,
"letType": null,
"letDateAvailable": null,
"letBond": null,
"showLettingFeesMessage": false,
"lettingFeesMessage": null,
"floorplanCount": 1,
"showMap": true,
"latitude": 51.535007,
"longitude": -0.082629,
"exactLocationAvailable": true,
"showStreetView": true,
"streetViewLatitude": 51.535015,
"streetViewLongitude": -0.082695,
"streetViewHeading": 149.77,
"streetViewPitch": 17.08,
"streetViewZoom": 1,
"saved": false,
"publicsiteUrl": "https://www.rightmove.co.uk/properties/138680705",
"mobileStreetViewUrl": "https://www.rightmove.co.uk/apps/streetview.html?propertyId=138680705",
"mobilePropertyMapViewUrl": "https://www.rightmove.co.uk/apps/property-mapview.html?propertyId=138680705",
"schoolCheckerUrl": "https://www.rightmove.co.uk/property-for-sale/nearby-schools/property-138680705.html",
"soldPricesUrl": "https://www.rightmove.co.uk/house-prices/n1-5ja.html",
"marketInfoUrl": "https://www.rightmove.co.uk/property-for-sale/market-information/property-138680705.html",
"propertyDisclaimer": "<b>Disclaimer</b> - Property reference 32532509. The information displayed about this property comprises a property advertisement. Rightmove.co.uk makes no warranty as to the accuracy or completeness of the advertisement or any linked or associated information, and Rightmove has no control over the content. This property advertisement does not constitute property particulars. The information is provided and maintained by <b>Oakwood, Stoke Newington</b>.&nbsp;Please contact the selling agent or developer directly to obtain any information which may be available under the terms of The Energy Performance of Buildings (Certificates and Inspections) (England and Wales) Regulations 2007 or the Home Report if in relation to a residential property in Scotland.",
"propertyPhrase": "2 bedroom flat",
"tenureType": "Leasehold",
"buildToRent": false,
"propertySubtype": "Flat",
"contactMethod": "EMAIL",
"misInfo": {
"propertyId": 138680705,
"branchId": 46001,
"offerAdvertStampTypeId": null,
"brandPlus": true,
"featuredProperty": false,
"channel": "BUY",
"premiumDisplay": false,
"premiumDisplayStampId": null,
"countryCode": "GB"
},
"mortgageCalculator": {
"price": 375000,
"propertyTypeAlias": "flats_apartments"
},
"brochure": {
"showBrochureLead": false,
"brochures": [
{
"url": "https://media.rightmove.co.uk/47k/46001/138680705/46001_32532509_DOC_02_0001.pdf",
"caption": "Clinger Court, Hobbs Place Estate, N1"
},
{
"url": "https://www.vebra.com/details/property/32532509",
"caption": "Brochure"
}
]
},
"analyticsInfo": {
"branchId": "46001",
"propertyId": "138680705",
"onlineViewing": "F",
"imageCount": "11",
"floorplanCount": "1",
"beds": "2",
"postcode": "N1 5JA",
"propertyType": "Flats / Apartments",
"propertySubType": "Flat",
"added": "20230815",
"price": "375000",
"tenure": "Leasehold",
"bathrooms": "1",
"sharedOwnership": "F"
},
"displayPrices": [
{
"displayPrice": "£375,000",
"displayPriceQualifier": "Offers in Excess of"
}
],
"stations": [
{
"station": "Hoxton Station",
"distance": 0.3,
"type": "6"
},
{
"station": "Haggerston Station",
"distance": 0.4,
"type": "6"
},
{
"station": "Old Street Station",
"distance": 0.7,
"type": "1,2"
}
],
"features": [],
"photos": [
{
"url": "https://media.rightmove.co.uk/dir/47k/46001/138680705/46001_32532509_IMG_00_0000_max_656x437.jpeg",
"thumbnailUrl": "https://media.rightmove.co.uk/dir/47k/46001/138680705/46001_32532509_IMG_00_0000_max_135x100.jpeg",
"maxSizeUrl": "https://media.rightmove.co.uk/47k/46001/138680705/46001_32532509_IMG_00_0000.jpeg",
"caption": "Clinger Court (1).jpg",
"order": 0
},
{
"url": "https://media.rightmove.co.uk/dir/47k/46001/138680705/46001_32532509_IMG_01_0000_max_656x437.jpeg",
"thumbnailUrl": "https://media.rightmove.co.uk/dir/47k/46001/138680705/46001_32532509_IMG_01_0000_max_135x100.jpeg",
"maxSizeUrl": "https://media.rightmove.co.uk/47k/46001/138680705/46001_32532509_IMG_01_0000.jpeg",
"caption": "Clinger Court (7).jpg",
"order": 1
},
{
"url": "https://media.rightmove.co.uk/dir/47k/46001/138680705/46001_32532509_IMG_02_0000_max_656x437.jpeg",
"thumbnailUrl": "https://media.rightmove.co.uk/dir/47k/46001/138680705/46001_32532509_IMG_02_0000_max_135x100.jpeg",
"maxSizeUrl": "https://media.rightmove.co.uk/47k/46001/138680705/46001_32532509_IMG_02_0000.jpeg",
"caption": "Clinger Court (3).jpg",
"order": 2
},
{
"url": "https://media.rightmove.co.uk/dir/47k/46001/138680705/46001_32532509_IMG_03_0000_max_656x437.jpeg",
"thumbnailUrl": "https://media.rightmove.co.uk/dir/47k/46001/138680705/46001_32532509_IMG_03_0000_max_135x100.jpeg",
"maxSizeUrl": "https://media.rightmove.co.uk/47k/46001/138680705/46001_32532509_IMG_03_0000.jpeg",
"caption": "Clinger Court (5).jpg",
"order": 3
},
{
"url": "https://media.rightmove.co.uk/dir/47k/46001/138680705/46001_32532509_IMG_04_0000_max_656x437.jpeg",
"thumbnailUrl": "https://media.rightmove.co.uk/dir/47k/46001/138680705/46001_32532509_IMG_04_0000_max_135x100.jpeg",
"maxSizeUrl": "https://media.rightmove.co.uk/47k/46001/138680705/46001_32532509_IMG_04_0000.jpeg",
"caption": "Clinger Court (4).jpg",
"order": 4
},
{
"url": "https://media.rightmove.co.uk/dir/47k/46001/138680705/46001_32532509_IMG_05_0000_max_656x437.jpeg",
"thumbnailUrl": "https://media.rightmove.co.uk/dir/47k/46001/138680705/46001_32532509_IMG_05_0000_max_135x100.jpeg",
"maxSizeUrl": "https://media.rightmove.co.uk/47k/46001/138680705/46001_32532509_IMG_05_0000.jpeg",
"caption": "Clinger Court (8).jpg",
"order": 5
},
{
"url": "https://media.rightmove.co.uk/dir/47k/46001/138680705/46001_32532509_IMG_06_0000_max_656x437.jpeg",
"thumbnailUrl": "https://media.rightmove.co.uk/dir/47k/46001/138680705/46001_32532509_IMG_06_0000_max_135x100.jpeg",
"maxSizeUrl": "https://media.rightmove.co.uk/47k/46001/138680705/46001_32532509_IMG_06_0000.jpeg",
"caption": "Clinger Court (9).jpg",
"order": 6
},
{
"url": "https://media.rightmove.co.uk/dir/47k/46001/138680705/46001_32532509_IMG_07_0000_max_656x437.jpeg",
"thumbnailUrl": "https://media.rightmove.co.uk/dir/47k/46001/138680705/46001_32532509_IMG_07_0000_max_135x100.jpeg",
"maxSizeUrl": "https://media.rightmove.co.uk/47k/46001/138680705/46001_32532509_IMG_07_0000.jpeg",
"caption": "Clinger Court (10).jpg",
"order": 7
},
{
"url": "https://media.rightmove.co.uk/dir/47k/46001/138680705/46001_32532509_IMG_08_0000_max_656x437.jpeg",
"thumbnailUrl": "https://media.rightmove.co.uk/dir/47k/46001/138680705/46001_32532509_IMG_08_0000_max_135x100.jpeg",
"maxSizeUrl": "https://media.rightmove.co.uk/47k/46001/138680705/46001_32532509_IMG_08_0000.jpeg",
"caption": "Clinger Court (2).jpg",
"order": 8
},
{
"url": "https://media.rightmove.co.uk/dir/47k/46001/138680705/46001_32532509_IMG_09_0000_max_656x437.jpeg",
"thumbnailUrl": "https://media.rightmove.co.uk/dir/47k/46001/138680705/46001_32532509_IMG_09_0000_max_135x100.jpeg",
"maxSizeUrl": "https://media.rightmove.co.uk/47k/46001/138680705/46001_32532509_IMG_09_0000.jpeg",
"caption": "Clinger Court (6).jpg",
"order": 9
},
{
"url": "https://media.rightmove.co.uk/dir/47k/46001/138680705/46001_32532509_IMG_10_0000_max_656x437.jpeg",
"thumbnailUrl": "https://media.rightmove.co.uk/dir/47k/46001/138680705/46001_32532509_IMG_10_0000_max_135x100.jpeg",
"maxSizeUrl": "https://media.rightmove.co.uk/47k/46001/138680705/46001_32532509_IMG_10_0000.jpeg",
"caption": "Clinger Court (11).jpg",
"order": 10
}
],
"virtualTours": [],
"epcs": [
{
"url": "https://media.rightmove.co.uk/47k/46001/138680705/46001_32532509_EPCGRAPH_00_0000.png",
"caption": "EE Rating",
"order": 0
}
],
"floorplans": [
{
"order": 0,
"url": "https://media.rightmove.co.uk/47k/46001/138680705/46001_32532509_FLP_00_0000.jpeg",
"thumbnailUrl": "https://media.rightmove.co.uk/dir/47k/46001/138680705/46001_32532509_FLP_00_0000_max_296x197.jpeg",
"caption": "floorplan.jpg"
}
],
"note": null,
"affordableBuyingScheme": false,
"lettingsInfo": {
"title": "",
"content": []
},
"propertyDetailsInfo": {
"title": "",
"content": [
{
"type": "propertyType",
"title": "Property type",
"value": "Flat"
},
{
"type": "bedrooms",
"title": "Bedrooms",
"value": "x2"
},
{
"type": "bathrooms",
"title": "Bathrooms",
"value": "x1"
},
{
"type": "tenure",
"title": "Tenure",
"value": "Leasehold"
}
]
},
"tenureInfo": {
"title": "Leasehold",
"content": [
{
"type": "groundRent",
"title": "Ground rent",
"value": "Ask agent"
},
{
"type": "annualServiceCharge",
"title": "Service charge",
"value": "£2,195.76 per year"
},
{
"type": "lengthOfLease",
"title": "Length of lease",
"value": "93 years left"
}
]
},
"sharedOwnershipInfo": {
"title": "",
"content": []
},
"councilTaxInfo": {
"title": "Council tax",
"content": [
{
"type": "councilTaxBand",
"title": "Council tax band",
"value": "B"
}
]
},
"domesticRatesInfo": {
"title": "",
"content": []
},
"linkToGlossary": "https://www.rightmove.co.uk/guides/property-details-glossary/",
"enquiredTimestamp": null,
"stampDutyCalculator": {
"country": "ENGLAND",
"price": 375000,
"buyerType": null,
"result": null
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,32 @@
{
"destination_addresses" :
[
"11 Canal Reach, London N1C 4DB, UK"
],
"origin_addresses" :
[
"1 Carville St, Finsbury Park, London N4 3PE, UK"
],
"rows" :
[
{
"elements" :
[
{
"distance" :
{
"text" : "5.4 km",
"value" : 5411
},
"duration" :
{
"text" : "27 mins",
"value" : 1607
},
"status" : "OK"
}
]
}
],
"status" : "OK"
}

View file

@ -0,0 +1,84 @@
{
"routes": [
{
"legs": [
{
"steps": [
{
"distanceMeters": 6,
"staticDuration": "5s",
"travelMode": "WALK"
},
{
"distanceMeters": 158,
"staticDuration": "133s",
"travelMode": "WALK"
},
{
"distanceMeters": 19,
"staticDuration": "16s",
"travelMode": "WALK"
},
{
"distanceMeters": 102,
"staticDuration": "87s",
"travelMode": "WALK"
},
{
"staticDuration": "30s",
"travelMode": "WALK"
},
{
"distanceMeters": 133,
"staticDuration": "60s",
"travelMode": "WALK"
},
{
"distanceMeters": 5202,
"staticDuration": "392s",
"travelMode": "TRANSIT"
},
{
"distanceMeters": 21,
"staticDuration": "30s",
"travelMode": "WALK"
},
{
"distanceMeters": 5627,
"staticDuration": "600s",
"travelMode": "TRANSIT"
},
{
"distanceMeters": 45,
"staticDuration": "60s",
"travelMode": "WALK"
},
{
"distanceMeters": 10907,
"staticDuration": "1320s",
"travelMode": "TRANSIT"
},
{
"distanceMeters": 63,
"staticDuration": "64s",
"travelMode": "WALK"
},
{
"distanceMeters": 70,
"staticDuration": "54s",
"travelMode": "WALK"
},
{
"distanceMeters": 85,
"staticDuration": "73s",
"travelMode": "WALK"
}
]
}
],
"distanceMeters": 22438,
"duration": "3463s",
"staticDuration": "3463s"
}
]
}

View file

@ -0,0 +1,752 @@
{
"routes": [
{
"legs": [
{
"distanceMeters": 22438,
"duration": "3462s",
"staticDuration": "3462s",
"polyline": {
"encodedPolyline": "q_vyHfrTIFMHQK}AwDw@gDONK_@cB_E?MzBiI@UbIt@rCRpFj@pATpJdCzAM|Ac@nCcAdF_AhEm@dFqAfFeBlFsBtAg@pFuA~KiD`Cm@|Es@jDQzH?bCLtCp@pA`@pAh@dBbA|AfAjAbArBfClLvOfBnCzB`EbCvFjCbHbC|G|Jd]xAhGfCnLrCvZ`@lCPr@xIvYsAvAYn@S~Cl@Td@j@x@vBzCfKDCN{@D}@CgA[{Dc@iDyMuc@a@oBQqAsCwZqDc~AAaCT_BXsBdUauAjBoKf@cBVg@l@m@xDgBrAe@`AO|GMrEc@`Eg@~@FtHfAvBd@~L~EfNbE^?fAk@dDuBrGiF^bBoAc@AK`E{C^o@VuAn@sFfAsKv@uIl@aM^_FJsBN_HG_GCkAMuASeAw@_CcAsDUaB_@kGa@yEQ}EWaEc@eOYuNWgFi@kZ]{NIcLk@y_@CgFS{MH_EKgFUaDF}GRwG`@}Ht@iId@cEfBiKTaBTs@pBiIzA_Fz@mC|AyFrAwG`AkGD}@?kAQ_F@eARiBh@kDPuBr@uMPiBPw@FsADwEAoECYAsGa@wLOwEiAsM]aB]eAcA}Bm@oB_@_CaCaUg@gDa@uB_@kA[o@iAcBq@o@}BcBq@a@q@WeF_Am@Y{@aAo@{@o@kAu@qB_@yAEaADiAL{@Vi@r@cApByB|@{@bAe@`EwAv@MjEsB^MhAo@|Bw@hD}@d@WxKiIp@_Al@qAXiATaCV}CVwAd@yArEsKzAoErAgFpBuI|@uELeAJuBd@_ENoBTiELmE@mEIoGi@qZSiFCiDHuFE{AG_AY_Bg@aBe@kAqCoFWw@OiACmARgDCqAOoAWyAGeAHoKF_BL{@fAqEMMpA}BGCS`Ac@bB][I@EGBuBIO?K"
},
"startLocation": {
"latLng": {
"latitude": 51.5636071,
"longitude": -0.110597
}
},
"endLocation": {
"latLng": {
"latitude": 51.503823499999996,
"longitude": 0.0490617
}
},
"steps": [
{
"distanceMeters": 6,
"staticDuration": "5s",
"polyline": {
"encodedPolyline": "q_vyHfrTIF"
},
"startLocation": {
"latLng": {
"latitude": 51.5636071,
"longitude": -0.110597
}
},
"endLocation": {
"latLng": {
"latitude": 51.563659300000005,
"longitude": -0.1106426
}
},
"navigationInstruction": {
"maneuver": "DEPART",
"instructions": "Head northwest on Pooles Park"
},
"localizedValues": {
"distance": {
"text": "6 m"
},
"staticDuration": {
"text": "1 min"
}
},
"travelMode": "WALK"
},
{
"distanceMeters": 158,
"staticDuration": "133s",
"polyline": {
"encodedPolyline": "{_vyHnrTMHQK}AwDw@gD"
},
"startLocation": {
"latLng": {
"latitude": 51.563659300000005,
"longitude": -0.1106426
}
},
"endLocation": {
"latLng": {
"latitude": 51.564572399999996,
"longitude": -0.10886889999999999
}
},
"navigationInstruction": {
"maneuver": "TURN_SLIGHT_RIGHT",
"instructions": "Slight right onto Biggerstaff St"
},
"localizedValues": {
"distance": {
"text": "0.2 km"
},
"staticDuration": {
"text": "2 mins"
}
},
"travelMode": "WALK"
},
{
"distanceMeters": 19,
"staticDuration": "18s",
"polyline": {
"encodedPolyline": "qevyHlgTON"
},
"startLocation": {
"latLng": {
"latitude": 51.564572399999996,
"longitude": -0.10886889999999999
}
},
"endLocation": {
"latLng": {
"latitude": 51.564651900000008,
"longitude": -0.1089478
}
},
"navigationInstruction": {
"maneuver": "TURN_LEFT",
"instructions": "Turn left onto Fonthill Rd"
},
"localizedValues": {
"distance": {
"text": "19 m"
},
"staticDuration": {
"text": "1 min"
}
},
"travelMode": "WALK"
},
{
"distanceMeters": 102,
"staticDuration": "85s",
"polyline": {
"encodedPolyline": "afvyH|gTK_@cB_E"
},
"startLocation": {
"latLng": {
"latitude": 51.564651900000008,
"longitude": -0.1089478
}
},
"endLocation": {
"latLng": {
"latitude": 51.5652057,
"longitude": -0.1078344
}
},
"navigationInstruction": {
"maneuver": "TURN_RIGHT",
"instructions": "Turn right onto Wells Terrace"
},
"localizedValues": {
"distance": {
"text": "0.1 km"
},
"staticDuration": {
"text": "1 min"
}
},
"travelMode": "WALK"
},
{
"staticDuration": "30s",
"polyline": {
"encodedPolyline": "qivyHn`T"
},
"startLocation": {
"latLng": {
"latitude": 51.565208,
"longitude": -0.107765
}
},
"endLocation": {
"latLng": {
"latitude": 51.565208,
"longitude": -0.107765
}
},
"navigationInstruction": {
"instructions": "Take entrance "
},
"localizedValues": {
"distance": {
"text": "1 m"
},
"staticDuration": {
"text": "1 min"
}
},
"travelMode": "WALK"
},
{
"distanceMeters": 133,
"staticDuration": "60s",
"polyline": {
"encodedPolyline": "qivyHn`TzBiI"
},
"startLocation": {
"latLng": {
"latitude": 51.565208,
"longitude": -0.107765
}
},
"endLocation": {
"latLng": {
"latitude": 51.56459,
"longitude": -0.10610900000000001
}
},
"localizedValues": {
"distance": {
"text": "0.1 km"
},
"staticDuration": {
"text": "1 min"
}
},
"travelMode": "WALK"
},
{
"distanceMeters": 5202,
"staticDuration": "392s",
"polyline": {
"encodedPolyline": "uevyHdvS@UbIt@rCRpFj@pATpJdCzAM|Ac@nCcAdF_AhEm@dFqAfFeBlFsBtAg@pFuA~KiD`Cm@|Es@jDQzH?bCLtCp@pA`@pAh@dBbA|AfAjAbArBfClLvOfBnCzB`EbCvFjCbHbC|G|Jd]xAhGfCnLrCvZ`@lCPr@xIvYsAvA"
},
"startLocation": {
"latLng": {
"latitude": 51.56459,
"longitude": -0.10610900000000001
}
},
"endLocation": {
"latLng": {
"latitude": 51.528693999999994,
"longitude": -0.13204
}
},
"navigationInstruction": {
"instructions": "Subway towards Brixton"
},
"localizedValues": {
"distance": {
"text": "5.2 km"
},
"staticDuration": {
"text": "7 mins"
}
},
"transitDetails": {
"stopDetails": {
"arrivalStop": {
"name": "Euston",
"location": {
"latLng": {
"latitude": 51.528693999999994,
"longitude": -0.13204
}
}
},
"arrivalTime": "2024-03-04T09:20:32Z",
"departureStop": {
"name": "Finsbury Park",
"location": {
"latLng": {
"latitude": 51.56459,
"longitude": -0.10610900000000001
}
}
},
"departureTime": "2024-03-04T09:14:00Z"
},
"localizedValues": {
"arrivalTime": {
"time": {
"text": "9:20AM"
},
"timeZone": "Europe/London"
},
"departureTime": {
"time": {
"text": "9:14AM"
},
"timeZone": "Europe/London"
}
},
"headsign": "Brixton",
"headway": "120s",
"transitLine": {
"agencies": [
{
"name": "Transport for London",
"uri": "https://tfl.gov.uk/modes/tube/"
}
],
"name": "Victoria line",
"uri": "https://tfl.gov.uk/modes/tube/",
"color": "#00a3e0",
"nameShort": "Victoria",
"textColor": "#ffffff",
"vehicle": {
"name": {
"text": "Subway"
},
"type": "SUBWAY",
"iconUri": "//maps.gstatic.com/mapfiles/transit/iw2/6/subway2.png",
"localIconUri": "//maps.gstatic.com/mapfiles/transit/iw2/6/uk-london-underground.png"
}
},
"stopCount": 4
},
"travelMode": "TRANSIT"
},
{
"distanceMeters": 21,
"staticDuration": "30s",
"polyline": {
"encodedPolyline": "ieoyHfxXYn@"
},
"startLocation": {
"latLng": {
"latitude": 51.528693999999994,
"longitude": -0.13204
}
},
"endLocation": {
"latLng": {
"latitude": 51.528819999999996,
"longitude": -0.13227500000000003
}
},
"localizedValues": {
"distance": {
"text": "21 m"
},
"staticDuration": {
"text": "1 min"
}
},
"travelMode": "WALK"
},
{
"distanceMeters": 5627,
"staticDuration": "600s",
"polyline": {
"encodedPolyline": "cfoyHvyXS~Cl@Td@j@x@vBzCfKDCN{@D}@CgA[{Dc@iDyMuc@a@oBQqAsCwZqDc~AAaCT_BXsBdUauAjBoKf@cBVg@l@m@xDgBrAe@`AO|GMrEc@`Eg@~@FtHfAvBd@~L~EfNbE^?fAk@dDuBrGiF^bB"
},
"startLocation": {
"latLng": {
"latitude": 51.528819999999996,
"longitude": -0.13227500000000003
}
},
"endLocation": {
"latLng": {
"latitude": 51.511845,
"longitude": -0.088246899999999989
}
},
"navigationInstruction": {
"instructions": "Subway towards Morden via Bank"
},
"localizedValues": {
"distance": {
"text": "5.6 km"
},
"staticDuration": {
"text": "10 mins"
}
},
"transitDetails": {
"stopDetails": {
"arrivalStop": {
"name": "Bank Station",
"location": {
"latLng": {
"latitude": 51.511845,
"longitude": -0.088246899999999989
}
}
},
"arrivalTime": "2024-03-04T09:35:00Z",
"departureStop": {
"name": "Euston",
"location": {
"latLng": {
"latitude": 51.528819999999996,
"longitude": -0.13227500000000003
}
}
},
"departureTime": "2024-03-04T09:25:00Z"
},
"localizedValues": {
"arrivalTime": {
"time": {
"text": "9:35AM"
},
"timeZone": "Europe/London"
},
"departureTime": {
"time": {
"text": "9:25AM"
},
"timeZone": "Europe/London"
}
},
"headsign": "Morden via Bank",
"headway": "180s",
"transitLine": {
"agencies": [
{
"name": "Transport for London",
"uri": "https://tfl.gov.uk/modes/tube/"
}
],
"name": "Northern Line",
"uri": "https://tfl.gov.uk/modes/tube/",
"color": "#000000",
"nameShort": "Northern",
"textColor": "#ffffff",
"vehicle": {
"name": {
"text": "Subway"
},
"type": "SUBWAY",
"iconUri": "//maps.gstatic.com/mapfiles/transit/iw2/6/subway2.png",
"localIconUri": "//maps.gstatic.com/mapfiles/transit/iw2/6/uk-london-underground.png"
}
},
"stopCount": 6
},
"travelMode": "TRANSIT"
},
{
"distanceMeters": 45,
"staticDuration": "60s",
"polyline": {
"encodedPolyline": "_|kyHpfPoAc@"
},
"startLocation": {
"latLng": {
"latitude": 51.511845,
"longitude": -0.088246899999999989
}
},
"endLocation": {
"latLng": {
"latitude": 51.512236699999995,
"longitude": -0.0880733
}
},
"localizedValues": {
"distance": {
"text": "45 m"
},
"staticDuration": {
"text": "1 min"
}
},
"travelMode": "WALK"
},
{
"distanceMeters": 10907,
"staticDuration": "1320s",
"polyline": {
"encodedPolyline": "o~kyHlePAK`E{C^o@VuAn@sFfAsKv@uIl@aM^_FJsBN_HG_GCkAMuASeAw@_CcAsDUaB_@kGa@yEQ}EWaEc@eOYuNWgFi@kZ]{NIcLk@y_@CgFS{MH_EKgFUaDF}GRwG`@}Ht@iId@cEfBiKTaBTs@pBiIzA_Fz@mC|AyFrAwG`AkGD}@?kAQ_F@eARiBh@kDPuBr@uMPiBPw@FsADwEAoECYAsGa@wLOwEiAsM]aB]eAcA}Bm@oB_@_CaCaUg@gDa@uB_@kA[o@iAcBq@o@}BcBq@a@q@WeF_Am@Y{@aAo@{@o@kAu@qB_@yAEaADiAL{@Vi@r@cApByB|@{@bAe@`EwAv@MjEsB^MhAo@|Bw@hD}@d@WxKiIp@_Al@qAXiATaCV}CVwAd@yArEsKzAoErAgFpBuI|@uELeAJuBd@_ENoBTiELmE@mEIoGi@qZSiFCiDHuFE{AG_AY_Bg@aBe@kAqCoFWw@OiACmARgDCqAOoAWyAGeAHoKF_BL{@fAqEMM"
},
"startLocation": {
"latLng": {
"latitude": 51.512236699999995,
"longitude": -0.0880733
}
},
"endLocation": {
"latLng": {
"latitude": 51.503653,
"longitude": 0.0483353
}
},
"navigationInstruction": {
"instructions": "Light rail towards Woolwich Arsenal"
},
"localizedValues": {
"distance": {
"text": "10.9 km"
},
"staticDuration": {
"text": "22 mins"
}
},
"transitDetails": {
"stopDetails": {
"arrivalStop": {
"name": "London City Airport",
"location": {
"latLng": {
"latitude": 51.503653,
"longitude": 0.0483353
}
}
},
"arrivalTime": "2024-03-04T10:03:00Z",
"departureStop": {
"name": "Bank Station",
"location": {
"latLng": {
"latitude": 51.512236699999995,
"longitude": -0.0880733
}
}
},
"departureTime": "2024-03-04T09:41:00Z"
},
"localizedValues": {
"arrivalTime": {
"time": {
"text": "10:03AM"
},
"timeZone": "Europe/London"
},
"departureTime": {
"time": {
"text": "9:41AM"
},
"timeZone": "Europe/London"
}
},
"headsign": "Woolwich Arsenal",
"transitLine": {
"agencies": [
{
"name": "Transport for London",
"uri": "https://tfl.gov.uk/modes/tube/"
}
],
"uri": "https://tfl.gov.uk/modes/dlr/",
"color": "#00afad",
"nameShort": "DLR",
"textColor": "#ffffff",
"vehicle": {
"name": {
"text": "Light rail"
},
"type": "TRAM",
"iconUri": "//maps.gstatic.com/mapfiles/transit/iw2/6/tram2.png",
"localIconUri": "//maps.gstatic.com/mapfiles/transit/iw2/6/uk-london-dlr.png"
}
},
"stopCount": 11
},
"travelMode": "TRANSIT"
},
{
"distanceMeters": 63,
"staticDuration": "64s",
"polyline": {
"encodedPolyline": "yhjyHcmHpA}B"
},
"startLocation": {
"latLng": {
"latitude": 51.503653,
"longitude": 0.0483353
}
},
"endLocation": {
"latLng": {
"latitude": 51.5032434,
"longitude": 0.048965499999999995
}
},
"navigationInstruction": {
"instructions": "Take exit "
},
"localizedValues": {
"distance": {
"text": "63 m"
},
"staticDuration": {
"text": "1 min"
}
},
"travelMode": "WALK"
},
{
"distanceMeters": 70,
"staticDuration": "54s",
"polyline": {
"encodedPolyline": "ofjyHeqHS`Ac@bB"
},
"startLocation": {
"latLng": {
"latitude": 51.5032794,
"longitude": 0.0489907
}
},
"endLocation": {
"latLng": {
"latitude": 51.503564399999995,
"longitude": 0.0481594
}
},
"navigationInstruction": {
"maneuver": "DEPART",
"instructions": "Head northwest on Hartmann Rd"
},
"localizedValues": {
"distance": {
"text": "70 m"
},
"staticDuration": {
"text": "1 min"
}
},
"travelMode": "WALK"
},
{
"distanceMeters": 85,
"staticDuration": "73s",
"polyline": {
"encodedPolyline": "ghjyH_lH][I@EGBuBIO?K"
},
"startLocation": {
"latLng": {
"latitude": 51.503564399999995,
"longitude": 0.0481594
}
},
"endLocation": {
"latLng": {
"latitude": 51.503823499999996,
"longitude": 0.0490617
}
},
"navigationInstruction": {
"maneuver": "TURN_RIGHT",
"instructions": "Turn right\nPartial restricted usage road"
},
"localizedValues": {
"distance": {
"text": "85 m"
},
"staticDuration": {
"text": "1 min"
}
},
"travelMode": "WALK"
}
],
"localizedValues": {
"distance": {
"text": "22.4 km"
},
"duration": {
"text": "58 mins"
},
"staticDuration": {
"text": "58 mins"
}
},
"stepsOverview": {
"multiModalSegments": [
{
"stepStartIndex": 0,
"stepEndIndex": 5,
"navigationInstruction": {
"instructions": "Walk to Finsbury Park"
},
"travelMode": "WALK"
},
{
"stepStartIndex": 6,
"stepEndIndex": 6,
"navigationInstruction": {
"instructions": "Subway towards Brixton"
},
"travelMode": "TRANSIT"
},
{
"stepStartIndex": 7,
"stepEndIndex": 7,
"navigationInstruction": {
"instructions": "Walk to Euston"
},
"travelMode": "WALK"
},
{
"stepStartIndex": 8,
"stepEndIndex": 8,
"navigationInstruction": {
"instructions": "Subway towards Morden via Bank"
},
"travelMode": "TRANSIT"
},
{
"stepStartIndex": 9,
"stepEndIndex": 9,
"navigationInstruction": {
"instructions": "Walk to Bank Station"
},
"travelMode": "WALK"
},
{
"stepStartIndex": 10,
"stepEndIndex": 10,
"navigationInstruction": {
"instructions": "Light rail towards Woolwich Arsenal"
},
"travelMode": "TRANSIT"
},
{
"stepStartIndex": 11,
"stepEndIndex": 13,
"travelMode": "WALK"
}
]
}
}
],
"distanceMeters": 22438,
"duration": "3463s",
"staticDuration": "3463s",
"polyline": {
"encodedPolyline": "q_vyHfrTIFMHQK}AwDw@gDONK_@cB_E?MzBiI@UbIt@rCRpFj@pATpJdCzAM|Ac@nCcAdF_AhEm@dFqAfFeBlFsBtAg@pFuA~KiD`Cm@|Es@jDQzH?bCLtCp@pA`@pAh@dBbA|AfAjAbArBfClLvOfBnCzB`EbCvFjCbHbC|G|Jd]xAhGfCnLrCvZ`@lCPr@xIvYsAvAYn@S~Cl@Td@j@x@vBzCfKDCN{@D}@CgA[{Dc@iDyMuc@a@oBQqAsCwZqDc~AAaCT_BXsBdUauAjBoKf@cBVg@l@m@xDgBrAe@`AO|GMrEc@`Eg@~@FtHfAvBd@~L~EfNbE^?fAk@dDuBrGiF^bBoAc@AK`E{C^o@VuAn@sFfAsKv@uIl@aM^_FJsBN_HG_GCkAMuASeAw@_CcAsDUaB_@kGa@yEQ}EWaEc@eOYuNWgFi@kZ]{NIcLk@y_@CgFS{MH_EKgFUaDF}GRwG`@}Ht@iId@cEfBiKTaBTs@pBiIzA_Fz@mC|AyFrAwG`AkGD}@?kAQ_F@eARiBh@kDPuBr@uMPiBPw@FsADwEAoECYAsGa@wLOwEiAsM]aB]eAcA}Bm@oB_@_CaCaUg@gDa@uB_@kA[o@iAcBq@o@}BcBq@a@q@WeF_Am@Y{@aAo@{@o@kAu@qB_@yAEaADiAL{@Vi@r@cApByB|@{@bAe@`EwAv@MjEsB^MhAo@|Bw@hD}@d@WxKiIp@_Al@qAXiATaCV}CVwAd@yArEsKzAoErAgFpBuI|@uELeAJuBd@_ENoBTiELmE@mEIoGi@qZSiFCiDHuFE{AG_AY_Bg@aBe@kAqCoFWw@OiACmARgDCqAOoAWyAGeAHoKF_BL{@fAqEMMpA}BGCS`Ac@bB][I@EGBuBIO?K"
},
"viewport": {
"low": {
"latitude": 51.502068799999996,
"longitude": -0.1359722
},
"high": {
"latitude": 51.565208,
"longitude": 0.0490617
}
},
"travelAdvisory": {
"transitFare": {
"currencyCode": "GBP",
"units": "3",
"nanos": 700000000
}
},
"localizedValues": {
"distance": {
"text": "22.4 km"
},
"duration": {
"text": "58 mins"
},
"staticDuration": {
"text": "58 mins"
},
"transitFare": {
"text": "£3.70"
}
},
"routeLabels": [
"DEFAULT_ROUTE"
]
}
]
}

File diff suppressed because it is too large Load diff

57
crawler/code/listings.py Normal file
View file

@ -0,0 +1,57 @@
import requests
headers = {
'Host': 'api.rightmove.co.uk',
# 'Accept-Encoding': 'gzip, deflate, br',
'User-Agent': 'okhttp/4.10.0',
'Connection': 'close',
}
params = {
'locationIdentifier': 'POSTCODE^4228216',
'channel': 'BUY',
'page': '1',
'numberOfPropertiesPerPage': '25',
'radius': '3.0',
'sortBy': 'distance',
'includeUnavailableProperties': 'false',
'propertyTypes': 'flat',
'dontShow': 'sharedOwnership,retirement',
'minPrice': '150000',
'maxPrice': '500000',
'minBedrooms': '2',
'maxBedrooms': '2',
'apiApplication': 'ANDROID',
'appVersion': '3.70.0',
}
response = requests.get('https://api.rightmove.co.uk/api/property-listing', params=params, headers=headers, verify=False)
import requests
headers = {
'Host': 'api.rightmove.co.uk',
# 'Accept-Encoding': 'gzip, deflate, br',
'User-Agent': 'okhttp/4.10.0',
'Connection': 'close',
}
params = {
'locationIdentifier': 'POSTCODE^4228216',
'channel': 'BUY',
'page': '2',
'numberOfPropertiesPerPage': '25',
'radius': '3.0',
'sortBy': 'distance',
'includeUnavailableProperties': 'false',
'propertyTypes': 'flat',
'dontShow': 'sharedOwnership,retirement',
'minPrice': '150000',
'maxPrice': '500000',
'minBedrooms': '2',
'maxBedrooms': '2',
'apiApplication': 'ANDROID',
'appVersion': '3.70.0',
}
response = requests.get('https://api.rightmove.co.uk/api/property-listing', params=params, headers=headers, verify=False)

View file

@ -0,0 +1,23 @@
import requests
API_KEY = 'AIzaSyBoBHzeQFgR7O-NlNsuHXQcC1B7ccEHpl8'
url = "https://maps.googleapis.com/maps/api/distancematrix/json"
origin = '51.5636306598907,-0.11061106079085892'
dest = "51.53836609846008,-0.12743940233824352"
params = {
"origins": origin,
"destinations": dest,
"key": API_KEY,
"departure_time": "", # timstamp, optional
"mode": "transit",
}
r = requests.get(url, params=params)
print(r.status_code)
print(r.json())
with open('code/json/routing_distancematrix.json', 'w') as f:
f.write(r.text)

View file

@ -0,0 +1,90 @@
import requests
from utils import nextMonday
from collections import defaultdict
API_KEY = 'AIzaSyBoBHzeQFgR7O-NlNsuHXQcC1B7ccEHpl8'
url = "https://routes.googleapis.com/directions/v2:computeRoutes"
def travel_time(origin_lat:float, origin_lon:float, dest_lat:float, dest_lon:float):
monday9am = nextMonday()
header = {
"X-Goog-Api-Key": API_KEY,
"Content-Type": "application/json",
"X-Goog-FieldMask": "routes.distanceMeters,routes.duration,routes.staticDuration,routes.legs.steps.distanceMeters,routes.legs.steps.staticDuration,routes.legs.steps.travelMode",
}
body = {
"origin":{
"location":{
"latLng":{
"latitude": origin_lat,
"longitude": origin_lon
}
}
},
"destination":{
"location":{
"latLng":{
"latitude": dest_lat,
"longitude": dest_lon
}
}
},
"travelMode": "TRANSIT",
# "2023-10-15T15:01:23.045123456Z"
"departureTime": monday9am.strftime("%Y-%m-%dT%H:%M:%S.%fZ"),
"computeAlternativeRoutes": False,
# "routeModifiers": {
# "avoidTolls": false,
# "avoidHighways": false,
# "avoidFerries": false
# },
"languageCode": "en-US",
"units": "METRIC"
}
r = requests.post(url, json=body, headers=header)
if r.status_code == 200:
return r.json()
raise Exception(r.json())
def extract_time(d):
r = d['routes'][0]
print(r.keys())
distance = r['distanceMeters']
duration = r['duration']
duration_static = r['staticDuration']
steps = r['legs'][0]['steps']
# print(steps)
duration_per_transit = defaultdict(lambda: 0)
distance_per_transit = defaultdict(lambda: 0)
for step in steps:
duration_per_transit[step['travelMode']] += int(step['staticDuration'].strip('s'))
distance_per_transit[step['travelMode']] += step.get('distanceMeters', 0)
print(f"dis {distance}, dur {duration}, duration per transit {dict(duration_per_transit)}, distance per transit {dict(distance_per_transit)}")
if __name__ == "__main__":
import json
with open('code/json/routing_routeapi.json', 'r') as f:
d = json.load(f)
extract_time(d)
# if __name__ == "__main__":
# origin = 51.5635664310333, -0.1107173751570373 # home
# dest = 51.50475678313417, 0.04915321000190009 # london city airport
# d = travel_time(origin[0], origin[1], dest[0], dest[1])
# import json
# with open('code/json/routing_routeapi.json', 'w') as f:
# json.dump(d, f)

View file

@ -0,0 +1,15 @@
import requests
headers = {
'Host': 'api.rightmove.co.uk',
# 'Accept-Encoding': 'gzip, deflate, br',
'User-Agent': 'okhttp/4.10.0',
'Connection': 'close',
}
params = {
'apiApplication': 'ANDROID',
'appVersion': '3.70.0',
}
response = requests.get('https://api.rightmove.co.uk/api/property/119578451', params=params, headers=headers, verify=False)

17
crawler/code/utils.py Normal file
View file

@ -0,0 +1,17 @@
from datetime import datetime, timedelta, timezone
def nextMonday():
"""
I think this function doesnt work when the day is monday itself.
Returns:
_type_: _description_
"""
now = datetime.now(timezone.utc)
days_until_monday = (0 - now.weekday() + 7) % 7
monday = now + timedelta(days=days_until_monday)
monday_9am = monday.replace(hour=9, minute=0, second=0, microsecond=0, tzinfo=timezone.utc)
return monday_9am
if __name__ == '__main__':
print(nextMonday())

354
crawler/poetry.lock generated Normal file
View file

@ -0,0 +1,354 @@
# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand.
[[package]]
name = "cachetools"
version = "5.3.2"
description = "Extensible memoizing collections and decorators"
optional = false
python-versions = ">=3.7"
files = [
{file = "cachetools-5.3.2-py3-none-any.whl", hash = "sha256:861f35a13a451f94e301ce2bec7cac63e881232ccce7ed67fab9b5df4d3beaa1"},
{file = "cachetools-5.3.2.tar.gz", hash = "sha256:086ee420196f7b2ab9ca2db2520aca326318b68fe5ba8bc4d49cca91add450f2"},
]
[[package]]
name = "certifi"
version = "2023.11.17"
description = "Python package for providing Mozilla's CA Bundle."
optional = false
python-versions = ">=3.6"
files = [
{file = "certifi-2023.11.17-py3-none-any.whl", hash = "sha256:e036ab49d5b79556f99cfc2d9320b34cfbe5be05c5871b51de9329f0603b0474"},
{file = "certifi-2023.11.17.tar.gz", hash = "sha256:9b469f3a900bf28dc19b8cfbf8019bf47f7fdd1a65a1d4ffb98fc14166beb4d1"},
]
[[package]]
name = "charset-normalizer"
version = "3.3.2"
description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
optional = false
python-versions = ">=3.7.0"
files = [
{file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"},
{file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3"},
{file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027"},
{file = "charset_normalizer-3.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03"},
{file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d"},
{file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e"},
{file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6"},
{file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5"},
{file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537"},
{file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c"},
{file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12"},
{file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f"},
{file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269"},
{file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519"},
{file = "charset_normalizer-3.3.2-cp310-cp310-win32.whl", hash = "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73"},
{file = "charset_normalizer-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09"},
{file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db"},
{file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96"},
{file = "charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e"},
{file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f"},
{file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574"},
{file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4"},
{file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8"},
{file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc"},
{file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae"},
{file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887"},
{file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae"},
{file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce"},
{file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f"},
{file = "charset_normalizer-3.3.2-cp311-cp311-win32.whl", hash = "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab"},
{file = "charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77"},
{file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8"},
{file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b"},
{file = "charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6"},
{file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a"},
{file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389"},
{file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa"},
{file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b"},
{file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed"},
{file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26"},
{file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d"},
{file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068"},
{file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143"},
{file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4"},
{file = "charset_normalizer-3.3.2-cp312-cp312-win32.whl", hash = "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7"},
{file = "charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001"},
{file = "charset_normalizer-3.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c"},
{file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5"},
{file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985"},
{file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6"},
{file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714"},
{file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786"},
{file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5"},
{file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c"},
{file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8"},
{file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711"},
{file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811"},
{file = "charset_normalizer-3.3.2-cp37-cp37m-win32.whl", hash = "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4"},
{file = "charset_normalizer-3.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99"},
{file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a"},
{file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac"},
{file = "charset_normalizer-3.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a"},
{file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33"},
{file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238"},
{file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a"},
{file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2"},
{file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8"},
{file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898"},
{file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99"},
{file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d"},
{file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04"},
{file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087"},
{file = "charset_normalizer-3.3.2-cp38-cp38-win32.whl", hash = "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25"},
{file = "charset_normalizer-3.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b"},
{file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4"},
{file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d"},
{file = "charset_normalizer-3.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0"},
{file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269"},
{file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c"},
{file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519"},
{file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796"},
{file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185"},
{file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c"},
{file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458"},
{file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2"},
{file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8"},
{file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"},
{file = "charset_normalizer-3.3.2-cp39-cp39-win32.whl", hash = "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f"},
{file = "charset_normalizer-3.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d"},
{file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"},
]
[[package]]
name = "diskcache"
version = "5.6.3"
description = "Disk Cache -- Disk and file backed persistent cache."
optional = false
python-versions = ">=3"
files = [
{file = "diskcache-5.6.3-py3-none-any.whl", hash = "sha256:5e31b2d5fbad117cc363ebaf6b689474db18a1f6438bc82358b024abd4c2ca19"},
{file = "diskcache-5.6.3.tar.gz", hash = "sha256:2c3a3fa2743d8535d832ec61c2054a1641f41775aa7c556758a109941e33e4fc"},
]
[[package]]
name = "greenlet"
version = "3.0.1"
description = "Lightweight in-process concurrent programming"
optional = false
python-versions = ">=3.7"
files = [
{file = "greenlet-3.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f89e21afe925fcfa655965ca8ea10f24773a1791400989ff32f467badfe4a064"},
{file = "greenlet-3.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28e89e232c7593d33cac35425b58950789962011cc274aa43ef8865f2e11f46d"},
{file = "greenlet-3.0.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b8ba29306c5de7717b5761b9ea74f9c72b9e2b834e24aa984da99cbfc70157fd"},
{file = "greenlet-3.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:19bbdf1cce0346ef7341705d71e2ecf6f41a35c311137f29b8a2dc2341374565"},
{file = "greenlet-3.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:599daf06ea59bfedbec564b1692b0166a0045f32b6f0933b0dd4df59a854caf2"},
{file = "greenlet-3.0.1-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b641161c302efbb860ae6b081f406839a8b7d5573f20a455539823802c655f63"},
{file = "greenlet-3.0.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d57e20ba591727da0c230ab2c3f200ac9d6d333860d85348816e1dca4cc4792e"},
{file = "greenlet-3.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:5805e71e5b570d490938d55552f5a9e10f477c19400c38bf1d5190d760691846"},
{file = "greenlet-3.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:52e93b28db27ae7d208748f45d2db8a7b6a380e0d703f099c949d0f0d80b70e9"},
{file = "greenlet-3.0.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f7bfb769f7efa0eefcd039dd19d843a4fbfbac52f1878b1da2ed5793ec9b1a65"},
{file = "greenlet-3.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:91e6c7db42638dc45cf2e13c73be16bf83179f7859b07cfc139518941320be96"},
{file = "greenlet-3.0.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1757936efea16e3f03db20efd0cd50a1c86b06734f9f7338a90c4ba85ec2ad5a"},
{file = "greenlet-3.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:19075157a10055759066854a973b3d1325d964d498a805bb68a1f9af4aaef8ec"},
{file = "greenlet-3.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e9d21aaa84557d64209af04ff48e0ad5e28c5cca67ce43444e939579d085da72"},
{file = "greenlet-3.0.1-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2847e5d7beedb8d614186962c3d774d40d3374d580d2cbdab7f184580a39d234"},
{file = "greenlet-3.0.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:97e7ac860d64e2dcba5c5944cfc8fa9ea185cd84061c623536154d5a89237884"},
{file = "greenlet-3.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:b2c02d2ad98116e914d4f3155ffc905fd0c025d901ead3f6ed07385e19122c94"},
{file = "greenlet-3.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:22f79120a24aeeae2b4471c711dcf4f8c736a2bb2fabad2a67ac9a55ea72523c"},
{file = "greenlet-3.0.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:100f78a29707ca1525ea47388cec8a049405147719f47ebf3895e7509c6446aa"},
{file = "greenlet-3.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:60d5772e8195f4e9ebf74046a9121bbb90090f6550f81d8956a05387ba139353"},
{file = "greenlet-3.0.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:daa7197b43c707462f06d2c693ffdbb5991cbb8b80b5b984007de431493a319c"},
{file = "greenlet-3.0.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ea6b8aa9e08eea388c5f7a276fabb1d4b6b9d6e4ceb12cc477c3d352001768a9"},
{file = "greenlet-3.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d11ebbd679e927593978aa44c10fc2092bc454b7d13fdc958d3e9d508aba7d0"},
{file = "greenlet-3.0.1-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:dbd4c177afb8a8d9ba348d925b0b67246147af806f0b104af4d24f144d461cd5"},
{file = "greenlet-3.0.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:20107edf7c2c3644c67c12205dc60b1bb11d26b2610b276f97d666110d1b511d"},
{file = "greenlet-3.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8bef097455dea90ffe855286926ae02d8faa335ed8e4067326257cb571fc1445"},
{file = "greenlet-3.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:b2d3337dcfaa99698aa2377c81c9ca72fcd89c07e7eb62ece3f23a3fe89b2ce4"},
{file = "greenlet-3.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:80ac992f25d10aaebe1ee15df45ca0d7571d0f70b645c08ec68733fb7a020206"},
{file = "greenlet-3.0.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:337322096d92808f76ad26061a8f5fccb22b0809bea39212cd6c406f6a7060d2"},
{file = "greenlet-3.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b9934adbd0f6e476f0ecff3c94626529f344f57b38c9a541f87098710b18af0a"},
{file = "greenlet-3.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc4d815b794fd8868c4d67602692c21bf5293a75e4b607bb92a11e821e2b859a"},
{file = "greenlet-3.0.1-cp37-cp37m-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:41bdeeb552d814bcd7fb52172b304898a35818107cc8778b5101423c9017b3de"},
{file = "greenlet-3.0.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:6e6061bf1e9565c29002e3c601cf68569c450be7fc3f7336671af7ddb4657166"},
{file = "greenlet-3.0.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:fa24255ae3c0ab67e613556375a4341af04a084bd58764731972bcbc8baeba36"},
{file = "greenlet-3.0.1-cp37-cp37m-win32.whl", hash = "sha256:b489c36d1327868d207002391f662a1d163bdc8daf10ab2e5f6e41b9b96de3b1"},
{file = "greenlet-3.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:f33f3258aae89da191c6ebaa3bc517c6c4cbc9b9f689e5d8452f7aedbb913fa8"},
{file = "greenlet-3.0.1-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:d2905ce1df400360463c772b55d8e2518d0e488a87cdea13dd2c71dcb2a1fa16"},
{file = "greenlet-3.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a02d259510b3630f330c86557331a3b0e0c79dac3d166e449a39363beaae174"},
{file = "greenlet-3.0.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:55d62807f1c5a1682075c62436702aaba941daa316e9161e4b6ccebbbf38bda3"},
{file = "greenlet-3.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3fcc780ae8edbb1d050d920ab44790201f027d59fdbd21362340a85c79066a74"},
{file = "greenlet-3.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4eddd98afc726f8aee1948858aed9e6feeb1758889dfd869072d4465973f6bfd"},
{file = "greenlet-3.0.1-cp38-cp38-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:eabe7090db68c981fca689299c2d116400b553f4b713266b130cfc9e2aa9c5a9"},
{file = "greenlet-3.0.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f2f6d303f3dee132b322a14cd8765287b8f86cdc10d2cb6a6fae234ea488888e"},
{file = "greenlet-3.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d923ff276f1c1f9680d32832f8d6c040fe9306cbfb5d161b0911e9634be9ef0a"},
{file = "greenlet-3.0.1-cp38-cp38-win32.whl", hash = "sha256:0b6f9f8ca7093fd4433472fd99b5650f8a26dcd8ba410e14094c1e44cd3ceddd"},
{file = "greenlet-3.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:990066bff27c4fcf3b69382b86f4c99b3652bab2a7e685d968cd4d0cfc6f67c6"},
{file = "greenlet-3.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:ce85c43ae54845272f6f9cd8320d034d7a946e9773c693b27d620edec825e376"},
{file = "greenlet-3.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:89ee2e967bd7ff85d84a2de09df10e021c9b38c7d91dead95b406ed6350c6997"},
{file = "greenlet-3.0.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:87c8ceb0cf8a5a51b8008b643844b7f4a8264a2c13fcbcd8a8316161725383fe"},
{file = "greenlet-3.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d6a8c9d4f8692917a3dc7eb25a6fb337bff86909febe2f793ec1928cd97bedfc"},
{file = "greenlet-3.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fbc5b8f3dfe24784cee8ce0be3da2d8a79e46a276593db6868382d9c50d97b1"},
{file = "greenlet-3.0.1-cp39-cp39-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:85d2b77e7c9382f004b41d9c72c85537fac834fb141b0296942d52bf03fe4a3d"},
{file = "greenlet-3.0.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:696d8e7d82398e810f2b3622b24e87906763b6ebfd90e361e88eb85b0e554dc8"},
{file = "greenlet-3.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:329c5a2e5a0ee942f2992c5e3ff40be03e75f745f48847f118a3cfece7a28546"},
{file = "greenlet-3.0.1-cp39-cp39-win32.whl", hash = "sha256:cf868e08690cb89360eebc73ba4be7fb461cfbc6168dd88e2fbbe6f31812cd57"},
{file = "greenlet-3.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:ac4a39d1abae48184d420aa8e5e63efd1b75c8444dd95daa3e03f6c6310e9619"},
{file = "greenlet-3.0.1.tar.gz", hash = "sha256:816bd9488a94cba78d93e1abb58000e8266fa9cc2aa9ccdd6eb0696acb24005b"},
]
[package.extras]
docs = ["Sphinx"]
test = ["objgraph", "psutil"]
[[package]]
name = "idna"
version = "3.4"
description = "Internationalized Domain Names in Applications (IDNA)"
optional = false
python-versions = ">=3.5"
files = [
{file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"},
{file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"},
]
[[package]]
name = "requests"
version = "2.31.0"
description = "Python HTTP for Humans."
optional = false
python-versions = ">=3.7"
files = [
{file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"},
{file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"},
]
[package.dependencies]
certifi = ">=2017.4.17"
charset-normalizer = ">=2,<4"
idna = ">=2.5,<4"
urllib3 = ">=1.21.1,<3"
[package.extras]
socks = ["PySocks (>=1.5.6,!=1.5.7)"]
use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
[[package]]
name = "sqlalchemy"
version = "2.0.23"
description = "Database Abstraction Library"
optional = false
python-versions = ">=3.7"
files = [
{file = "SQLAlchemy-2.0.23-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:638c2c0b6b4661a4fd264f6fb804eccd392745c5887f9317feb64bb7cb03b3ea"},
{file = "SQLAlchemy-2.0.23-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e3b5036aa326dc2df50cba3c958e29b291a80f604b1afa4c8ce73e78e1c9f01d"},
{file = "SQLAlchemy-2.0.23-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:787af80107fb691934a01889ca8f82a44adedbf5ef3d6ad7d0f0b9ac557e0c34"},
{file = "SQLAlchemy-2.0.23-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c14eba45983d2f48f7546bb32b47937ee2cafae353646295f0e99f35b14286ab"},
{file = "SQLAlchemy-2.0.23-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0666031df46b9badba9bed00092a1ffa3aa063a5e68fa244acd9f08070e936d3"},
{file = "SQLAlchemy-2.0.23-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:89a01238fcb9a8af118eaad3ffcc5dedaacbd429dc6fdc43fe430d3a941ff965"},
{file = "SQLAlchemy-2.0.23-cp310-cp310-win32.whl", hash = "sha256:cabafc7837b6cec61c0e1e5c6d14ef250b675fa9c3060ed8a7e38653bd732ff8"},
{file = "SQLAlchemy-2.0.23-cp310-cp310-win_amd64.whl", hash = "sha256:87a3d6b53c39cd173990de2f5f4b83431d534a74f0e2f88bd16eabb5667e65c6"},
{file = "SQLAlchemy-2.0.23-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d5578e6863eeb998980c212a39106ea139bdc0b3f73291b96e27c929c90cd8e1"},
{file = "SQLAlchemy-2.0.23-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:62d9e964870ea5ade4bc870ac4004c456efe75fb50404c03c5fd61f8bc669a72"},
{file = "SQLAlchemy-2.0.23-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c80c38bd2ea35b97cbf7c21aeb129dcbebbf344ee01a7141016ab7b851464f8e"},
{file = "SQLAlchemy-2.0.23-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75eefe09e98043cff2fb8af9796e20747ae870c903dc61d41b0c2e55128f958d"},
{file = "SQLAlchemy-2.0.23-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:bd45a5b6c68357578263d74daab6ff9439517f87da63442d244f9f23df56138d"},
{file = "SQLAlchemy-2.0.23-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:a86cb7063e2c9fb8e774f77fbf8475516d270a3e989da55fa05d08089d77f8c4"},
{file = "SQLAlchemy-2.0.23-cp311-cp311-win32.whl", hash = "sha256:b41f5d65b54cdf4934ecede2f41b9c60c9f785620416e8e6c48349ab18643855"},
{file = "SQLAlchemy-2.0.23-cp311-cp311-win_amd64.whl", hash = "sha256:9ca922f305d67605668e93991aaf2c12239c78207bca3b891cd51a4515c72e22"},
{file = "SQLAlchemy-2.0.23-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d0f7fb0c7527c41fa6fcae2be537ac137f636a41b4c5a4c58914541e2f436b45"},
{file = "SQLAlchemy-2.0.23-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7c424983ab447dab126c39d3ce3be5bee95700783204a72549c3dceffe0fc8f4"},
{file = "SQLAlchemy-2.0.23-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f508ba8f89e0a5ecdfd3761f82dda2a3d7b678a626967608f4273e0dba8f07ac"},
{file = "SQLAlchemy-2.0.23-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6463aa765cf02b9247e38b35853923edbf2f6fd1963df88706bc1d02410a5577"},
{file = "SQLAlchemy-2.0.23-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:e599a51acf3cc4d31d1a0cf248d8f8d863b6386d2b6782c5074427ebb7803bda"},
{file = "SQLAlchemy-2.0.23-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:fd54601ef9cc455a0c61e5245f690c8a3ad67ddb03d3b91c361d076def0b4c60"},
{file = "SQLAlchemy-2.0.23-cp312-cp312-win32.whl", hash = "sha256:42d0b0290a8fb0165ea2c2781ae66e95cca6e27a2fbe1016ff8db3112ac1e846"},
{file = "SQLAlchemy-2.0.23-cp312-cp312-win_amd64.whl", hash = "sha256:227135ef1e48165f37590b8bfc44ed7ff4c074bf04dc8d6f8e7f1c14a94aa6ca"},
{file = "SQLAlchemy-2.0.23-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:14aebfe28b99f24f8a4c1346c48bc3d63705b1f919a24c27471136d2f219f02d"},
{file = "SQLAlchemy-2.0.23-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e983fa42164577d073778d06d2cc5d020322425a509a08119bdcee70ad856bf"},
{file = "SQLAlchemy-2.0.23-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e0dc9031baa46ad0dd5a269cb7a92a73284d1309228be1d5935dac8fb3cae24"},
{file = "SQLAlchemy-2.0.23-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:5f94aeb99f43729960638e7468d4688f6efccb837a858b34574e01143cf11f89"},
{file = "SQLAlchemy-2.0.23-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:63bfc3acc970776036f6d1d0e65faa7473be9f3135d37a463c5eba5efcdb24c8"},
{file = "SQLAlchemy-2.0.23-cp37-cp37m-win32.whl", hash = "sha256:f48ed89dd11c3c586f45e9eec1e437b355b3b6f6884ea4a4c3111a3358fd0c18"},
{file = "SQLAlchemy-2.0.23-cp37-cp37m-win_amd64.whl", hash = "sha256:1e018aba8363adb0599e745af245306cb8c46b9ad0a6fc0a86745b6ff7d940fc"},
{file = "SQLAlchemy-2.0.23-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:64ac935a90bc479fee77f9463f298943b0e60005fe5de2aa654d9cdef46c54df"},
{file = "SQLAlchemy-2.0.23-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c4722f3bc3c1c2fcc3702dbe0016ba31148dd6efcd2a2fd33c1b4897c6a19693"},
{file = "SQLAlchemy-2.0.23-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4af79c06825e2836de21439cb2a6ce22b2ca129bad74f359bddd173f39582bf5"},
{file = "SQLAlchemy-2.0.23-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:683ef58ca8eea4747737a1c35c11372ffeb84578d3aab8f3e10b1d13d66f2bc4"},
{file = "SQLAlchemy-2.0.23-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:d4041ad05b35f1f4da481f6b811b4af2f29e83af253bf37c3c4582b2c68934ab"},
{file = "SQLAlchemy-2.0.23-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:aeb397de65a0a62f14c257f36a726945a7f7bb60253462e8602d9b97b5cbe204"},
{file = "SQLAlchemy-2.0.23-cp38-cp38-win32.whl", hash = "sha256:42ede90148b73fe4ab4a089f3126b2cfae8cfefc955c8174d697bb46210c8306"},
{file = "SQLAlchemy-2.0.23-cp38-cp38-win_amd64.whl", hash = "sha256:964971b52daab357d2c0875825e36584d58f536e920f2968df8d581054eada4b"},
{file = "SQLAlchemy-2.0.23-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:616fe7bcff0a05098f64b4478b78ec2dfa03225c23734d83d6c169eb41a93e55"},
{file = "SQLAlchemy-2.0.23-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0e680527245895aba86afbd5bef6c316831c02aa988d1aad83c47ffe92655e74"},
{file = "SQLAlchemy-2.0.23-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9585b646ffb048c0250acc7dad92536591ffe35dba624bb8fd9b471e25212a35"},
{file = "SQLAlchemy-2.0.23-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4895a63e2c271ffc7a81ea424b94060f7b3b03b4ea0cd58ab5bb676ed02f4221"},
{file = "SQLAlchemy-2.0.23-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:cc1d21576f958c42d9aec68eba5c1a7d715e5fc07825a629015fe8e3b0657fb0"},
{file = "SQLAlchemy-2.0.23-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:967c0b71156f793e6662dd839da54f884631755275ed71f1539c95bbada9aaab"},
{file = "SQLAlchemy-2.0.23-cp39-cp39-win32.whl", hash = "sha256:0a8c6aa506893e25a04233bc721c6b6cf844bafd7250535abb56cb6cc1368884"},
{file = "SQLAlchemy-2.0.23-cp39-cp39-win_amd64.whl", hash = "sha256:f3420d00d2cb42432c1d0e44540ae83185ccbbc67a6054dcc8ab5387add6620b"},
{file = "SQLAlchemy-2.0.23-py3-none-any.whl", hash = "sha256:31952bbc527d633b9479f5f81e8b9dfada00b91d6baba021a869095f1a97006d"},
{file = "SQLAlchemy-2.0.23.tar.gz", hash = "sha256:c1bda93cbbe4aa2aa0aa8655c5aeda505cd219ff3e8da91d1d329e143e4aff69"},
]
[package.dependencies]
greenlet = {version = "!=0.4.17", markers = "platform_machine == \"aarch64\" or platform_machine == \"ppc64le\" or platform_machine == \"x86_64\" or platform_machine == \"amd64\" or platform_machine == \"AMD64\" or platform_machine == \"win32\" or platform_machine == \"WIN32\""}
typing-extensions = ">=4.2.0"
[package.extras]
aiomysql = ["aiomysql (>=0.2.0)", "greenlet (!=0.4.17)"]
aioodbc = ["aioodbc", "greenlet (!=0.4.17)"]
aiosqlite = ["aiosqlite", "greenlet (!=0.4.17)", "typing-extensions (!=3.10.0.1)"]
asyncio = ["greenlet (!=0.4.17)"]
asyncmy = ["asyncmy (>=0.2.3,!=0.2.4,!=0.2.6)", "greenlet (!=0.4.17)"]
mariadb-connector = ["mariadb (>=1.0.1,!=1.1.2,!=1.1.5)"]
mssql = ["pyodbc"]
mssql-pymssql = ["pymssql"]
mssql-pyodbc = ["pyodbc"]
mypy = ["mypy (>=0.910)"]
mysql = ["mysqlclient (>=1.4.0)"]
mysql-connector = ["mysql-connector-python"]
oracle = ["cx-oracle (>=8)"]
oracle-oracledb = ["oracledb (>=1.0.1)"]
postgresql = ["psycopg2 (>=2.7)"]
postgresql-asyncpg = ["asyncpg", "greenlet (!=0.4.17)"]
postgresql-pg8000 = ["pg8000 (>=1.29.1)"]
postgresql-psycopg = ["psycopg (>=3.0.7)"]
postgresql-psycopg2binary = ["psycopg2-binary"]
postgresql-psycopg2cffi = ["psycopg2cffi"]
postgresql-psycopgbinary = ["psycopg[binary] (>=3.0.7)"]
pymysql = ["pymysql"]
sqlcipher = ["sqlcipher3-binary"]
[[package]]
name = "typing-extensions"
version = "4.8.0"
description = "Backported and Experimental Type Hints for Python 3.8+"
optional = false
python-versions = ">=3.8"
files = [
{file = "typing_extensions-4.8.0-py3-none-any.whl", hash = "sha256:8f92fc8806f9a6b641eaa5318da32b44d401efaac0f6678c9bc448ba3605faa0"},
{file = "typing_extensions-4.8.0.tar.gz", hash = "sha256:df8e4339e9cb77357558cbdbceca33c303714cf861d1eef15e1070055ae8b7ef"},
]
[[package]]
name = "urllib3"
version = "2.1.0"
description = "HTTP library with thread-safe connection pooling, file post, and more."
optional = false
python-versions = ">=3.8"
files = [
{file = "urllib3-2.1.0-py3-none-any.whl", hash = "sha256:55901e917a5896a349ff771be919f8bd99aff50b79fe58fec595eb37bbc56bb3"},
{file = "urllib3-2.1.0.tar.gz", hash = "sha256:df7aa8afb0148fa78488e7899b2c59b5f4ffcfa82e6c54ccb9dd37c1d7b52d54"},
]
[package.extras]
brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"]
socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"]
zstd = ["zstandard (>=0.18.0)"]
[metadata]
lock-version = "2.0"
python-versions = ">3.8"
content-hash = "b7c1944042f5637e95525997a1a8b7806e70f31f0db2c79e84cf35d65601d01c"

18
crawler/pyproject.toml Normal file
View file

@ -0,0 +1,18 @@
[tool.poetry]
name = "rec"
version = "0.1.0"
description = ""
authors = ["Kadir Tugan <git@k8n.dev>"]
[tool.poetry.dependencies]
python = ">3.8"
SQLAlchemy = "^2.0.23"
requests = "^2.31.0"
cachetools = "^5.3.2"
diskcache = "^5.6.3"
[tool.poetry.dev-dependencies]
[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"

0
crawler/rec/__init__.py Normal file
View file

38
crawler/rec/db.py Normal file
View file

@ -0,0 +1,38 @@
from sqlalchemy import create_engine
from sqlalchemy.orm import Session
from sqlalchemy import Column, Integer, JSON, FLOAT
from sqlalchemy.orm import declarative_base
engine = create_engine("sqlite:///sqlite.db", echo=True)
session = Session(engine)
Base = declarative_base()
class RightmoveListing(Base):
__tablename__ = "rightmove"
id = Column(Integer, primary_key=True)
price = Column(FLOAT)
listing_json = Column(JSON, nullable=True)
detail_json = Column(JSON, nullable=True)
updated_timestamp = Column(Integer, nullable=True)
lat = Column(FLOAT)
lon = Column(FLOAT)
distance_to_office_minutes = Column(FLOAT, nullable=True)
def save(self):
session.add(self)
session.commit()
def __repr__(self):
return "<RightMoveListing(id='{}', price='{}', lat={}, lon={}')>".format(
self.id,
self.price,
self.lat,
self.lon,
)
if __name__ == "__main__":
Base.metadata.create_all(engine)

80
crawler/rec/query.py Normal file
View file

@ -0,0 +1,80 @@
import pickle
import cachetools
from diskcache import Cache
import requests
from rec.db import RightmoveListing
import urllib3
urllib3.disable_warnings()
cache = Cache(r"_cache")
headers = {
"Host": "api.rightmove.co.uk",
# 'Accept-Encoding': 'gzip, deflate, br',
"User-Agent": "okhttp/4.10.0",
"Connection": "close",
}
def detail_query(detail_id: int):
params = {
'apiApplication': 'ANDROID',
'appVersion': '3.70.0',
}
url = f'https://api.rightmove.co.uk/api/property/{detail_id}'
response = requests.get(url, params=params, headers=headers, verify=False)
if response.status_code != 200:
raise Exception("Failed due to: ", response.text)
return response.json()
@cache.memoize()
def listing_query(page: int, min_bedrooms: int, max_bedrooms: int, radius: float, min_price: int, max_price: int):
print("Querying")
params = {
"locationIdentifier": "POSTCODE^4228216",
"channel": "BUY",
"page": str(page),
"numberOfPropertiesPerPage": "25",
"radius": str(radius),
"sortBy": "distance",
"includeUnavailableProperties": "false",
"propertyTypes": "flat",
"dontShow": "sharedOwnership,retirement",
"minPrice": str(min_price),
"maxPrice": str(max_price),
"minBedrooms": str(min_bedrooms),
"maxBedrooms": str(max_bedrooms),
"apiApplication": "ANDROID",
"appVersion": "3.70.0",
}
response = requests.get(
"https://api.rightmove.co.uk/api/property-listing",
params=params,
headers=headers,
verify=False,
)
if response.status_code != 200:
raise Exception("Failed due to: ", response.text)
return response.json()
if __name__ == "__main__":
response = listing_query(page=1, min_bedrooms=2, max_bedrooms=2, radius=5.0, min_price=150000, max_price=700000)
resp = response
for d in resp["properties"]:
rl = RightmoveListing(
id=d["identifier"],
listing_json=d,
price=d["price"],
updated_timestamp=d["updateDate"],
lat=d["latitude"],
lon=d["longitude"],
)
rl.save()

View file

@ -0,0 +1,8 @@
def parse_listing_json_entry(d):
id = d["identifier"]
# address = d['address']
propertyType = d["propertyType"]
price = d["price"]
latitude = d["latitude"]
longitude = d["longitude"]
updated_date = d["updateDate"]

10
crawler/testing.py Normal file
View file

@ -0,0 +1,10 @@
from rec.db import RightmoveListing, session
from sqlalchemy import select
if __name__ == '__main__':
print("x")
x = select(RightmoveListing).where(RightmoveListing.price <600000)
print("y")
d = list(session.execute(x))
print(d)