Bir web sitesinden veri toplamanın en iyi yolu nedir? [kapalı]


107

Bir web sitesinden içerik çıkarmam gerekiyor, ancak uygulama bu verilere programlı olarak erişmek için herhangi bir uygulama programlama arayüzü veya başka bir mekanizma sağlamıyor.

Import.io adında , web sayfalarını kazımak ve veri kümeleri oluşturmak için tıkla ve git işlevi sağlayan kullanışlı bir üçüncü taraf araç buldum , tek şey verilerimi yerel olarak tutmak ve herhangi bir abonelik planına abone olmak istemiyorum .

Bu şirket web sayfalarını kazımak ve veri setlerini oluşturmak için ne tür bir teknik kullanıyor? Bazı web kazıma çerçeveleri buldum pjscrape & Scrapy böyle bir özellik sağlayabilir mi?


4
PHP kesinlikle söz konusu değildir, bu açıkça yanlıştır. gist.github.com/krakjoe/b1526fcc828621e840cb
Joe Watkins

Gerçekten harika görünen @JoeWatkins, çalışması için özel bir PHP yapılandırmasına ihtiyaç var mı? Ve performans, aşağıda sağlanan araçlar / dillerle karşılaştırıldığında nasıldır?
0x1ad2

1
PHP'nin iş parçacığı için güvenli bir derlemesini gerektirir ve pthreads, github.com/krakjoe/pthreads/blob/master/README.md'yi okuyun , yardım istiyorsanız beni sohbette bulabilirsiniz, ben veya başka biri :)
Joe Watkins

@ 0x1ad2 Verileri yerel olarak tutmak istiyorsanız, Web API'leri yerine yazılımı ( datascraping.co ) denemelisiniz . Araçların çoğu, web sitelerinden veri ayıklamak için Xpath, CSS seçici ve REGEX kullanır ve Data Scraping Studio tüm bu 3 özelliği destekler.
Vikash Rathee

İki yol var, bunlardan biri, çok fazla çaba gerektiren ücretsiz / açık kaynak kitaplıkları kullanarak kendi başlığınızı yaymaktır. Scrape.it kullanarak herhangi bir site için kelimenin tam anlamıyla bir ajax web tarayıcısı oluşturabilirsiniz. Ücretli bir araçtır, ancak import.io veya kimono gibi ücretsiz araçlar görüntülenemediğinde çalıştı.
I Love Python

Yanıtlar:


271

Kesinlikle iyi bir web kazıma çerçevesi ile başlamak isteyeceksiniz. Daha sonra çok sınırlayıcı olduklarına karar verebilirsiniz ve kendi kitaplık yığınınızı bir araya getirebilirsiniz, ancak çok fazla kazıma deneyimi olmadan tasarımınız pjscrape veya scrapy'den çok daha kötü olacaktır.

Not: Burada gezinme ve kazıma terimlerini temelde birbirinin yerine kullanıyorum. Bu, Quora sorunuza verdiğim cevabın bir kopyası, oldukça uzun.

Araçlar

Tercih ettiğiniz tarayıcıya bağlı olarak Firebug veya Chrome geliştirme araçlarını iyice öğrenin. Verileri aldığınız siteye göz atarken ve aradığınız verileri hangi url'lerin içerdiğini ve hangi veri formatlarının yanıtları oluşturduğunu belirlerken bu kesinlikle gerekli olacaktır.

HTML'nin yanı sıra HTTP hakkında iyi bir çalışma bilgisine ihtiyacınız olacak ve muhtemelen orta proxy yazılımında iyi bir insan parçası bulmak isteyeceksiniz. HTTP isteklerini ve yanıtlarını inceleyebilmeniz ve tanımlama bilgilerinin, oturum bilgilerinin ve sorgu parametrelerinin nasıl aktarıldığını anlamanız gerekecektir. Fiddler ( http://www.telerik.com/fiddler ) ve Charles Proxy ( http://www.charlesproxy.com/ ) popüler araçlardır. Bir fareden çok klavyeci olduğum için mitmproxy ( http://mitmproxy.org/ ) kullanıyorum .

Anında geri bildirim ile çeşitli kod parçalarını deneyebileceğiniz bir tür konsol / kabuk / REPL tipi ortam paha biçilmez olacaktır. Bunun gibi tersine mühendislik görevleri çok fazla deneme yanılma gerektirdiğinden, bunu kolaylaştıran bir iş akışı isteyeceksiniz.

Dil

