Seite 1 von 1

mechanize links()

Verfasst: Dienstag 5. August 2008, 13:39
von Crazed
Hallo,
Eventuell kennst sich hier ja jemand besser mit mechanize als ich aus aber ich probiere momentan eine Website nach bild-urls zu durchsuchen, sprich:

*.jpg, *.png, *.gif etc.

Das wollte ich mit mechanize machen:

Code: Alles auswählen

...

for link in browser.links():
    print link.url

Jetzt ist mir aber aufgefallen das links() nur wirkliche Links zurück gibt, also Links die auf andere HTML Dokumente bzw. Webserver verlinken.

Gibt es da einen Trick wie ich möglichst einfach an die komme?

EDIT: Tut mir Leid habe mich vertan, aber es gibt immer noch falsche Links zurück:

Code: Alles auswählen

#!/usr/bin/python

import mechanize

class Grabber(object):
    def __init__(self, url):
        self.browser = mechanize.Browser()
        self.browser.set_handle_gzip(True)
        self.browser.set_handle_robots(False)
        self.url = url                
        
    def _get_links(self):
        self.browser.open(self.url)
        links = []
        for link in self.browser.links():
            links.append(link)
        return links
    
    def _filter_links(self, links, types):
        filtered = []
        for link in links:
            for type in types:
                if link.url.endswith(type):
                    if not filtered.count(link):
                        filtered.append(link)
        return filtered
    
x = Grabber('http://crackpod.bplaced.net')
links = x._get_links()
for link in x._filter_links(links, 'png'):
    print link.url

MfG,
CracKPod

Verfasst: Dienstag 5. August 2008, 14:00
von BlackJack
Kleiner Tip: Du bekommst alle die mit 'p', 'n', oder 'g' enden.

Verfasst: Dienstag 5. August 2008, 14:23
von Crazed
Vielen Dank BlackJack:

So klappt es übrigens einigermaßen schnell und gut:

Code: Alles auswählen

#!/usr/bin/python

import mechanize
import BeautifulSoup

class Grabber(object):
    def __init__(self, url):
        self.browser = mechanize.Browser()
        self.browser.set_handle_gzip(True)
        self.browser.set_handle_robots(False)
        self.url = url
        
    def _get_links(self, types):
        soup = BeautifulSoup.BeautifulSoup(self.browser.open(self.url))
        links = []
        for link in self.browser.links():
            links.append(link.url)
        for img in soup.findAll('img'):
            links.append(img['src'])
        return self._filter_links(links, types)
    
    def _filter_links(self, links, types):
        filtered = []
        for link in links:
            for type in types:
                if link.endswith(type):
                    if not filtered.count(link):
                        filtered.append(link)
        return filtered
    
x = Grabber('http://crackpod.bplaced.net/')
for link in x._get_links(['.png', '.gif', '.jpg', 'jpeg']):
    print link
Output:

Verfasst: Dienstag 5. August 2008, 17:44
von BlackJack
Die beiden Methoden lassen sich kürzer schreiben und insbesondere bei der `_filter_links()` sollte man auf ein `set()` statt einer Liste zurückgreifen:

Code: Alles auswählen

    def _get_links(self, types): 
        soup = BeautifulSoup.BeautifulSoup(self.browser.open(self.url)) 
        links = [link.url for link in self.browser.links()]
        links.extend(img['src'] for img in soup('img'))
        return self._filter_links(links, types) 
    
    @staticmethod
    def _filter_links(links, types): 
        return set(link for link in links
                   if any(link.endswith(t) for t in types))

Verfasst: Dienstag 5. August 2008, 18:05
von Crazed
Wofür ist das @StaticMethod? Kenne ich gar nicht.

Code: Alles auswählen

links.extend(img['src'] for img in soup('img'))
Und musst da nicht stehen soup.findAll('img')?

Und warum ein set? Eine liste eigenet sich doch vervorragend, oder nicht?
Omg und das "any" keyword kannte ich auch auch gar nicht...

Könntest du mich ein bisschen aufklären?

Verfasst: Dienstag 5. August 2008, 18:22
von BlackJack
`staticmethod()` ist eine Funktion um Funktionen in Klassen unter zu bringen. Du brauchst das Objekt als erstes Argument hier ja gar nicht, dann sollte man die "Methode" entweder aus der Klasse heraus nehmen, oder als "statische Methode" einbauen.

`BeatifulSoup` hat die `__call__()`-Methode implementiert und die verhält sich wie `findAll(), darum kann man Exemplare aufrufen.

`set()` statt Liste, weil Du jede URL ja nur *einmal* haben willst. Und das mit dem `set()` ist wesemtlich effizienter als die lineare Suche, die Du mit der Liste veranstaltet hast.

`any()` ist kein Schlüsselwort, sondern eine Funktion.

Verfasst: Dienstag 5. August 2008, 18:51
von Crazed
Dankeschön.

1.Also static immer dann benutzen wenn man nicht auf den Objekt namespace in den Methoden/Funktion innerhalb einer Klasse zugreifen muss.

2. Verstanden. Das ist eine sogenannten "Magische Methode", oder? Man hookt/überschreibt einfach mehr oder weniger __call__()

3.set hmm ok. Das schlage ich nochmal

4. auch..

Danke

Verfasst: Montag 11. August 2008, 12:08
von Leonidas
Crazed hat geschrieben:2. Verstanden. Das ist eine sogenannten "Magische Methode", oder? Man hookt/überschreibt einfach mehr oder weniger __call__()
Ja, wenn man ein Objekt aufruft, wie eine Funktion dann wird ``__call__`` aurfgerufen, somit kann man die Funktionsweise von einfachen Funktionen nachbauen.