You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
**Verify the client** (run the script to hit the live site and print sample data):
76
+
77
+
```bash
78
+
pip install -e .
79
+
python scripts/verify_client.py # up to 3 pages of ratings per section (default)
80
+
python scripts/verify_client.py --max-pages 10 --page-size 20 # scrape more pages
81
+
```
82
+
83
+
**Scrape all ratings** for a professor or school: the client fetches the first page from HTML and subsequent pages via the site’s GraphQL API. Use the iterators to get every rating:
84
+
85
+
```python
86
+
with RMPClient() as client:
87
+
for rating in client.iter_professor_ratings("2823076"):
88
+
print(rating.date, rating.comment)
89
+
for rating in client.iter_school_ratings("1466"):
90
+
print(rating.date, rating.comment)
91
+
```
92
+
93
+
## How it works
94
+
95
+
### Package architecture
96
+
97
+
```mermaid
98
+
flowchart TB
99
+
subgraph Your code
100
+
User["Your script / app"]
101
+
end
102
+
103
+
subgraph rmp_client [rmp_client package]
104
+
Client["RMPClient\n(client.py)"]
105
+
Config["RMPClientConfig\n(config.py)"]
106
+
Models["Models\n(School, Professor, Rating)\n(models.py)"]
107
+
Errors["RMPError hierarchy\n(errors.py)"]
108
+
end
109
+
110
+
subgraph HTTP layer
111
+
HttpCtx["HttpClientContext\n(http.py)"]
112
+
Http["HttpClient\n(retries, headers)"]
113
+
Bucket["TokenBucket\n(rate_limit.py)"]
114
+
end
115
+
116
+
subgraph External
117
+
RMP["RMP pages\n(ratemyprofessors.com)"]
118
+
end
119
+
120
+
User --> Client
121
+
Client --> Config
122
+
Client --> HttpCtx
123
+
HttpCtx --> Http
124
+
Http --> Bucket
125
+
Http --> RMP
126
+
Client --> Models
127
+
Client --> Errors
128
+
```
129
+
130
+
### Request flow
131
+
132
+
Professor, school, compare-schools, and search endpoints **fetch the relevant RMP page HTML** (GET), extract `window.__RELAY_STORE__` from the response, and parse it into `Professor`, `School`, `Rating`, or search result lists.
133
+
134
+
**Ratings pagination (Relay):** The first page of professor or school ratings comes from the same HTML (Relay store). The store’s connection includes:
135
+
136
+
-**`pageInfo.endCursor`** — opaque cursor for “start after this item”
137
+
-**`pageInfo.hasNextPage`** — whether more ratings exist
138
+
139
+
The client then requests the next page by POSTing to `/graphql` with the same query and variables:
140
+
141
+
-`id` — Relay node id (base64 of `Teacher-{legacyId}` or `School-{legacyId}`)
142
+
-`first` — page size (e.g. 20)
143
+
-`after` — `pageInfo.endCursor` from the previous response
144
+
145
+
Loop until `hasNextPage` is false. The cursor is typically base64 for an internal offset (e.g. `YXJyYXljb25uZWN0aW9uOjQ=` decodes to `arrayconnection:4`, meaning “after item 4”). RMP does not rotate or expire these cursors, so you can paginate with plain HTTP requests without a browser. This client sends the **full GraphQL query** in each request; if the site ever required persisted queries (e.g. `doc_id` only), you’d capture the real request from the browser and reuse that format.
146
+
147
+
```mermaid
148
+
sequenceDiagram
149
+
participant User
150
+
participant RMPClient
151
+
participant HttpClient
152
+
participant TokenBucket
153
+
participant httpx
154
+
participant RMP
155
+
156
+
User->>RMPClient: e.g. get_professor(id), get_school(id), search_professors(q), get_compare_schools(id1, id2)
157
+
RMPClient->>HttpClient: get_html(url)
158
+
HttpClient->>TokenBucket: consume()
159
+
TokenBucket-->>HttpClient: (blocks until token available)
160
+
HttpClient->>httpx: GET page URL
161
+
httpx->>RMP: HTTPS request
162
+
RMP-->>httpx: HTML (with __RELAY_STORE__)
163
+
httpx-->>HttpClient: response
164
+
HttpClient-->>RMPClient: HTML text
165
+
RMPClient->>RMPClient: Extract and parse __RELAY_STORE__, resolve refs
166
+
RMPClient->>RMPClient: Map to Professor / School / Rating / SearchResult
167
+
RMPClient-->>User: Professor, School, list, or CompareSchoolsResult
0 commit comments