PHP temelde çıktı, bu görev için pek uygun değil ve bu alanda kütüphane / çerçeve desteği zayıf. Python (Scrapy harika bir başlangıç ​​noktasıdır) ve Clojure / Clojurescript (inanılmaz derecede güçlü ve üretken ancak büyük bir öğrenme eğrisi) bu problem için harika dillerdir. Yeni bir dil öğrenmek istemediğiniz ve zaten Javascript bildiğiniz için JS'ye bağlı kalmanızı kesinlikle öneririm. Pjscrape kullanmadım ama belgelerini hızlıca okuduktan sonra oldukça iyi görünüyor. Çok uygundur ve aşağıda anlattığım soruna mükemmel bir çözüm sunar.

Normal ifadeler hakkında bir not: HTML'yi PARSE ETMEK İÇİN NORMAL İFADELER KULLANMAYIN. Yeni başlayanların çoğu, normal ifadelere aşina oldukları için bunu yapar. Bu büyük bir hata, html'de gezinmek için xpath veya css seçicilerini kullanın ve html düğümü içindeki gerçek metinden verileri çıkarmak için yalnızca normal ifadeleri kullanın. Bu sizin için zaten aşikar olabilir, denerseniz çabucak aşikar hale gelir, ancak birçok insan nedense bu yolda giderken çok zaman harcıyor. Xpath veya css seçicilerinden korkmayın, bunlar normal ifadelerden ÇOK daha kolay öğrenilir ve bu sorunu çözmek için tasarlandılar.

Javascript ağırlıklı siteler

Eskiden bir http talebinde bulunmanız ve HTML yanıtını çözümlemeniz gerekiyordu. Artık, hedef sitenin javascript bölümü tarafından yapılan standart HTML HTTP istek / yanıtları ve eşzamansız HTTP çağrılarının bir karışımı olan sitelerle neredeyse kesinlikle uğraşmanız gerekecektir. Proxy yazılımınızın ve firebug / devtools'un ağ sekmesinin çok kullanışlı olduğu yer burasıdır. Bunlara verilen yanıtlar html veya json olabilir, nadir durumlarda xml veya başka bir şey olabilir.

Bu soruna iki yaklaşım vardır:

Düşük seviyeli yaklaşım:

Javascript sitesinin hangi ajax url'lerini aradığını ve bu yanıtların neye benzediğini anlayabilir ve aynı istekleri kendiniz de yapabilirsiniz. Dolayısıyla, http://example.com/foobar'dan html'yi çekip bir veri parçası çıkarabilir ve ardından json yanıtını http://example.com/api/baz?foo=b ... konumuna çekmeniz gerekebilir . diğer veri parçasını alın. Doğru çerezleri veya oturum parametrelerini geçirmenin farkında olmanız gerekir. Bu çok nadirdir, ancak bazen bir ajax çağrısı için gerekli bazı parametreler sitenin javascript'inde yapılan bazı çılgın hesaplamaların sonucu olabilir, tersine mühendislik bu can sıkıcı olabilir.

Gömülü tarayıcı yaklaşımı:

Neden html'de hangi verilerin olduğunu ve bir ajax çağrısından hangi verilerin geldiğini hesaplamanız gerekiyor? Tüm bu oturum ve çerez verilerini mi yönetiyorsunuz? Bir siteye, tarayıcıya ve javascript sitesine göz atarken bunu yapmak zorunda değilsiniz. Bütün mesele bu.

Sayfayı phantomjs gibi başsız bir tarayıcı motoruna yüklerseniz, sayfayı yükleyecek, javascript'i çalıştıracak ve tüm ajax çağrılarının ne zaman tamamlandığını size söyleyecektir. Uygun tıklamaları tetiklemek için gerekirse kendi javascript'inizi veya site javascript'inin uygun verileri yüklemesi için gerekli olan her şeyi enjekte edebilirsiniz.

Şimdi iki seçeneğiniz var, bitmiş html'yi çıkarıp ayrıştırmasını sağlayın veya ayrıştırma ve veri biçimlendirmenizi yapan ve verileri dışarı atan sayfaya biraz javascript enjekte edin (muhtemelen json biçiminde). Bu iki seçeneği de özgürce karıştırabilirsiniz.

Hangi yaklaşım en iyisidir?

Bu duruma göre değişir, kesinlikle düşük seviyeli yaklaşıma aşina ve rahat olmanız gerekecektir. Gömülü tarayıcı yaklaşımı her şey için işe yarar, uygulaması çok daha kolay olacak ve kazımadaki en zorlu sorunların bazılarını ortadan kaldıracaktır. Aynı zamanda, anlamanız gereken oldukça karmaşık bir makine parçası. Bu sadece HTTP istekleri ve yanıtları değil, istekleri, gömülü tarayıcı oluşturma, site javascript, enjekte edilmiş javascript, kendi kodunuz ve gömülü tarayıcı süreciyle 2 yönlü etkileşimdir.

