2010-11-22 16 views
2

Web siteleri kazımak için bazı Python kodları yazıyorum ve neyle sonuçlanacağım, her biri yaklaşık 50'den fazla özel kazıyıcı koleksiyonudur. satırlar uzun ve özel bir web sitesinden özel bilgileri ayıklamak.Birbirinden büyük farklılıklar gösteren, ancak benzer şekilde işlenen işlevler için desen ve tasarım

Programın ilk yinelemesi, bir web sitesini bir argüman olarak alan devasa bir dosyadır ve bu web sitesini tanıyıp tanıtan özel bir kod içeriyorsa (web sitesini tanıyıp tanımadığını görmek için devasa bir durum bildirimi kullanarak) .

Açıkçası, bu harika bir tasarım değil, bu yüzden yapmak istediğim özel kazıma işlevlerini kendi dosyalarına/sınıflarına çekmek ve adlarına göre adlandırmak için kullanabileceğim küçük bir betiğe sahip olmak. Örneğin:

scrape.py --site google 

Ve benzer bir dosya yapısına sahip istiyorum: Henüz ben uzmanlaşamadım

scrape.py 
sites/ 
    google.py 
    yahoo.py 
    ... 
    bing.py 

nesne yönelimi, ama bu onun için seslendiğini olduğunu fark, ve aradığım şey muhtemelen ortak bir OO modeli.

Bu kodun alınmasıyla ilgili herhangi bir yardım doğru şekilde yeniden oluşturuldu mu?

PS - Scrapy'ye baktım ve çeşitli nedenlerden dolayı ihtiyacım olan şey bu değil.
PPS - Aslında arama web sitelerini kazıyorum, ABD mahkeme web sitelerini kazıyorum.

cevap

4

herşey yapılandırılmış almak için

from sites import scrapers 
all_scrapers = {} 
...... 
# Load all scrapers 
for scraper_name in scrapers: 
    all_scrapers[scraper_name] = __import__('%s.%s' % (sites.__name__, scraper_name), fromlist=[scraper_name], level=0) 
# get the input on what to scrape via command line etc 
scraper_name = .. 
assert scraper_name not in scrapers 
# call the function based on name 
scrapeHandler = all_scrapers.get(scraper_name, None) 
if scrapeHandler is not None: 
    scrapeHandler(....) 
, bir _download yöntem sitesine bağlanmak ve indirmek için , sonuçları kaydetmek için _store yöntemi ve bir run yöntem kravat Hep birlikte, şöyle:

class Scraper(object): 
    def __init__(self, parser, page_generator): 
     self._parser = parser 
     self._pages = pages 

    def _download(self, page): 
     # do whatever you're already doing to download it 
     return html 

    def _store(self, data): 
     # Do whatever you're already doing to store the data 

    def run(self): 
     for page in pages: 
      html = self._download(page) 
      data = self._parser.parse(html) 
      self._store(data) 

Bu sınıf parser.py dosyada yaşayabilir.

Sitenize özgü dosyalardan her birinde iki şey koyun.

class Parser(object): 
    def parse(html): 
     # All of your rules go here 

def pages(some, args, if_, you, need, them): # but they should be the same for all files 
    return a_list_of_pages_or_generator 

Sonra aşağıdaki fonksiyonu ile python.py dosyayı ayarlayabilirsiniz:

def get_scraper(name): 
    mod = __import__(name) 

    parser = mod.Parser() 
    pages = mod.pages() # Pass whatever args you need to figure out the urls 

    return Scraper(parser, pages) 

Ardından

scraper = get_scraper('google') 
scraper.run() 

bu şekilde yapmak gibi kullanabilirsiniz gerektirmeyen bir avantaja sahiptir Scraper sınıfında herhangi bir değişiklik yapmanız gerekir. Sunucuları kazıyıcınız ile konuşmak için farklı numaralar yapmanız gerekiyorsa, her modülde Downloader sınıfı oluşturabilir ve Parser sınıfı gibi kullanabilirsiniz. Aynı şeyi yapan iki veya daha fazla ayrıştırıcınız varsa, bunları ayrı bir modülde genel bir ayrıştırıcı olarak tanımlayın ve bunu gerektiren her sitenin modülüne içe aktarın. Ya da tweaks yapmak için alt sınıf. Siteleri nasıl indirip ayrıştırdığınızı bilmeden, daha spesifik olmak zordur.

Duygularım, tüm detayların ütülenmesi için birkaç soru sormanız gerekebileceğidir, ancak iyi bir öğrenme deneyimi olacaktır.

+0

Nihayetinde, [Juriscraper] (https://bitbucket.org/mlissner/juriscraper/) kütüphanesini oluşturmak için buradaki cevapların ikisini de kullandım, ancak daha fazla ödünç aldım. Gerçekten yararlı şeyler, teşekkürler! – mlissner

1

Refactoring tekniğiniz nasıl gidiyor? İşte, bu sorunu nasıl uygulamaya bakacağım.

İlk

ben site dizinine içindeki tüm dosyaları ScrapeHandler adlı tek işlevi yaratacak

- google.py, yahoo.py vb

def ScrapeHandler(...): 
    ... 

İkinci

Aşağıdaki içeriğe sahip bir site dizininde __init__.py oluşturabilirim. Ana dosya scrape.py olarak

Üçüncü

scrapers = ["google", "yahoo", ...] 

, ben uygun kazıma mantığı seçme zamanında kazıyıcı yüklemek istiyorum.

Bir __init__ yöntemle bir sınıfta kodu koyabilirsiniz
+0

İşleyici için, yaptığım modülde __all__ değişkeni üzerinde yinelemeyi bitirdim, ama evet, burada iyi şeyler. Teşekkür ederim! – mlissner