docs: def run(self):
          """Run loading of movie appearances.
  
          The wiki page structure for this part cannot be easily handled by simple xpath queries.
          We need to iterate over the respective portion of the page and parse appearances.
          """
  
          # make all requests via a cache instance
          request_cache = cache.get_request_cache()
  
          # DB session to operate in
          session = client.get_client().create_session()
  
          # clear completion flag for this task
          self.mark_incomplete()
  
          # list of universes seen in character appearances
          universes = []
  
          # don't auto-flush the session for queries, this causes issues with the 'id' field of newly
          # created MovieAppearance instances
          with session.no_autoflush:
  
              # get all movies
              movies = session.query(models.Movie).all()
  
              # iterate over all movies and build appearance objects
              for movie in movies:
  
                  # retrieve movie article, keep main article content only, parse
                  article = request_cache.get("http://marvel.wikia.com" + movie.url,
                                              xpath="//article[@id='WikiaMainContent']",
                                              rate_limit=0.5)
                  doc = html.fromstring(article)
  
                  # find heading for appearances, this is a span inside an h2; go to the h2
                  node = doc.xpath("//span[@id='Appearances']")[0]
                  node = node.getparent()
  
                  # Appearance type is given by <p><b>... some text ...</b></p> tags. Sometimes the first
                  # group of appearances carries no such label, assume it's the featured characters.
                  appearance_type = "Featured Characters"
  
                  # walk along the tree; character lists are in <ul>s, labels in <p>s;
                  # the next h2 ends the character listing
                  node = node.getnext()
                  while node is not None and node.tag != 'h2':
                      if node.tag == 'ul' and ('characters' in appearance_type.lower() or
                                                       'villains' in appearance_type.lower()):
                          # starts a new list of stuff; only enter here if the previous label was for characters;
                          # use iter() to iterate over all 'li' items (also those of nested lists)
                          for li in node.iter('li'):
                              # inside the list element, find all 'a's; iterate over child nodes, don't use iter(),
                              # since we want don't want to find 'a's of sub-elements in a nested list here
                              for a in li:
                                  if a.tag != 'a':
                                      continue
  
                                  # there are 'a's in the list that wrap imags, don't use these; also don't use
                                  # links that lead to somewhere else than the wiki
                                  if "image" in a.get("class", "") or not a.get("href").startswith("/wiki/"):
                                      continue
  
                                  match = re.search(r'\(.*?\)', a.get('href'))
                                  if match:
                                      universes.append(match.group()[1:-1])
  
                                  # accept the first matching href, build a new appearance object, then skip to next li
                                  try:
                                      character = session.query(models.Character) \
                                          .filter(models.Character.url == a.get("href")) \
                                          .one()
  
                                      # -- start documentation include: many-to-many-generation
                                      appearance = models.MovieAppearance(movie_id=movie.id,
                                                                          character_id=character.id,
                                                                          appearance_type=appearance_type)
                                      session.add(appearance)
                                      # -- end documentation include: many-to-many-generation
  
                                  except NoResultFound:
                                      # none found, ignore
                                      pass
  
                                  # break looping over 'a's once we have found one, go to next 'li'
                                  break
  
                      elif node.tag == 'p':
                          # new character class (or label for locations, items, ...)
                          appearance_type = " ".join(node.itertext()).strip().strip(':').strip()
                      node = node.getnext()
  
          print("\nNumber of character appearances per universe: ")
          print(pd.Series(data=universes).value_counts())
  
          # done, save all data, finalize task
          session.commit()
          session.close()
          self.mark_complete()