Gömülü tarayıcı, oluşturma ek yükü nedeniyle ölçeğe göre çok daha yavaştır, ancak çok sayıda farklı alan adı kazmadığınız sürece bu neredeyse kesinlikle önemli olmayacaktır. Taleplerinizi sınırlama ihtiyacınız, tek bir alan adı durumunda işleme süresini tamamen önemsiz hale getirecektir.

Hız Sınırlama / Bot davranışı

Bunun çok farkında olmalısın. Hedef alanlarınıza makul bir oranda talepte bulunmanız gerekir. Web sitelerini tararken iyi davranan bir bot yazmanız gerekir ve bu, robots.txt'ye saygı duymak ve sunucuyu isteklere boğmamak anlamına gelir. Buradaki hatalar veya ihmaller çok etik değildir, çünkü bu bir hizmet reddi saldırısı olarak kabul edilebilir. Kabul edilebilir oran, kime sorduğunuza bağlı olarak değişir, 1req / s, Google tarayıcısının çalıştığı maksimum değerdir, ancak siz Google değilsiniz ve muhtemelen Google kadar hoş karşılanmıyorsunuz. Makul olduğu kadar yavaş tutun. Her sayfa isteği arasında 2-5 saniye öneririm.

Botunuzu tanımlayan ve botunuz için amacını açıklayan bir web sayfası olan bir kullanıcı aracısı dizesiyle isteklerinizi tanımlayın. Bu url aracı dizesine giriyor.

Site sizi engellemek isterse, kolayca engelleyeceksiniz. Uçlarındaki akıllı bir mühendis, botları kolayca tanımlayabilir ve sonunda birkaç dakikalık çalışma, sizin tarafınızdan kazıma kodunuzu değiştiren haftalarca çalışmanıza veya bunu imkansız hale getirmesine neden olabilir. İlişki düşmanca ise, hedef bölgedeki akıllı bir mühendis, bir dahi mühendisi bir tarayıcı yazarken tamamen engelleyebilir. Kazıma kodu doğası gereği kırılgandır ve bu durumdan kolayca yararlanılır. Bu yanıtı tetikleyecek bir şey zaten neredeyse kesinlikle etik değildir, bu yüzden iyi huylu bir bot yazın ve bunun için endişelenmeyin.

Test yapmak

Birim / entegrasyon test görevlisi değil misiniz? Çok kötü. Şimdi bir olmak zorundasın. Siteler sık ​​sık değişir ve kodunuzu sık sık değiştirirsiniz. Bu, zorluğun büyük bir kısmı.

Modern bir web sitesini kazımayla ilgili pek çok hareketli parça vardır, iyi test uygulamaları çok yardımcı olacaktır. Bu tür bir kodu yazarken karşılaşacağınız hataların çoğu, bozuk verileri sessizce döndüren türden olacaktır. Gerilemeleri kontrol etmek için iyi testler olmadan, bir süredir farkına varmadan gereksiz bozuk verileri veritabanınıza kaydettiğinizi göreceksiniz. Bu proje sizi veri doğrulama (kullanmak için bazı iyi kütüphaneler bulun) ve test etme konusunda oldukça aşina hale getirecektir. Kapsamlı testler gerektiren ve test edilmesi çok zor olan başka birçok sorun yoktur.

Testlerinizin ikinci kısmı, önbelleğe alma ve değişiklik algılamayı içerir. Kodunuzu yazarken, sebepsiz yere aynı sayfa için sunucuyu tekrar tekrar kullanmak istemezsiniz. Birim testlerinizi çalıştırırken, kodunuzu kırdığınız için veya web sitesi yeniden tasarlandığınız için testlerinizin başarısız olup olmadığını bilmek istersiniz. İlgili url'lerin önbelleğe alınmış bir kopyasına karşı birim testlerinizi çalıştırın. Önbelleğe alma proxy'si burada çok kullanışlıdır, ancak doğru şekilde yapılandırılması ve kullanılması zordur.

Ayrıca sitenin değişip değişmediğini de bilmek istersiniz. Siteyi yeniden tasarlamışlarsa ve tarayıcınız bozulmuşsa, önbelleğe alınmış bir kopyada çalıştıkları için birim testleriniz yine de geçecektir! Ya yayındaki siteye karşı seyrek olarak çalıştırılan başka, daha küçük bir entegrasyon testleri setine ya da tam sorunları günlüğe kaydeden, sizi soruna karşı uyaran ve taramayı durduran tarama kodunuzda iyi günlüğe kaydetme ve hata tespitine ihtiyacınız olacak. Artık önbelleğinizi güncelleyebilir, birim testlerinizi çalıştırabilir ve neyi değiştirmeniz gerektiğini görebilirsiniz.

