In [1]:
from yelp.client import Client
from yelp.oauth1_authenticator import Oauth1Authenticator
import io
import json

with io.open('config_yelp.json') as cred:
    creds = json.load(cred)
    auth = Oauth1Authenticator(**creds)
    client = Client(auth)

biz = client.get_business('yelp-san-francisco')

In [8]:
biz = client.get_business('yolk-chicago-8')
biz.business.categories


Out[8]:
[Category(name=u'Breakfast & Brunch', alias=u'breakfast_brunch'),
 Category(name=u'American (Traditional)', alias=u'tradamerican'),
 Category(name=u'Diners', alias=u'diners')]

In [9]:
biz.business.eat24_url

In [17]:
biz.business.reviews[0].excerpt


Out[17]:
u"We aren't breakfast people, but Yolk has us nearly converted. I had the protein & eggs while the husband had Hey Ricky! It was amazing. \n\nPlus, our waiter..."

In [18]:
biz.business.ho


Out[18]:
['__class__',
 '__delattr__',
 '__dict__',
 '__doc__',
 '__format__',
 '__getattribute__',
 '__hash__',
 '__init__',
 '__module__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__setattr__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 '__weakref__',
 '_fields',
 '_parse',
 '_parse_categories',
 '_parse_list_to_objects',
 '_parse_main_response_body',
 '_parse_one_to_object',
 'categories',
 'deals',
 'display_phone',
 'distance',
 'eat24_url',
 'gift_certificates',
 'id',
 'image_url',
 'is_claimed',
 'is_closed',
 'location',
 'menu_date_updated',
 'menu_provider',
 'mobile_url',
 'name',
 'phone',
 'rating',
 'rating_img_url',
 'rating_img_url_large',
 'rating_img_url_small',
 'reservation_url',
 'review_count',
 'reviews',
 'snippet_image_url',
 'snippet_text',
 'url']

In [ ]:
"""Functions to make API call to Yelp for restaurants in a city"""

from model import City, Restaurant
from model import db

from sqlalchemy.orm.exc import NoResultFound

from yelp.client import Client
from yelp.oauth1_authenticator import Oauth1Authenticator

import io
import json


# def get_city_id(city):
#     """Get the city id from database. Otherwise, add city to database and get the city id."""

#     try:
#         existing_city = db.session.query(City).filter(City.name == city).one()

#     except NoResultFound:
#         new_city = City(name=city)
#         db.session.add(new_city)
#         db.session.commit()
#         return new_city.city_id

#     return existing_city.city_id


# Resource for how to offset Yelp API results from http://www.mfumagalli.com/wp/portfolio/nycbars/
def get_restaurants(city, offset):
    """
    Returns API response from Yelp API call to get restaurants for a city, with the results offset.
    Note that Yelp only returns 20 results each time, which is why we need to offset if we want
    the next Nth results.
    """

    # Read Yelp API keys
    with io.open('config_yelp.json') as cred:
        creds = json.load(cred)
        auth = Oauth1Authenticator(**creds)
        client = Client(auth)

    # Set term as restaurant to get restaurants for results
    # Need to pass in offset, so Yelp knows how much to offset by
    params = {
        'term': 'restaurant',
        'offset': offset
    }

    return client.search(city, **params)


def load_restaurants(city):
    """Get all restaurants for a city from Yelp and load restaurants into database."""

    # Get city id, as city id is a required parameter when adding a restaurant to the database
    city_id = get_city_id(city)

    # Start offset at 0 to return the first 20 results from Yelp API request
    offset = 0

    # Get total number of restaurants for this city
    total_results = get_restaurants(city, offset).total

    # Get all restaurants for a city and load each restaurant into the database
    # Note: Yelp has a limitation of 1000 for accessible results, so get total results
    # if less than 1000 or get only 1000 results back even if there should be more
    while 1000 > offset < total_results:

        # API response returns a SearchResponse object with accessible attributes
        # response.businesses returns a list of business objects with further attributes
        for business in get_restaurants(city, offset).businesses:
            restaurant = Restaurant(city_id=city_id,
                                    name=business.name,
                                    address=" ".join(business.location.display_address),
                                    phone=business.display_phone,
                                    image_url=business.image_url,
                                    latitude=business.location.coordinate.latitude,
                                    longitude=business.location.coordinate.longitude)
            db.session.add(restaurant)

        # Yelp returns only 20 results each time, so need to offset by 20 while iterating
        offset += 20

    db.session.commit()

In [3]:
"""Models and database functions."""
import datetime

# from sqlalchemy_searchable import make_searchable
# from sqlalchemy_utils.types import TSVectorType

# This is the connection to the PostgreSQL database; we're getting this through
# the Flask-SQLAlchemy helper library. On this, we can find the `session`
# object, where we do most of our interactions (like committing, etc.)
# db = SQLAlchemy()

from sqlalchemy import Column, ForeignKey, Integer, String
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship
from sqlalchemy import create_engine
 
Base = declarative_base()
 
# make_searchable()


##############################################################################
# Model definitions

# class User(db.Model):
#     """User of website."""

