mechanize links()

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
Antworten
Crazed
User
Beiträge: 171
Registriert: Sonntag 18. Mai 2008, 11:44

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
BlackJack

Kleiner Tip: Du bekommst alle die mit 'p', 'n', oder 'g' enden.
Crazed
User
Beiträge: 171
Registriert: Sonntag 18. Mai 2008, 11:44

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:
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))
Crazed
User
Beiträge: 171
Registriert: Sonntag 18. Mai 2008, 11:44

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?
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.
Crazed
User
Beiträge: 171
Registriert: Sonntag 18. Mai 2008, 11:44

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
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

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.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Antworten