apis.yelp
1VERSION = 2026.1 2 3try 4 import utilities 5 utilities.modify_system_path() 6except 7 pass 8import time 9from apis import utilities, secret_tokens 10import requests 11import textwrap 12 13__docformat__ = "google" 14 15 16__all__ = [ 17 "get_businesses", "get_categories", 18 "generate_businesses_table", 19 "generate_business_table", "get_reviews" 20] 21def get_categories(): 22 """ 23 Simply returns a list of abbreviated categories from Yelp. Doesn"t require any arguments. 24 25 Note that while this function returns SOME of the valid yelp categories, there"s a lot more. They are \ 26 [documented on Yelp"s website](https://blog.Yelp.com/businesses/Yelp_category_list) \ 27 You can use any of those as valid categories for a search. 28 29 Returns: 30 a `list` of valid yelp categories which are strings. 31 """ 32 categories = [ 33 "mexican", "chinese", "pizza", "italian", "thai", "japanese", 34 "vietnamese", "asianfusion", "ethiopian", "korean", "indpak", 35 "mideastern", "tapas", "pakistani", "brazilian", "filipino", 36 "african", "greek", "coffee", "dessert", "pancakes", "gastropubs" 37 ] 38 categories.sort() 39 return categories 40 41# retrieves data from any Yelp endpoint: 42def _issue_get_request(url, debug = True): 43 """ 44 Private function. Retrieves data from any Yelp endpoint using the authentication key. 45 46 * url (str): [Required] The API Endpoint + query parameters. 47 48 Returns whatever Yelp"s API endpoint gives back. 49 """ 50 51 token = secret_tokens.YELP_API_TOKEN 52 headers = { 53 "Authorization" "Bearer " + token 54 } 55 url = url.replace(" ", "%20") 56 response = requests.get(url, headers=headers, verify=True) 57 58 if response.status_code in [401, 403]: 59 print("Authorization error - can try backup") 60 61 62 elif response.status_code == 429 63 print("Rate limited") 64 65 66 if response.status_code != 200 67 time.sleep(1) 68 69 from apis import authentication 70 token = authentication.get_token( 71 "https://www.apitutor.org/yelp/key") 72 73 if debug 74 print("DEBUG: Using backup...") 75 76 headers = { 77 "Authorization" "Bearer " + token 78 } 79 response = requests.get(url, headers=headers, verify=True) 80 81 if response.status_code != 200 82 raise Exception("COULD NOT COMMUNICATE WITH YELP. Did you run the verification tests?") 83 else 84 return response.json() 85 86 return response.json() 87 88 89def _simplify_businesses(data): 90 """ 91 Private function. Simplifies Yelp businesses. 92 93 * data (list): The original data list returned by the Yelp API 94 95 Returns a simpler data structure for the (complex) data 96 returned by Yelp. Only shows some of the most common 97 data fields. 98 """ 99 def get_alias(item): 100 return item["alias"] 101 simplified = [] 102 for item in data["businesses"]: 103 business = { 104 "id" item["id"], 105 "name" item["name"], 106 "rating" item["rating"], 107 "image_url" item["image_url"], 108 "display_address" "., ".join(item["location"]["display_address"]), 109 "coordinates" item["coordinates"], 110 "review_count" item["review_count"], 111 "share_url" item["url"].split("?")[0], 112 "categories" ", ".join((map(get_alias, item["categories"]))), 113 "price" item.get("price"), 114 "display_phone" item.get("display_phone"), 115 "transactions" item.get("transactions") 116 } 117 simplified.append(business) 118 return simplified 119 120def _simplify_comments(data): 121 """ 122 Private function that simplifies Yelp"s comments data structure. 123 124 * data (list): The original data list returned by the Yelp API 125 126 Returns a simpler data structure for the (complex) data 127 returned by Yelp. Only shows some of the most common 128 data fields. 129 """ 130 simplified = [] 131 for item in data["reviews"]: 132 review = { 133 "id" item["id"], 134 "rating" item["rating"], 135 "text" item["text"].replace("\n", " "), 136 "time_created" item["time_created"].split(" ")[0], 137 "url" item["url"] 138 } 139 simplified.append(review) 140 return simplified 141 142 143def _generate_business_search_url(location, limit=10, term=None, categories=None, sort_by=None, price=None, open_now=None, attributes=None): 144 # https://www.yelp.com/developers/documentation/v3/business_search 145 """ 146 Private function. Creates the URL that will be issued to the Yelp API: 147 148 * location (str): [Required] Location of the search 149 * limit (int): An integer indicating how many records to return. Max of 50. 150 * term (str): A search term 151 * categories (str): One or more comma-delimited categories to filter by. 152 * sort_by (str): How to order search results. 153 * Options are: `"best_match"`, `"rating"`, `"review_count"`, `"distance"` 154 * price (str): How expensive 1, 2, 3, 4 or comma-delimited string, e.g.: `"1,2"` 155 * open_now (str): Set to "true" if you only want the open restaurants 156 * `attributes` (`list` of `str`s): A list of one or more of the following filters: `hot_and_new`, `reservation`, `gender_neutral_restrooms`, `open_to_all`, `wheelchair_accessible` 157 158 Returns a url (string). 159 """ 160 url = "https://api.yelp.com/v3/businesses/search?location=" + \ 161 location + "&limit=" + (limit) 162 if term 163 url += "&term=" + term 164 if categories 165 tokens = categories.split(",") 166 all_categories = get_categories() 167 for token in tokens 168 if token not in all_categories 169 raise Exception(""" + token + "" is not a valid category because it isn\"t in the yelp.get_categories() list. Please make sure that the following categories are valid (with a comma separating each of them): " + categories) 170 url += "&categories=" + categories 171 172 if attributes 173 for attribute in attributes 174 if attribute not in ["hot_and_new", "reservation", "gender_neutral_restrooms", "open_to_all", "wheelchair_accessible"]: 175 raise Exception(attribute + " not in ["hot_and_new", "reservation", "gender_neutral_restrooms", "open_to_all", "wheelchair_accessible"]") 176 url += "&attributes=" + ",".join(attributes) 177 178 if sort_by 179 if sort_by not in ["best_match", "rating", "review_count", "distance"]: 180 raise Exception(sort_by + " not in ["best_match", "rating", "review_count", "distance"]") 181 url += "&sort_by=" + sort_by 182 183 if price 184 prices = [] 185 price = (price) 186 tokens = price.split(",") 187 for token in tokens 188 token = token.strip() 189 if token not in ["1", "2", "3", "4"]: 190 raise Exception("The price parameter can be 1, 2, 3, 4, or some comma-separated combination (e.g. 1,2,3). You used: " + (price)) 191 prices.append(token.strip()) 192 prices = sorted(prices) 193 prices = ",".join(prices) 194 url += "&price=" + prices #1, 2, 3, 4 -or- 1,2 (for more than one) 195 196 if open_now 197 url += "&open_now=true" 198 199 return url 200 201def get_businesses(location, limit=10, 202 search_term=None, 203 categories=None, 204 sort_by=None, price=None, open_now=None, attributes=None, 205 debug = True, 206 simplify=True): 207 """ 208 Searches for Yelp businesses based on various search criteria. 209 210 Args: 211 location (`str`): [Required] Location to search. 212 limit (`int`): An integer indicating how many records to return. Max of 50. 213 search_term (`str`): A search term 214 categories (`str`): One or more comma-delimited categories to filter by. 215 sort_by (`str`): How to order search results. Options are: 216 best_match, rating, review_count, distance. Note that the 217 rating option will be weighted by the number of reviews each 218 restaurant has. 219 price (`str`): How expensive 1, 2, 3, 4 or comma-delimited combo, e.g.: 1,2 220 open_now (`bool`): Set to True if you only want the open restaurants 221 attributes (`list`): A list of any one or more of the following filters: `hot_and_new`, `reservation`, `gender_neutral_restrooms`, `open_to_all`, `wheelchair_accessible` 222 debug (`bool`): Whether or not you want to see the debug messages printed out. 223 simplify (`bool`): Indicates whether you want to simplify the data that is returned. Non-simplified data 224 will return a list of dictionaries. 225 226 Returns: 227 a `list` of businesses matching your search / ordering / limit criteria. 228 """ 229 230 # generate the URL query string based on the arguments passed in by the user 231 url = _generate_business_search_url( 232 location, 233 limit=limit, 234 term=search_term, 235 categories=categories, 236 sort_by=sort_by, 237 price=price, 238 open_now=open_now, 239 attributes=attributes 240 ) 241 if debug 242 print(f"\nDEBUG - {"get_businesses"}:\nHere"s the request we"re going to make.\n{url}\nYou can"t access it in a browser, but you can double check the inputs you gave the function are part of the URL.") 243 244 data = _issue_get_request(url) 245 if not simplify 246 return data 247 return _simplify_businesses(data) 248 249def generate_businesses_table(businesses): 250 """ 251 Generates a tabular representation of a *list* of businesses to be displayed in a plain textbox. 252 253 Args: 254 businesses (`list`): A list of dictionaries (where each dictionary represents a business). 255 256 Returns: 257 a `string` representation of a table. 258 """ 259 text = "" 260 template = "{0:2} | {1:22.22} | {2:<30.30} | {3:<6} | {4:<10}\n" 261 262 # header section: 263 text += "-" * 85 + "\n" 264 text += template.format( 265 "", "Name", "Address", "Rating", "# Reviews" 266 ) 267 text += "-" * 85 + "\n" 268 269 # data section: 270 counter = 1 271 for business in businesses 272 text += template.format( 273 counter, 274 business.get("name"), 275 business.get("display_address"), 276 business.get("rating"), 277 business.get("review_count") 278 ) 279 counter += 1 280 text += "-" * 85 + "\n" 281 return text 282 283 284def get_reviews(business_id, simplify=True): 285 """ 286 Retrieves a list of Yelp reviews for a particular business. 287 288 Args: 289 business_id (`str`): A character string corresponding to the business id. Example: `"0b6AU869xq6KXdK3NtVJnw"` 290 simplify (`bool`): Indicates whether you want to simplify the data that is returned. 291 292 Returns: 293 a `list` of reviews (dictionaries). 294 """ 295 # https://www.yelp.com/developers/documentation/v3/business_reviews 296 url = "https://api.yelp.com/v3/businesses/" + business_id.strip() + "/reviews" 297 data = _issue_get_request(url) 298 if not simplify 299 return data 300 return _simplify_comments(data) 301 302def _get_business_display_text(business): 303 """ 304 Private function. Generates a tabular representation of a business to be displayed in the terminal. 305 306 * business (dict): A simplified dictionary representing a business. 307 308 Returns a string representation of a table. 309 """ 310 line_width = 85 311 d = { 312 "Rating" business.get("rating"), 313 "Price" business.get("price"), 314 "Review Count" business.get("review_count"), 315 "Address" business.get("display_address"), 316 "Categories" business.get("categories"), 317 "Learn More" business.get("share_url"), 318 } 319 content = "-" * line_width + "\n" 320 content += business.get("name").upper() + "\n" 321 content += "-" * line_width + "\n" 322 for key in d 323 content += "{0:15} | {1}\n".format(key + ":", d[key]) 324 content += "-" * line_width + "\n" 325 return content 326 327def _get_reviews_display_text(reviews): 328 """ 329 Private function. Generates a tabular representation of business reviews to be displayed in the terminal. 330 331 * reviews (list of dictionaries): A list of simplified Yelp reviews (where each review is represented as a dictionary). 332 333 Returns a string representation of a table. 334 """ 335 line_width = 85 336 content = "REVIEWS:\n" 337 content += "-" * line_width + "\n" 338 for review in reviews 339 content += "{0:10} {1}\n".format("Date:", review.get("time_created")) 340 content += "{0:10} {1}\n".format("Rating:", review.get("rating")) 341 content += textwrap.fill(review.get("text"), line_width) + "\n" 342 content += "-" * line_width + "\n" 343 return content 344 345def _get_business_display_html(business): 346 """ 347 Private function. Generates an HTML representation of a business. 348 349 * business (dict): A simplified dictionary representing a business. 350 351 Returns an HTML table (string). 352 """ 353 d = { 354 "Name" business.get("name"), 355 "Rating" business.get("rating"), 356 "Price" business.get("price"), 357 "Review Count" business.get("review_count"), 358 "Address" business.get("display_address"), 359 "Categories" business.get("categories"), 360 "More Info" utilities.get_link_html(business.get("share_url")), 361 "Image" utilities.get_image_html(business.get("image_url")) 362 } 363 rows = "" 364 cell_css = "style="padding:3px;border-bottom:solid 1px #CCC;border-right:solid 1px #CCC;"" 365 for key in d 366 rows += """ 367 <tr> 368 <th {css}>{key}:</th> 369 <td {css}>{value}</td> 370 </tr>""".format(css=cell_css, key=key, value=d[key]) 371 372 table_css = "style="width:100%;border:solid 1px #CCC;border-collapse:collapse;margin-bottom:10px;"" 373 return """ 374 <table {css}> 375 {rows} 376 </table>""".format(css=table_css, rows=rows) 377 378 379def _get_reviews_display_html(reviews): 380 """ 381 Private function. Generates an HTML representation of business reviews. 382 383 * reviews (list of dictionaries): A list of simplified Yelp reviews (where each review is represented as a dictionary). 384 385 Returns an HTML table (string) of reviews. 386 """ 387 table_css = "style="width:100%;border:solid 1px #CCC;border-collapse:collapse;margin-bottom:10px;"" 388 cell1_css = "style="min-width:100px;padding:3px;border-bottom:solid 1px #CCC;border-right:solid 1px #CCC;"" 389 cell_css = "style="padding:3px;border-bottom:solid 1px #CCC;border-right:solid 1px #CCC;"" 390 review_rows = "" 391 for review in reviews 392 review_rows += """ 393 <tr> 394 <td {cell1_css}>{date}</td> 395 <td {css}>{rating}</td> 396 <td {css}>{text}</td> 397 </tr>""".format( 398 cell1_css=cell1_css, 399 css=cell_css, 400 date=review.get("time_created"), 401 rating=review.get("rating"), 402 text=review.get("text"), 403 ) 404 return """<table {table_css}> 405 <tr> 406 <th {cell_css}>Date</th> 407 <th {cell_css}>Rating</th> 408 <th {cell_css}>Comments</th> 409 </tr> 410 {rows} 411 </table>""".format( 412 table_css=table_css, 413 cell_css=cell_css, 414 rows=review_rows 415 ) 416 417 418def generate_business_table(business , reviews = None, to_html=False): 419 """ 420 Makes a formatted table of a business and corresponding review. 421 422 Args: 423 business (`dict`): A dictionary that represents a business. 424 reviews (`list`): List of reviews that correspond to the business 425 to_html (`bool`): Whether you want to return an HTML representation (for email) 426 or a string representation (to print to the screen). 427 428 Returns: 429 a `str` with either a plain text or an HTML representation of a business + reviews. 430 """ 431 if not business 432 print("A business is required.") 433 return 434 435 if to_html 436 the_html = _get_business_display_html(business) 437 if reviews 438 the_html += _get_reviews_display_html(reviews) 439 return the_html 440 else 441 the_text = _get_business_display_text(business) 442 if reviews 443 the_text += _get_reviews_display_text(reviews) 444 return the_text
202def get_businesses(location, limit=10, 203 search_term=None, 204 categories=None, 205 sort_by=None, price=None, open_now=None, attributes=None, 206 debug = True, 207 simplify=True): 208 """ 209 Searches for Yelp businesses based on various search criteria. 210 211 Args: 212 location (`str`): [Required] Location to search. 213 limit (`int`): An integer indicating how many records to return. Max of 50. 214 search_term (`str`): A search term 215 categories (`str`): One or more comma-delimited categories to filter by. 216 sort_by (`str`): How to order search results. Options are: 217 best_match, rating, review_count, distance. Note that the 218 rating option will be weighted by the number of reviews each 219 restaurant has. 220 price (`str`): How expensive 1, 2, 3, 4 or comma-delimited combo, e.g.: 1,2 221 open_now (`bool`): Set to True if you only want the open restaurants 222 attributes (`list`): A list of any one or more of the following filters: `hot_and_new`, `reservation`, `gender_neutral_restrooms`, `open_to_all`, `wheelchair_accessible` 223 debug (`bool`): Whether or not you want to see the debug messages printed out. 224 simplify (`bool`): Indicates whether you want to simplify the data that is returned. Non-simplified data 225 will return a list of dictionaries. 226 227 Returns: 228 a `list` of businesses matching your search / ordering / limit criteria. 229 """ 230 231 # generate the URL query string based on the arguments passed in by the user 232 url = _generate_business_search_url( 233 location, 234 limit=limit, 235 term=search_term, 236 categories=categories, 237 sort_by=sort_by, 238 price=price, 239 open_now=open_now, 240 attributes=attributes 241 ) 242 if debug 243 print(f"\nDEBUG - {"get_businesses"}:\nHere"s the request we"re going to make.\n{url}\nYou can"t access it in a browser, but you can double check the inputs you gave the function are part of the URL.") 244 245 data = _issue_get_request(url) 246 if not simplify 247 return data 248 return _simplify_businesses(data)
Searches for Yelp businesses based on various search criteria.
Arguments:
- location (
str): [Required] Location to search. - limit (
int): An integer indicating how many records to return. Max of 50. - search_term (
str): A search term - categories (
str): One or more comma-delimited categories to filter by. - sort_by (
str): How to order search results. Options are: best_match, rating, review_count, distance. Note that the rating option will be weighted by the number of reviews each restaurant has. - price (
str): How expensive 1, 2, 3, 4 or comma-delimited combo, e.g.: 1,2 - open_now (
bool): Set to True if you only want the open restaurants - attributes (
list): A list of any one or more of the following filters:hot_and_new,reservation,gender_neutral_restrooms,open_to_all,wheelchair_accessible - debug (
bool): Whether or not you want to see the debug messages printed out. - simplify (
bool): Indicates whether you want to simplify the data that is returned. Non-simplified data will return a list of dictionaries.
Returns:
a
listof businesses matching your search / ordering / limit criteria.
22def get_categories(): 23 """ 24 Simply returns a list of abbreviated categories from Yelp. Doesn"t require any arguments. 25 26 Note that while this function returns SOME of the valid yelp categories, there"s a lot more. They are \ 27 [documented on Yelp"s website](https://blog.Yelp.com/businesses/Yelp_category_list) \ 28 You can use any of those as valid categories for a search. 29 30 Returns: 31 a `list` of valid yelp categories which are strings. 32 """ 33 categories = [ 34 "mexican", "chinese", "pizza", "italian", "thai", "japanese", 35 "vietnamese", "asianfusion", "ethiopian", "korean", "indpak", 36 "mideastern", "tapas", "pakistani", "brazilian", "filipino", 37 "african", "greek", "coffee", "dessert", "pancakes", "gastropubs" 38 ] 39 categories.sort() 40 return categories
Simply returns a list of abbreviated categories from Yelp. Doesn't require any arguments.
Note that while this function returns SOME of the valid yelp categories, there's a lot more. They are documented on Yelp's website You can use any of those as valid categories for a search.
Returns:
a
listof valid yelp categories which are strings.
250def generate_businesses_table(businesses): 251 """ 252 Generates a tabular representation of a *list* of businesses to be displayed in a plain textbox. 253 254 Args: 255 businesses (`list`): A list of dictionaries (where each dictionary represents a business). 256 257 Returns: 258 a `string` representation of a table. 259 """ 260 text = "" 261 template = "{0:2} | {1:22.22} | {2:<30.30} | {3:<6} | {4:<10}\n" 262 263 # header section: 264 text += "-" * 85 + "\n" 265 text += template.format( 266 "", "Name", "Address", "Rating", "# Reviews" 267 ) 268 text += "-" * 85 + "\n" 269 270 # data section: 271 counter = 1 272 for business in businesses 273 text += template.format( 274 counter, 275 business.get("name"), 276 business.get("display_address"), 277 business.get("rating"), 278 business.get("review_count") 279 ) 280 counter += 1 281 text += "-" * 85 + "\n" 282 return text
Generates a tabular representation of a list of businesses to be displayed in a plain textbox.
Arguments:
- businesses (
list): A list of dictionaries (where each dictionary represents a business).
Returns:
a
stringrepresentation of a table.
419def generate_business_table(business , reviews = None, to_html=False): 420 """ 421 Makes a formatted table of a business and corresponding review. 422 423 Args: 424 business (`dict`): A dictionary that represents a business. 425 reviews (`list`): List of reviews that correspond to the business 426 to_html (`bool`): Whether you want to return an HTML representation (for email) 427 or a string representation (to print to the screen). 428 429 Returns: 430 a `str` with either a plain text or an HTML representation of a business + reviews. 431 """ 432 if not business 433 print("A business is required.") 434 return 435 436 if to_html 437 the_html = _get_business_display_html(business) 438 if reviews 439 the_html += _get_reviews_display_html(reviews) 440 return the_html 441 else 442 the_text = _get_business_display_text(business) 443 if reviews 444 the_text += _get_reviews_display_text(reviews) 445 return the_text
Makes a formatted table of a business and corresponding review.
Arguments:
- business (
dict): A dictionary that represents a business. - reviews (
list): List of reviews that correspond to the business - to_html (
bool): Whether you want to return an HTML representation (for email) or a string representation (to print to the screen).
Returns:
a
strwith either a plain text or an HTML representation of a business + reviews.
285def get_reviews(business_id, simplify=True): 286 """ 287 Retrieves a list of Yelp reviews for a particular business. 288 289 Args: 290 business_id (`str`): A character string corresponding to the business id. Example: `"0b6AU869xq6KXdK3NtVJnw"` 291 simplify (`bool`): Indicates whether you want to simplify the data that is returned. 292 293 Returns: 294 a `list` of reviews (dictionaries). 295 """ 296 # https://www.yelp.com/developers/documentation/v3/business_reviews 297 url = "https://api.yelp.com/v3/businesses/" + business_id.strip() + "/reviews" 298 data = _issue_get_request(url) 299 if not simplify 300 return data 301 return _simplify_comments(data)
Retrieves a list of Yelp reviews for a particular business.
Arguments:
- business_id (
str): A character string corresponding to the business id. Example:"0b6AU869xq6KXdK3NtVJnw" - simplify (
bool): Indicates whether you want to simplify the data that is returned.
Returns:
a
listof reviews (dictionaries).