#     __tablename__ = "users"

#     user_id = db.Column(db.Integer, autoincrement=True, primary_key=True)
#     city_id = db.Column(db.Integer, db.ForeignKey('cities.city_id'), nullable=False)
#     email = db.Column(db.String(100), unique=True, nullable=False)
#     password = db.Column(db.String(100), nullable=False)
#     first_name = db.Column(db.String(100), nullable=False)
#     last_name = db.Column(db.String(100), nullable=False)
#     # Put name inside TSVectorType definition for it to be fulltext-indexed (searchable)
#     search_vector = db.Column(TSVectorType('first_name', 'last_name'))

#     city = db.relationship("City", backref=db.backref("users"))

#     def __repr__(self):
#         """Provide helpful representation when printed."""

#         return "<User user_id=%s email=%s>" % (self.user_id,
#                                                self.email)


class Restaurant(Base):
    """Restaurant on website."""

    __tablename__ = "restaurants"

    [u'is_claimed', u'rating', u'review_count', u'name', u'phone', u'url', 
     u'price', u'coordinates', u'hours', u'photos', u'image_url', u'categories', 
     u'display_phone', u'id', u'is_closed', u'location']
    
    restaurant_id = Column(Integer, autoincrement=True, primary_key=True)
    yelp_id = db.Column(db.String(150), nullable=True)
    yelp_rating = db.Column(db.Numeric, nullable=True)
    yelp_review_count = db.Column(db.Integer, nullable=True)
    name = db.Column(db.String(150), nullable=False)
    phone = db.Column(db.String(20), nullable=True)
    yelp_url = db.Column(db.String(200), nullable=True)
    yelp_price_level = db.Column(db.String(10), nullable=True)
    latitude = db.Column(db.Numeric, nullable=True)
    longitude = db.Column(db.Numeric, nullable=True)
    hours_type = db.Column(db.String(20), nullable=True)
    is_open_now = db.Column(db.Boolean(), nullable=True) 
    hour_start_monday = db.Column(db.String(20), nullable=True)
    hour_end_monday = db.Column(db.String(20), nullable=True)
    hour_start_tuesday = db.Column(db.String(20), nullable=True)
    hour_end_tuesday = db.Column(db.String(20), nullable=True)    
    hour_start_wednesday = db.Column(db.String(20), nullable=True)
    hour_end_wednesday = db.Column(db.String(20), nullable=True)    
    hour_start_thursday = db.Column(db.String(20), nullable=True)
    hour_end_thursday = db.Column(db.String(20), nullable=True)    
    hour_start_friday = db.Column(db.String(20), nullable=True)
    hour_end_friday = db.Column(db.String(20), nullable=True)    
    hour_start_saturday = db.Column(db.String(20), nullable=True)
    hour_end_saturday = db.Column(db.String(20), nullable=True)    
    hour_start_sunday = db.Column(db.String(20), nullable=True)
    hour_end_sunday = db.Column(db.String(20), nullable=True)    
    is_closed = db.Column(db.Boolean(), nullable=True) 
    categories = db.Column(db.String(200), nullable=True)
    display_phone = db.Column(db.String(50), nullable=True)
    location = db.Column(db.String(400), nullable=True)
    
    # Latitude and Longitude need to be Numeric, not Integer to have decimal places
    # Put restaurant name and address inside definition of TSVectorType to be fulltext-indexed (searchable)
#     city = db.relationship("City", backref=db.backref("restaurants"))
#     categories = db.relationship("Category", secondary="restaurantcategories", backref="restaurants")
#     users = db.relationship("User", secondary="visits", backref="restaurants")

    def __repr__(self):
        """Provide helpful representation when printed."""

        return "<Restaurant restaurant_id=%s name=%s>" % (self.restaurant_id,
                                                          self.name)


# class Visit(db.Model):
#     """User's visited/saved restaurant on Breadcrumbs website.
#     Association table between User and Restaurant.
#     """

#     __tablename__ = "visits"

#     visit_id = db.Column(db.Integer, autoincrement=True, primary_key=True)
#     user_id = db.Column(db.Integer, db.ForeignKey('users.user_id'), nullable=False)
#     restaurant_id = db.Column(db.Integer, db.ForeignKey('restaurants.restaurant_id'), nullable=False)

#     user = db.relationship("User", backref=db.backref("visits"))
#     restaurant = db.relationship("Restaurant", backref=db.backref("visits"))

#     def __repr__(self):
#         """Provide helpful representation when printed."""

#         return "<Visit visit_id=%s restaurant_id=%s>" % (self.visit_id,
#                                                          self.restaurant_id)


# class City(db.Model):
#     """City where the restaurant is in."""

#     __tablename__ = "cities"

#     city_id = db.Column(db.Integer, autoincrement=True, primary_key=True)
#     name = db.Column(db.String(100), nullable=False)
#     # Set default for timestamp of current time at UTC time zone
#     updated_At = db.Column(db.DateTime, default=datetime.datetime.utcnow)

#     def __repr__(self):
#         """Provide helpful representation when printed."""

