docs: def find_repo_urls(session, name, candidates):
      """
      Visits the given URL candidates and searches the page for valid links to a repository.
      :param session: requests Session instance
      :param name: str, project name
      :param candidates: list, list of URL candidates
      :return: str, URL to a repo
      """
      for _url in candidates:
          if validate_url(_url):
              try:
                  resp = session.get(_url)
                  if resp.status_code == 200:
                      tree = etree.HTML(resp.content)
                      if tree:
                          for link in frozenset([str(l) for l in tree.xpath("//a/@href")]):
                              # check if the link 1) is to github.com / bitbucket.org AND 2) somewhat
                              # contains the project name
                              if ("github.com" in link or "bitbucket.org" in link or
                                      "sourceforge.net" in link) \
                                      and contains_project_name(name, link):
                                  link = validate_url(validate_repo_url(url=link))
                                  if link:
                                      logger.debug("Found repo URL {}".format(link))
                                      yield link
              except ConnectionError:
                  # we really don't care about connection errors here. a lot of project pages are simply
                  # down because the project is no longer maintained
                  pass
              except etree.XMLSyntaxError:
                  # unable to parse HTML
                  pass
              except UnicodeEncodeError:
                  pass