-
Notifications
You must be signed in to change notification settings - Fork 4
/
event_fetcher.py
171 lines (134 loc) · 5.93 KB
/
event_fetcher.py
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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
import requests
import json
import time
import csv
import sys
import argparse
from datetime import datetime, timedelta
URL = 'https://ra.co/graphql'
HEADERS = {
'Content-Type': 'application/json',
'Referer': 'https://ra.co/events/uk/london',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:106.0) Gecko/20100101 Firefox/106.0'
}
QUERY_TEMPLATE_PATH = "graphql_query_template.json"
DELAY = 1 # Adjust this value as needed
class EventFetcher:
"""
A class to fetch and print event details from RA.co
"""
def __init__(self, areas, listing_date_gte, listing_date_lte):
self.payload = self.generate_payload(areas, listing_date_gte, listing_date_lte)
@staticmethod
def generate_payload(areas, listing_date_gte, listing_date_lte):
"""
Generate the payload for the GraphQL request.
:param areas: The area code to filter events.
:param listing_date_gte: The start date for event listings (inclusive).
:param listing_date_lte: The end date for event listings (inclusive).
:return: The generated payload.
"""
with open(QUERY_TEMPLATE_PATH, "r") as file:
payload = json.load(file)
payload["variables"]["filters"]["areas"]["eq"] = areas
payload["variables"]["filters"]["listingDate"]["gte"] = listing_date_gte
payload["variables"]["filters"]["listingDate"]["lte"] = listing_date_lte
return payload
def get_events(self, page_number):
"""
Fetch events for the given page number.
:param page_number: The page number for event listings.
:return: A list of events.
"""
self.payload["variables"]["page"] = page_number
response = requests.post(URL, headers=HEADERS, json=self.payload)
try:
response.raise_for_status()
data = response.json()
except (requests.exceptions.RequestException, ValueError):
print(f"Error: {response.status_code}")
return []
if 'data' not in data:
print(f"Error: {data}")
return []
return data["data"]["eventListings"]["data"]
@staticmethod
def print_event_details(events):
"""
Print the details of the events.
:param events: A list of events.
"""
for event in events:
event_data = event["event"]
print(f"Event name: {event_data['title']}")
print(f"Date: {event_data['date']}")
print(f"Start Time: {event_data['startTime']}")
print(f"End Time: {event_data['endTime']}")
print(f"Artists: {[artist['name'] for artist in event_data['artists']]}")
print(f"Venue: {event_data['venue']['name']}")
print(f"Event URL: {event_data['contentUrl']}")
print(f"Number of guests attending: {event_data['attending']}")
print("-" * 80)
def fetch_and_print_all_events(self):
"""
Fetch and print all events.
"""
page_number = 1
while True:
events = self.get_events(page_number)
if not events:
break
self.print_event_details(events)
page_number += 1
time.sleep(DELAY)
def fetch_all_events(self):
"""
Fetch all events and return them as a list.
:return: A list of all events.
"""
all_events = []
page_number = 1
while True:
events = self.get_events(page_number)
if not events:
break
all_events.extend(events)
page_number += 1
time.sleep(DELAY)
return all_events
def save_events_to_csv(self, events, output_file="events.csv"):
"""
Save events to a CSV file.
:param events: A list of events.
:param output_file: The output file path. (default: "events.csv")
"""
with open(output_file, "w", newline="", encoding="utf-8") as file:
writer = csv.writer(file)
writer.writerow(["Event name", "Date", "Start Time", "End Time", "Artists",
"Venue", "Event URL", "Number of guests attending"])
for event in events:
event_data = event["event"]
writer.writerow([event_data['title'], event_data['date'], event_data['startTime'],
event_data['endTime'], ', '.join([artist['name'] for artist in event_data['artists']]),
event_data['venue']['name'], event_data['contentUrl'], event_data['attending']])
def main():
parser = argparse.ArgumentParser(description="Fetch events from ra.co and save them to a CSV file.")
parser.add_argument("areas", type=int, help="The area code to filter events.")
parser.add_argument("start_date", type=str, help="The start date for event listings (inclusive, format: YYYY-MM-DD).")
parser.add_argument("end_date", type=str, help="The end date for event listings (inclusive, format: YYYY-MM-DD).")
parser.add_argument("-o", "--output", type=str, default="events.csv", help="The output file path (default: events.csv).")
args = parser.parse_args()
listing_date_gte = f"{args.start_date}T00:00:00.000Z"
listing_date_lte = f"{args.end_date}T23:59:59.999Z"
event_fetcher = EventFetcher(args.areas, listing_date_gte, listing_date_lte)
all_events = []
current_start_date = datetime.strptime(args.start_date, "%Y-%m-%d")
while current_start_date <= datetime.strptime(args.end_date, "%Y-%m-%d"):
listing_date_gte = current_start_date.strftime("%Y-%m-%dT00:00:00.000Z")
event_fetcher.payload = event_fetcher.generate_payload(args.areas, listing_date_gte, listing_date_lte)
events = event_fetcher.fetch_all_events()
all_events.extend(events)
current_start_date += timedelta(days=len(events))
event_fetcher.save_events_to_csv(all_events, args.output)
if __name__ == "__main__":
main()