#         return "<City city_id=%s name=%s>" % (self.city_id,
#                                               self.name)


# class Category(db.Model):
#     """Category of the restaurant."""

#     __tablename__ = "categories"

#     category_id = db.Column(db.Integer, autoincrement=True, primary_key=True)
#     name = db.Column(db.String(100), unique=True, nullable=False)

#     def __repr__(self):
#         """Provide helpful representation when printed."""

#         return "<Category category_id=%s name=%s>" % (self.category_id,
#                                                       self.name)


# class RestaurantCategory(db.Model):
#     """Association table linking Restaurant and Category to manage the M2M relationship."""

#     __tablename__ = "restaurantcategories"

#     restcat_id = db.Column(db.Integer, autoincrement=True, primary_key=True)
#     restaurant_id = db.Column(db.Integer, db.ForeignKey('restaurants.restaurant_id'), nullable=False)
#     category_id = db.Column(db.Integer, db.ForeignKey('categories.category_id'), nullable=False)

#     def __repr__(self):
#         """Provide helpful representation when printed."""

#         return "<RestaurantCategory restcat_id=%s restaurant_id=%s category_id=%s>" % (self.restcat_id,
#                                                                                        self.restaurant_id,
#                                                                                        self.category_id)


# class Image(db.Model):
#     """Image uploaded by user for each restaurant visit."""

#     __tablename__ = "images"

#     image_id = db.Column(db.Integer, autoincrement=True, primary_key=True)
#     visit_id = db.Column(db.Integer, db.ForeignKey('visits.visit_id'), nullable=False)
#     url = db.Column(db.String(200), nullable=False)
#     uploaded_At = db.Column(db.DateTime, default=datetime.datetime.utcnow)
#     taken_At = db.Column(db.DateTime, nullable=True)
#     rating = db.Column(db.String(100), nullable=True)

#     visit = db.relationship("Visit", backref=db.backref("images"))

#     def __repr__(self):
#         """Provide helpful representation when printed."""

#         return "<Image image_id=%s visit_id=%s>" % (self.image_id,
#                                                     self.visit_id)


# class Connection(db.Model):
#     """Connection between two users to establish a friendship and can see each other's info."""

#     __tablename__ = "connections"

#     connection_id = db.Column(db.Integer, autoincrement=True, primary_key=True)
#     user_a_id = db.Column(db.Integer, db.ForeignKey('users.user_id'), nullable=False)
#     user_b_id = db.Column(db.Integer, db.ForeignKey('users.user_id'), nullable=False)
#     status = db.Column(db.String(100), nullable=False)

#     # When both columns have a relationship with the same table, need to specify how
#     # to handle multiple join paths in the square brackets of foreign_keys per below
#     user_a = db.relationship("User", foreign_keys=[user_a_id], backref=db.backref("sent_connections"))
#     user_b = db.relationship("User", foreign_keys=[user_b_id], backref=db.backref("received_connections"))

#     def __repr__(self):
#         """Provide helpful representation when printed."""

#         return "<Connection connection_id=%s user_a_id=%s user_b_id=%s status=%s>" % (self.connection_id,
#                                                                                       self.user_a_id,
#                                                                                       self.user_b_id,
#                                                                                       self.status)


##############################################################################
# Helper functions

# def connect_to_db(app, db_uri=None):
#     """Connect the database to our Flask app."""

#     # Configure to use our PostgreSQL database
#     app.config['SQLALCHEMY_DATABASE_URI'] = db_uri or 'postgresql:///zoeshrm'
#     app.config['SQLALCHEMY_ECHO'] = True
#     db.app = app
#     db.init_app(app)

def example_data():
    """Create some sample data for testing."""

#     van = City(name="Vancouver")

    chambar = Restaurant(name="Chambar",
                         address="568 Beatty St, Vancouver, BC V6B 2L3",
                         phone="(604) 879-7119",
                         latitude=49.2810018,
                         longitude=-123.1109668)

    miku = Restaurant(name="Miku",
                      address="200 Granville St #70, Vancouver, BC V6C 1S4",
                      phone="(604) 568-3900",
                      latitude=49.2868017,
                      longitude=-123.1131884)

    fable = Restaurant(name="Fable",
                       address="1944 W 4th Ave, Vancouver, BC V6J 1M7",
                       phone="(604) 732-1322",
                       latitude=49.2679389,
                       longitude=-123.2190482)

#     ashley = User(city_id=1,
#                   email="ashley@test.com",
#                   password="ashley",
#                   first_name="Ashley",
#                   last_name="Test")

#     bob = User(city_id=1,
#                email="bob@test.com",
#                password="bob",
#                first_name="Bob",
#                last_name="Test")

#     cat = User(city_id=1,
#                email="cat@test.com",
#                password="cat",
#                first_name="Cat",
#                last_name="Test")

    db.session.add_all([chambar, miku, fable])
    db.session.commit()


if __name__ == "__main__":
    # As a convenience, if we run this module interactively, it will leave
    # you in a state of being able to work with the database directly.

#     from server import app
#     connect_to_db(app)
    print "Connected to DB."


Connected to DB.

In [ ]: