2012-03-24 3 views
0

Scraping-Seiten mit BeautifulSoup; "... html # Kommentare"Syntaxfehler - Python re.search (Zeichenklasse, Caret)

-Code folgt versuchen, Links zu filtern, die in Ende:

import urllib.request 
import re 
from bs4 import BeautifulSoup 

base_url = "http://voices.washingtonpost.com/thefix/morning-fix/" 
soup = BeautifulSoup(urllib.request.urlopen(base_url)).findAll('a') 
links_to_follow = [] 
for i in soup: 
     if i.has_key('href') and \ 
    re.search(base_url, i['href']) and \ 
    len(i['href']) > len(base_url) and \ 
    re.search(r'[^(comments)]', i['href']): 
     print(i['href']) 

Python 3.2, Windows 7 64-bit.

Das obige Skript behält

Ich versuchte re.search([^comments], i['href']), re.search([^(comments)], i['href']) und re.search([^'comments'], i['href']) in "#Kommentare" einen Link endet - alle Syntaxfehler warf.

Neu bei Python, also Entschuldigung für Banalität.

Ich vermute, entweder (a) Ich verstehe nicht genug über das ‚r‘ Präfix es richtig zu verwenden oder (b) als Reaktion auf [^ (foo)] re.search nicht zurückgibt von Zeilen, die "foo" ausschließen, aber die Menge von Zeilen, die mehr als nur "foo" umfasst. z. B. halte ich meine ... # comments link weil ... texttexttext.html # comments vor oder (c) Python interpretiert "#" als Kommentar, der die Zeile beendet, die re.search entsprechen soll.

Ich glaube, ich liege falsch (b).

Entschuldigung, das ist einfach. Dank,

Zack

+1

Sie sollten den genauen Text der Fehler/Tracebacks sind Sie bekommen. – Amber

Antwort

2
[^(comments)] 

bedeutet "ein Zeichen, das weder ein, noch ein (c, ein o, ein m, ein e, ein n, ein t, ein s oder ein )". Wahrscheinlich nicht, was Sie vorhatten.

Wenn Ihr Ziel ist es, einen regulären Ausdruck zu haben, die nur übereinstimmt, wenn die bereitgestellte Zeichenfolge in #comments endet nicht, dann würde ich

... and not re.search("#comments$", i['href']) 

oder noch besser nutzen (warum überhaupt einen regulären Ausdruck verwenden, wenn es so einfach ist ?):

... and not i['href'].endswith("#comments") 

Was Ihre anderen Fragen:

Die r'...' Notation ermöglicht es Ihnen, "raw strings", was bedeutet, dass Schrägstriche nicht zu schreiben werden müssen entkommen:

  • r'\b' bedeutet "umgekehrten Schrägstrich + b" (die durch den regulären Ausdruck Motor interpretiert wird als "Wortgrenze"
  • '\b' bedeutet "Backspace Zeichen"
  • usw.

# hat keine besondere Bedeutung in einem regulären Ausdruck, es sei denn, Sie verwenden die Option (?x) oder re.VERBOSE Option. In diesem Fall wird tatsächlich ein Kommentar in einem Multiline-Regex gestartet.

+0

musste wegtreten und gerade jetzt zurück - danke für beide Antworten. – Zack

0

Regex vielleicht nicht die beste Lösung hier:

import urllib.request 
from bs4 import BeautifulSoup 

base_url = "http://voices.washingtonpost.com/thefix/morning-fix/" 
soup = BeautifulSoup(urllib.request.urlopen(base_url)).findAll('a') 
links_to_follow = [] 
for i in soup: 
    href = i.get('href') 
    if href is None: 
     continue 
    if not href.startswith(base_url): 
     continue 
    if href.endswith('#comments'): 
     print href