Yasal sorunlar

Aptalca şeyler yaparsanız buradaki kanun biraz tehlikeli olabilir. Yasa dahil olursa, düzenli olarak wget ve curl'den "hackleme araçları" olarak bahseden insanlarla uğraşıyorsunuz demektir. Bunu istemezsin.

Durumun etik gerçekliği, bir url istemek ve bazı verilere bakmak için tarayıcı yazılımını kullanmak ile bir url istemek ve bazı verilere bakmak için kendi yazılımınızı kullanmak arasında hiçbir fark olmamasıdır. Google, dünyanın en büyük kazıma şirketidir ve onun için sevilmektedir. Bot adınızı kullanıcı aracısında tanımlamak ve web tarayıcınızın hedefleri ve niyetleri hakkında açık olmak, yasa Google'ın ne olduğunu anladığından burada yardımcı olacaktır. Sahte kullanıcı hesapları oluşturmak veya sitenin yapmamanız gereken alanlara erişmek gibi gölgeli bir şey yapıyorsanız (robots.txt tarafından "engellenmiş" veya bir tür yetkilendirme istismarı nedeniyle), o zaman etik olmayan bir şey yaptığınızı unutmayın. ve hukukun teknoloji konusundaki bilgisizliği burada olağanüstü derecede tehlikeli olacaktır. Gülünç bir durum ama gerçek bir durum.

Dürüst bir vatandaş olarak yeni bir arama motoru denemek ve inşa etmek, bir hata yapmak veya yazılımınızda bir hata olması ve bir bilgisayar korsanı olarak görülmek tam anlamıyla mümkündür. Mevcut politik gerçekliği düşündüğünüzde isteyeceğiniz bir şey değil.

Bu devasa metin duvarını yine de ben kimim?

Hayatımda çok sayıda web tarama ile ilgili kod yazdım. On yıldan fazla bir süredir danışman, çalışan ve girişim kurucusu olarak web ile ilgili yazılım geliştirme yapıyorum. İlk günler perl tarayıcıları / kazıyıcıları ve php web siteleri yazıyordu. XMLHTTPRequest bir fikirden önce, Jesse James Garrett ona ajax adını vermeden önce ajax yapmak için web sayfalarına csv verilerini yükleyen gizli iframe'leri gömerken. JQuery'den önce, json'dan önce. 30'lu yaşlarımın ortasındayım, görünüşe göre bu iş için eski kabul ediliyor.

Bir medya şirketinde (Perl'de) büyük bir ekip için bir kez ve son zamanlarda bir arama motoru başlangıcında (Python / Javascript'te) CTO olarak küçük bir ekip için olmak üzere iki kez büyük ölçekli tarama / kazıma sistemleri yazdım. Şu anda danışman olarak çalışıyorum, çoğunlukla Clojure / Clojurescript'te kodlama yapıyorum (genel olarak harika bir uzman dili ve tarayıcı / kazıyıcı sorunlarını bir zevk haline getiren kitaplıkları var)

Başarılı tarama önleme yazılım sistemleri de yazdım. Sevmediğiniz botları tespit etmek ve sabote etmek istiyorsanız, neredeyse hiç bozulmayan siteler yazmak oldukça kolaydır.

Tarayıcı, kazıyıcı ve ayrıştırıcı yazmayı diğer yazılım türlerinden daha çok seviyorum. Zorlu, eğlenceli ve harika şeyler yaratmak için kullanılabilir.


4
PHP'nin kötü bir seçim olduğu konusunda seninle aynı fikirdeydim, ama doğru kitaplıklarla çok da kötü değil. Regex ve dizi / sokma manipülasyonu beceriksizdir ancak artı tarafta hızlı ve her yerde.
pguardiario

3
Bunu bir zevk haline getiren ve onu oldukça basit ve oldukça kolaylaştıran birkaç kütüphanenin olduğu bir ortamda ... neden "çok kötü değil" diyesiniz? Katılıyorum, PHP'de (ve FORTRAN, C, VB, vb.) Yapılabilir, ancak sorununuz gerçekten çok basit değilse, iş için doğru araçları kullanmak çok daha iyi bir fikir olacaktır. Ve yine, çözmeniz gereken inanılmaz derecede basit bir problem olmadıkça ... normal ifadenin her yerde olmasının ne önemi var? Kitaplıkları kurmak, hemen hemen her kazıma probleminden çok daha basittir. Ve aslında, normal ifade bu problem için genellikle oldukça yavaştır.
Jesse Sherlock

