def parse(self, user_page):
    """Parses the DOM and returns user attributes in the main-content area.

    :type user_page: :class:`bs4.BeautifulSoup`
    :param user_page: MAL user page's DOM

    :rtype: dict
    :return: User attributes.

    """
    user_info = self.parse_sidebar(user_page)

    section_headings = user_page.find_all(u'div', {u'class': u'normal_header'})

    # parse general details.
    # we have to work from the bottom up, since there's broken HTML after every header.
    last_online_elt = user_page.find(u'td', text=u'Last Online')
    if last_online_elt:
      try:
        general_table = last_online_elt.parent.parent
      except:
        if not self.session.suppress_parse_exceptions:
          raise

      if general_table and general_table.name == u'table':
        try:
          last_online_elt = general_table.find(u'td', text=u'Last Online')
          if last_online_elt:
            user_info[u'last_online'] = utilities.parse_profile_date(last_online_elt.findNext(u'td').text)
        except:
          if not self.session.suppress_parse_exceptions:
            raise

        try:
          gender = general_table.find(u'td', text=u'Gender')
          if gender:
            user_info[u'gender'] = gender.findNext(u'td').text
        except:
          if not self.session.suppress_parse_exceptions:
            raise

        try:
          birthday = general_table.find(u'td', text=u'Birthday')
          if birthday:
            user_info[u'birthday'] = utilities.parse_profile_date(birthday.findNext(u'td').text)
        except:
          if not self.session.suppress_parse_exceptions:
            raise

        try:
          location = general_table.find(u'td', text=u'Location')
          if location:
            user_info[u'location'] = location.findNext(u'td').text
        except:
          if not self.session.suppress_parse_exceptions:
            raise

        try:
          website = general_table.find(u'td', text=u'Website')
          if website:
            user_info[u'website'] = website.findNext(u'td').text
        except:
          if not self.session.suppress_parse_exceptions:
            raise

        try:
          join_date = general_table.find(u'td', text=u'Join Date')
          if join_date:
            user_info[u'join_date'] = utilities.parse_profile_date(join_date.findNext(u'td').text)
        except:
          if not self.session.suppress_parse_exceptions:
            raise

        try:
          access_rank = general_table.find(u'td', text=u'Access Rank')
          if access_rank:
            user_info[u'access_rank'] = access_rank.findNext(u'td').text
        except:
          if not self.session.suppress_parse_exceptions:
            raise

        try:
          anime_list_views = general_table.find(u'td', text=u'Anime List Views')
          if anime_list_views:
            user_info[u'anime_list_views'] = int(anime_list_views.findNext(u'td').text.replace(',', ''))
        except:
          if not self.session.suppress_parse_exceptions:
            raise

        try:
          manga_list_views = general_table.find(u'td', text=u'Manga List Views')
          if manga_list_views:
            user_info[u'manga_list_views'] = int(manga_list_views.findNext(u'td').text.replace(',', ''))
        except:
          if not self.session.suppress_parse_exceptions:
            raise

        try:
          num_comments = general_table.find(u'td', text=u'Comments')
          if num_comments:
            user_info[u'num_comments'] = int(num_comments.findNext(u'td').text.replace(',', ''))
        except:
          if not self.session.suppress_parse_exceptions:
            raise

        try:
          num_forum_posts = general_table.find(u'td', text=u'Forum Posts')
          if num_forum_posts:
            user_info[u'num_forum_posts'] = int(num_forum_posts.findNext(u'td').text.replace(" (Find All)", "").replace(',', ''))
        except:
          if not self.session.suppress_parse_exceptions:
            raise

    try:
      # last list updates.
      list_updates_header = filter(lambda x: u'Last List Updates' in x.text, section_headings)
      if list_updates_header:
        list_updates_header = list_updates_header[0]
        list_updates_table = list_updates_header.findNext(u'table')
        if list_updates_table:
          user_info[u'last_list_updates'] = {}
          for row in list_updates_table.find_all(u'tr'):
            cols = row.find_all(u'td')
            info_col = cols[1]
            media_link = info_col.find(u'a')
            link_parts = media_link.get(u'href').split(u'/')
            # of the form /(anime|manga)/10087/Fate/Zero
            if link_parts[1] == u'anime':
              media = self.session.anime(int(link_parts[2])).set({u'title': media_link.text})
            else:
              media = self.session.manga(int(link_parts[2])).set({u'title': media_link.text})
            list_update = {}
            progress_div = info_col.find(u'div', {u'class': u'spaceit_pad'})
            if progress_div:
              progress_match = re.match(r'(?P<status>[A-Za-z]+)(  at (?P<episodes>[0-9]+) of (?P<total_episodes>[0-9]+))?', progress_div.text).groupdict()
              list_update[u'status'] = progress_match[u'status']
              if progress_match[u'episodes'] is None:
                list_update[u'episodes'] = None
              else:
                list_update[u'episodes'] = int(progress_match[u'episodes'])
              if progress_match[u'total_episodes'] is None:
                list_update[u'total_episodes'] = None
              else:
                list_update[u'total_episodes'] = int(progress_match[u'total_episodes'])
            time_div = info_col.find(u'div', {u'class': u'lightLink'})
            if time_div:
              list_update[u'time'] = utilities.parse_profile_date(time_div.text)
            user_info[u'last_list_updates'][media] = list_update
    except:
      if not self.session.suppress_parse_exceptions:
        raise

    lower_section_headings = user_page.find_all(u'h2')
    # anime stats.
    try:
      anime_stats_header = filter(lambda x: u'Anime Stats' in x.text, lower_section_headings)
      if anime_stats_header:
        anime_stats_header = anime_stats_header[0]
        anime_stats_table = anime_stats_header.findNext(u'table')
        if anime_stats_table:
          user_info[u'anime_stats'] = {}
          for row in anime_stats_table.find_all(u'tr'):
            cols = row.find_all(u'td')
            value = cols[1].text
            if cols[1].find(u'span', {u'title': u'Days'}):
              value = round(float(value), 1)
            else:
              value = int(value)
            user_info[u'anime_stats'][cols[0].text] = value
    except:
      if not self.session.suppress_parse_exceptions:
        raise

    try:
      # manga stats.
      manga_stats_header = filter(lambda x: u'Manga Stats' in x.text, lower_section_headings)
      if manga_stats_header:
        manga_stats_header = manga_stats_header[0]
        manga_stats_table = manga_stats_header.findNext(u'table')
        if manga_stats_table:
          user_info[u'manga_stats'] = {}
          for row in manga_stats_table.find_all(u'tr'):
            cols = row.find_all(u'td')
            value = cols[1].text
            if cols[1].find(u'span', {u'title': u'Days'}):
              value = round(float(value), 1)
            else:
              value = int(value)
            user_info[u'manga_stats'][cols[0].text] = value
    except:
      if not self.session.suppress_parse_exceptions:
        raise

    try:
      about_header = filter(lambda x: u'About' in x.text, section_headings)
      if about_header:
        about_header = about_header[0]
        user_info[u'about'] = about_header.findNext(u'div').text.strip()
    except:
      if not self.session.suppress_parse_exceptions:
        raise

    return user_info