2015-03-06 2 views
0

J'utilise BeautifulSoup4 dans Python2.7 pour essayer de trouver tous les liens uniques dans un corps HTML.Python Beautifulsoup trouver des liens uniques

Donc, si le corps HTML a 3 du même lien, utilisez-en seulement un.

Mon code ressemble à ceci:

def extract_links_from_content(self): 
    content = "%s %s" % (self.html_body, self.plaintext) 
    url_regex = 'http[s]?://(?:[a-zA-Z]|[0-9]|[[email protected]&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+' 
    links = [] 

    soup = BeautifulSoup(content, "html5lib") 

    for link in soup.findAll('a'): 
     if not link.get('no_track'): 
      target = link.get('href') 
      name = link.get('data-name') 
      link_text = unicode(link) 

      # If there is no target or a mailto link 
      # skip it, cause we can't track whats not there or an email link 
      if not target or target.startswith('mailto') or '{' in target: 
       continue 

      # If the target is a bookmark, skip it 
      if target.startswith('#'): 
       continue 

      target = re.search(url_regex, target) 

      if target: 
       links.append({ 
        'name': name, 
        'target': target.group() 
       }) 

    return links 
+1

Alors, quelle est exactement votre question? –

Répondre

1

Vous pouvez réellement combiner tous les contrôles en fonction et de transmettre cette fonction en tant que valeur d'argument mot-clé href-find_all(). On dirait plus propre et plus lisible:

import re 

from bs4 import BeautifulSoup 

def filter_links(link): 
    href = link and link.get('href') 

    return all([ 
     link, 
     link.name == 'a', 
     href, 
     not link.has_attr('no_track'), 
     not href.startswith('mailto'), 
     '{' not in target, 
     not href.startswith('#') 
    ]) 

content = "%s %s" % (self.html_body, self.plaintext) 
pattern = re.compile(r'http[s]?://(?:[a-zA-Z]|[0-9]|[[email protected]&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+') 

soup = BeautifulSoup(content, "html5lib") 

links = [] 
for link in soup.find_all(filter_links): 
    target = link['href'] 
    name = link.get('data-name') 

    target = pattern.search(target) 
    if target: 
     links.add({ 
      'name': name, 
      'target': target.group() 
     }) 

Pour éviter des liens en double, vous pouvez faire un ensemble de la liste links. Pour que cela fonctionne, vous devez stocker tuples au lieu de dictionnaires:

links.add((name, target.group())) 
+0

Voici mon code mis à jour: https://gist.github.com/dennismonsewicz/a1bba896d014ea1d49b8 mais je reçois maintenant l'erreur «objet unicode» n'a pas d'attribut «get» – dennismonsewicz

+0

@dennismonsewicz fixe, s'il vous plaît essayez à nouveau. – alecxe

+0

@alexce Comment puis-je faire un ensemble de la liste des liens pour éviter les dupes? – dennismonsewicz