forked from alltheplaces/alltheplaces
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtraveliq_web_cameras.py
More file actions
70 lines (59 loc) · 3.02 KB
/
traveliq_web_cameras.py
File metadata and controls
70 lines (59 loc) · 3.02 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
import re
from typing import Iterable
from scrapy import Spider
from scrapy.http import JsonRequest, Response
from locations.categories import Categories, apply_category
from locations.items import Feature
class TravelIQWebCamerasSpider(Spider):
"""
Travel-IQ is a real-time road vehicle traffic management system used
extensively in North America for providing the public with the following
types of information:
- Congestion
- Variable speed limit changes
- Roadworks
- Traffic accidents
- Weather information
- Webcam feeds
Usually TravelIQSpider could be used to retrieve information but in some
rarer cases, a state transportation agency/department may be providing
a Travel-IQ system with the official API disabled. This typically occurs
when there is no corresponding mobile application and all users are
required to use a web browser instead.
This storefinder class implements an alternative type of API used by web
browser sessions for retrieving a list of traffic cameras.
To use, specify:
- 'allowed_domains': mandatory parameter
"""
def start_requests(self) -> Iterable[JsonRequest]:
yield JsonRequest(
url="https://"
+ self.allowed_domains[0]
+ '/List/GetData/Cameras?query={"columns":[{"data":null,"name":""},{"name":"sortId","s":true},{"name":"state","s":true},{"name":"roadway","s":true},{"name":"description1"},{"data":5,"name":""}],"order":[{"column":2,"dir":"asc"},{"column":1,"dir":"asc"}],"start":0,"length":100,"search":{"value":""}}&lang=en-US'
)
def parse(self, response: Response) -> Iterable[JsonRequest | Feature]:
for start in range(100, response.json()["recordsFiltered"], 100):
yield JsonRequest(
url=response.url.replace("%22start%22:0", "%22start%22:{}".format(start)), callback=self.parse_cameras
)
yield from self.parse_cameras(response)
def parse_cameras(self, response: Response) -> Iterable[Feature]:
for camera in response.json()["data"]:
properties = {
"ref": str(camera["id"]),
"name": camera["location"],
"state": camera["state"],
}
wkt = camera["latLng"]["geography"]["wellKnownText"]
if m := re.fullmatch(r"POINT \((-?\d+\.\d+) (-?\d+\.\d+)\)", wkt):
properties["lon"] = m.group(1)
properties["lat"] = m.group(2)
apply_category(Categories.SURVEILLANCE_CAMERA, properties)
properties["extras"]["contact:webcam"] = "https://{}/tooltip/Cameras/{}".format(
self.allowed_domains[0], properties["ref"]
)
properties["extras"]["camera:type"] = "fixed"
yield from self.post_process_item(Feature(**properties), response, camera) or []
def post_process_item(self, item: Feature, response: Response, feature: dict) -> Iterable[Feature]:
"""Override to perform post-processing of the extracted feature."""
yield item