def parse_profile_html(html):
    html = html.lower()
    soup = BeautifulSoup(html, convertEntities=BeautifulSoup.HTML_ENTITIES)
    NA = 'NA'
    basics_soup = soup.find(name = 'div', attrs = {'id': 'basic_info'})
    details_soup = soup.find(name='div', attrs={'id':'profile_details'})
    essays_soup = soup.find(name='div', attrs={'id':'main_column'})
    if not (basics_soup and details_soup and essays_soup):
        print 'Profile likely deleted. Missing expected html structure.'
        return None, None
    profile = {}
    # Extract top-line profile data (age, gender, city) from tags like
    # <span id='ajax_gender'>Female</span>
    for tag in basics_soup.findAll(name = 'span')[1:]:  # Skip 'Last Online'
        feature, value = tag['id'].split('_', 1)[1], tag.text.strip()
        print feature, value
        profile[feature] = value
    # Extract personal data items from tags like
    # <dd id='ajax_bodytype'>Female</span>
    for tag in details_soup.findAll(name = 'dd'):
        try:
            feature, value = tag['id'].split('_', 1)[1], tag.text.strip()
            if feature == 'height':
                # Special case height to parse into inches
                print value
                feet, inches = [int(x[:-1]) for x in value.split()[:2]]
                value = str(int(feet) * 12 + int(inches))
            print feature, value
            profile[feature] = value
        except KeyError:
            continue
    # Essays
    essays = {}
    for e in essays_soup.findAll('div', recursive=False):
        if e['id'].startswith('essay_'):
            essay_id = int(e['id'].split('essay_')[1])
            title = e.a.text
            user_response = ''.join(
                str(x) for x in e.div.div.contents).replace('<br />', '').strip()
            essays[essay_id] = (title, user_response)
        elif e['id'] == 'what_i_want':
            # These are high-level details about what the user wants in a date
            # TODO: parse and incorporate these as profile features
            pass
    return profile, essays
Register an action to be available globally.
dataset/ETHPy150Open everett-wetchler/okcupid/FetchProfiles.py/parse_profile_html--crossover with--dataset/ETHPy150Open AppScale/appscale/AppServer/lib/django-1.3/django/contrib/admin/sites.py/AdminSite.add_action