links aus einer liste besuchen und ziel scrapen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Benutzeravatar
bitbum
User
Beiträge: 9
Registriert: Mittwoch 5. September 2012, 10:40

hi community,

ich habe mich (nach meinem letzten) mal wieder an einem neuen wörter-scraper versucht und scheitere momentan an meinem vorhaben.

das ist der relevante codeteil:

Code: Alles auswählen

#!/usr/bin/python

import mechanize
import urllib2
import re
from bs4 import BeautifulSoup

# I am doing a lot of not so plausible stuff, i better pretend to be a browser
browser = mechanize.Browser()
#cookie jar
cookies = cookielib.MozillaCookieJar('cookie_jar')
# set up the emulated browser
browser.set_cookiejar(cookies)
browser.set_handle_redirect(True)
browser.set_handle_robots(False)
browser.set_handle_equiv(True)
browser.set_handle_gzip(False)
browser.set_handle_referer(True)
browser.set_handle_refresh(mechanize._http.HTTPRefreshProcessor(), max_time=1)
browser.addheaders = [('User-Agent', 'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:14.0) Gecko/20120405 Firefox/14.0a1')]

# prep my lists
urls = []
wordlist = []

#prep containers
alltextinsoup = open('wordlist.txt', 'w')
urlsfile = open('links.txt', 'w')

# cook the initial soup
target = raw_input("enter target to scrape for words_> ")
r = browser.open("http://%s"%target)
html = r.read()
soup = BeautifulSoup(html)

# find all links in initial soup
for eachlink in soup.findAll('a'):
	urls.append(eachlink.get('href'))

for link in urls:
        # cook a soup for every links content
	r = browser.open(link)
	html = r.read()
	soup = BeautifulSoup(html)
	rawtext = (soup.get_text()).encode('utf-8', 'ignore')
        # i just want the clean words
	rawtext = re.sub('[^A-Za-z ]+', '', rawtext)
	splittedrawtext = rawtext.split(' ')
	for x in splittedrawtext:
		if x not in wordlist and (len(x) > 3 and len(x) < 12):
			wordlist.append(x.encode('utf-8'))
			for item in wordlist:
				alltextinsoup.write(str(item) + '\n')	
	
################################	
alltextinsoup.close()
also der code soll eine webseite nach links durchforsten, allen links folgen und von jeder verlinkten webseite alle gefilterten wörter in eine liste packen und von dort aus in eine text schreiben.
problem.. es funzt nicht und ich verstehe nicht warum. jedes mal wenn ich etwas korrigiere kommen nur mehr fehler dazu :(
theoretisch müsste er doch gehen. *amkopfkratz*

ich bin sehr dankbar für jeden tipp

p.s. ich bin erst seit kurzen am python coden. ich bitte um nachsicht.
Sirius3
User
Beiträge: 18335
Registriert: Sonntag 21. Oktober 2012, 17:20

Hallo Bitbum,

an welcher Stelle treten Fehler auf?
Sind es Runtime-Errors oder endspricht das Ergebnis nicht Deinen Erwartungen?

Prinzipiell ist es immer besser, das Programm in einzelne Abschnitte einzuteilen,
diese in Funktionen auszulagern und die Funktionen darauf zu testen, dass sie
das gewünschte tun.

Da ich nicht weiß welche Fehler auftreten, kann ich nur ein paar Problemstellen
nennen:
1) re.sub entfernt alles außer Buchstaben. Wie sieht es mit Umlauten aus, was ist
mit Wörtern die nicht durch Leerzeichen getrennt werden, wie Zeilenumbrüchen,
Klammern, Bindestriche, etc?
2) split() ohne Argument trennt nach allen Leerräumen, nicht nur einzelne Leerzeichen
3) x ist schon utf-8 kodiert, ein weiteres encode unsinnig
4) Du schreibst jedes mal die komplette Wortliste in die Datei, wenn ein neues
Wort gefunden wurde. Das Rausschreiben sollte nach der for-link-Schleife erfolgen.

Grüße
Sirius
Benutzeravatar
bitbum
User
Beiträge: 9
Registriert: Mittwoch 5. September 2012, 10:40

Hi Sirius3

danke für deine antwort.
ich glaube ich habe die ungefähre fehlerquelle gefunden. es ist ein mechanize fehler "wrapper fehler 404 not found"
ich glaube weil öfters mal so was unter den links in der liste ist "/dienste/a-637773.html" und kein http:// kann der code dem link nicht folgen.

1) ja, dass re.sub die umlaute rausfischt ist gewollt. kannst du mir sagen wie ich das ganze wort rausfiltere sofern es eine Ö,Ü oder Ä in sich hat? hab
das auch ewig probiert ohne erfolg.
2) edit: ist geändert!
3) hast recht! ist enfernt :)
4) danke für den hinweis. da hab ich wohl kopfverwirrung gehabt.

falls du noch einen tipp hast wie ich das problem mit den unbrauchbaren links lösen kannst bin ich ebenfalls dankbar. ansonsten werd ich das irgendwie mit
einem mix aus if 'http://' in link lösen. aber die nacht ist ja noch jung ^^

danke für deine hilfe.
Sirius3
User
Beiträge: 18335
Registriert: Sonntag 21. Oktober 2012, 17:20

Hallo Bitbum,

relative Pfade solltest Du mit urljoin in absolute URLs umwandeln:

Code: Alles auswählen

url=urlparse.urljoin(absurl,relurl)
Wörter mit Umlauten rauszufiltern würde noch relative einfach gehen -- re.sub('\w*([äöü]\w*)+',' ',text)
aber es gibt ja auch noch eine vielzahl anderer Buchstaben mit Akzent.

Grüße
Sirius
Benutzeravatar
bitbum
User
Beiträge: 9
Registriert: Mittwoch 5. September 2012, 10:40

Danke nochmals Sirius :)

das re.sub hat mir jedoch immernoch die wörter mit umlauten übergeben.
ich bin mittlerweile auf:

Code: Alles auswählen

re.findall(r"(?:\s|^)(\w+)(?=\s|$)", rawtext)
umgestiegen. du hast mich da auf die richtige fährte gebracht.

urlsparse war auch ein toller tip. der fertige code sieht an der stelle so aus (vielleicht hilft es mal leuten die irgendwann den thread lesen):

Code: Alles auswählen

for eachlink in soup.findAll('a', href=True):
    eachlink['href'] = urlparse.urljoin(target, eachlink['href'])
    if eachlink not in linklist:
        linklist.append(eachlink['href'])
ich bin fleißig am weitercoden :) werde das ergebnis oder weitere fagen dann hier posten.

danke nochmals.
Antworten