5
Sen doğru olabilir, ama ben bir gerçeği biliyorum ben PHP'de gibi kolayca bunu yapamaz. PHP'den uzaklaşmadan önce on yıla yakın profesyonel PHP deneyimim vardı. Python'da ölçekli bir kazıma sistemi oluşturmak için bir yıldan fazla zaman harcadım ve PHP'de bulunmayan bazı güzel kitaplıklar olmadan veya Python'da mevcut olan kısa meta programlama teknikleri olmadan yapmayı hayal edemiyorum . Daha güçlü meta programlama yetenekleri elde etmek için Clojure'a taşınmamın nedeni de bu.
Jesse Sherlock

4
Enlive, projeye özel kod için Clojure'un gücüyle birlikte en büyük kazananlardır. Şema, bilgi çıkarma kodunun çok büyük bir parçası olan harika bir doğrulama kitaplığıdır. Şu anda Mahout ve bazı js uygulamaları için Nashorn / Rhino gibi şeyler için Java dünyasıyla kolay etkileşimden gerçekten memnunum. Ve Clojure insanları, sizin zorunda kalmamanız için bu github.com/shriphani/subotai gibi libler yazan tiplerdir . ... sonraki yorumun devamı ...
Jesse Sherlock

3
Ayrıca, gerçek bir tarayıcıya gerçekten ihtiyacınız olduğunda ve phantomjs / casperjs ile gitmeniz gerektiğinde, clojurescript yerine sayfaya enjekte ettiğiniz j'leri yazmak için clojurescript (genellikle clj ve cljs arasında paylaşılan kod) kullanmanın gerçekten harika olduğunu buldum. . Core.async, sunucudaki oldukça eşzamanlı tarama kodunu koordine etmek ve js ortamında geri arama cehenneminden çıkmak için harikadır (phantomjs içindeki core.async cljs koduyla tarayıcı otomasyonunu koordine etmek, alternatiflere kıyasla cennettir).
Jesse Sherlock

21

Evet, kendiniz yapabilirsiniz. Bu sadece sayfanın kaynaklarını ele geçirme ve onları istediğiniz şekilde ayrıştırma meselesidir.

Çeşitli olasılıklar var. İyi bir combo, python isteklerini ( urllib.requesturllib2'nin üstüne inşa edilmiştir, Python3'tedir) ve öğeleri seçme yöntemlerine sahip olan ve ayrıca CSS seçicilere izin veren BeautifulSoup4'ü kullanmaktır :

import requests
from BeautifulSoup4 import BeautifulSoup as bs
request = requests.get("http://foo.bar")
soup = bs(request.text) 
some_elements = soup.find_all("div", class_="myCssClass")

Bazıları xpath ayrıştırmayı veya jquery benzeri pyquery, lxml veya başka bir şeyi tercih eder .

İstediğiniz veriler bir JavaScript tarafından üretildiğinde , yukarıdakiler çalışmayacaktır. Ya python hayaletine ya da Selenium'a ihtiyacınız var. İkincisini PhantomJS ile birleştirilmiş , çok daha hafif ve kurulumu daha basit ve kullanımı kolay olanı tercih ederim :

from selenium import webdriver
client = webdriver.PhantomJS()
client.get("http://foo")
soup = bs(client.page_source)

Kendi çözümünüzü başlatmanızı tavsiye ederim. Bunu yaparken Scrapy'nin faydalarını anlayacaksınız.

ps: hemen bir göz atın: https://github.com/scrapy/scrapely

pps: programlama bilgisi olmadan bilgileri görsel olarak çıkarmaya başlamak için Portia'ya bir göz atın: https://github.com/scrapinghub/portia


Pekala, yanıtlayan için teşekkürler, tek sorun Python'un becerilerimde olmaması. Aynı görevleri yerine getirebilecek başka iyi programlama dilleri var mı? Ağırlıklı olarak PHP ve Javascript ile çalışıyorum.
0x1ad2

Karışıklık için özür dilerim (sorumda Python çerçevesinden bahsetmiştim), ancak Python bunu yapmanın en iyi yolu ise öğrenebilirim.
0x1ad2

Python hurdalığı çok kolaylaştırır. Öğrenmesi de kolaydır. Şu anda iyi performans gösteren en iyi sıyırıcı hurdadır. Ayrıca çok iyi belgelere sahipler.
Abhishek
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.