Web Crawler(romanticdevil-crawler.py)
#1
[Image: vg7l3m.jpg]
Halo teman - teman back lagi bersama sy ... ya kali ini sy akan share code saya yang bernama romanticdevil-crawler.py atau bisa di katakan sebuah Web Crawler.berawal dari saya membuat tutorial Python Web Scraping & Screen Scraping / Parse Html pada : http://jimmyromanticdevil.wordpress.com/...web-pages/ dan bermula ide ini waktu sy sendiri browsing2 thread di indonesianbacktrack sendiri yang bertema http://forum.indonesianbacktrack.or.id/s...p?tid=1104 "Menjarah website dengan Httrack + sharing website" linux " sy sendiri mulai membuat web Crawler sy sendiri .
Nah sebelumnya kita kenal dulu apakah yang di maksud dengan web Crawler ini ?

Apa itu Web Crawler?
Web Crawler adalah sebuah program/script otomatis yang memprosess halaman web. Bisa juga disebut sebagai web spider atau web robot. Ide dasarnya sangat simpel dan hampir sama dengan ketika kalian sedang menjelajahi halaman website secara manual dengan menggunakan browser. Bermula pada sebuah link alamat website, dibuka pada browser kemudian browser melakukan permintaan dan mendownload data dari web server melalui protokol HTTP. Setiap hyperlink yang ditemui pada konten yang tampil akan dibuka lagi pada windows/tab browser yang baru, demikian proses terus berulang. Nah, Web Crawler mengotomatisasikan pekerjaan ini. Jadi, Web Crawler berfungsi mengidentifikasi hyperlink dan melakukan proses kunjungan/visit secara rekursif.
Nah dan Tools sy sendiri ini juga sama fungsinya dengan tools httrack yang di mana httrack ini Jika kalian suka dengan isi suatu website tetapi tidak punya waktu atau uang untuk membacanya pada saat itu juga, maka Anda bisa memakai HTTrack. HTTrack adalah sebuah website copier yang fungsinya adalah menyalin keseluruhan isi dari suatu website untuk nantinya dapat dibaca secara offline. Software ini tentunya sangat berguna jika anda pergunakan di warnet, karena dapat menghemat waktu untuk menyimpan secara manual atau membaca di tempat.
Cuman banyak kekurangan pada Tools saya yaitu content yang di dapatkan hanya terbatas yaitu css file,javascript file,image file dan isi web page html.jadi untuk format seperti mp3,swf,dll tidak akan bisa di crawler dengan tools sy . tapi saya rasa cukup untuk basic dari web crawler. selanjutnya jika kalian tertarik silahkan mengembangkannya sendiri .. ^.^

How it work ??
Jadi pertanyaanya sekarang bagaimana code saya bekerja . ok jadi saya hanya akan menjelaskan inti dari code saya . jadi jika ada yang belum jelas sy harap kalian bisa comment di bawah . dan sebelum itu sebaiknya kalian melihat tutorial saya sebelumnya tentang Python Web Scraping & Screen Scraping / Parse Html pada : http://jimmyromanticdevil.wordpress.com/...web-pages/ supaya code bisa kalian pahami dengan cpat/mudah .
ya di sini saya masih mengunakan yang namanya modul urllib2 untuk melakukan request terhadap sebuah website dan beautifullsoup untuk menscrap/parse link2,src link or tag2 html yang ada pada page yang nantinya link2 tersebut akan di proses kembali untuk di pada fungsi2 yang sy sediakan untuk di download .

First code explain :
Code:
opener = urllib2.build_opener()
    opener.addheaders = [('User-agent', random.choice(user_agent))]
    page = opener.open(url) -->merequest page
penjelasan : Di sini saya mengunakan user agent dengan mengadd header urllib2 sy.dan user agent akan terpilih dengan acak/random.kenapa harus pake random user agent ?? agar code tidak terprotek dari securty sebuah website karena biasa sebagian situs menggunakan sebuah script untuk mendeteksi browser yang sedang mengakses kesitus tersebut, yang dideteksi adalah User Agent.biasanya tanpa user agent atau jika user agent tidak terdaftar di website maka kita tidak akan bisa mengakses website tersebut.

Code:
htmlcode_page = page.read()  ##-->membaca keseluruhan string dari 'page' dan simpan pada variabel 'htmlcode_page'
   dump_isihtml = bs(htmlcode_page) ##-->Parsing page
   print dump_isihtml.title.string ##--> cetak string dari judul page site
   Links = dump_isihtml.findAll("a", {"href": True})  ##-->dapatkan tag a href
   leng = len(Links)   ##-->hitung banyaknya elemen pada Links
   count = 0   ##-->counter
   while count < leng:##-->perulangan untuk menulis link dari href selama counter kurang dari banyaknya link
      try:  
         url_match = re.findall("((http\://|https\://|ftp\://)|(www.))+(([a-zA-Z0-9\.-]+\.[a-zA-Z]{2,4})|([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}))(/[a-zA-Z0-9%:/-_\?\.'~]*)?", Links[count]["href"]) ##-->

penjelasan kenapa sy memakai regex .. contoh di sini akan ada 2 type result dari Links[count]["href"] yaitu pada contoh di hrefnya mengunakan href="register.html" dan ada yang href="http://www.indonesianbacktrack.or.id/?page_id=7".nah jadi sy match apakah result di depannya ada http: / www / atau ftp/
jika ia maka saya akan langsung melemparnya ke fungsi yang saya buat tanpa menambahkan url di depannya . bisa di lihat di
Code:
elif url_match:
            [statement]

nah jika tidak misalnya resultnya adalah register.html
maka sy harus menambahkan url dari yang di request di atas contoh url+Links[count]["href"]
jadi hasilnya adalah http://www.indonesianbacktrack.or.id/register.html bisa di lihat pada else

Code:
else:
        [statement]
        
    terdapat juga count += 1  ##--> increment jika sukses di lakukan semua statement
    maka count akan bertambah satu berarti url berhasil di scrap/parse .

Code:
if Links[count]["href"] == "#" or Links[count]["href"] == "" or os.path.isfile(Links[count]["href"]):
        print 'page available or got filter'
        count +=1

Di sini saya akan mengecek apakah Links[count]["href"] berisi '#' biasa umum pada web yang bersifat ajax without reload page.atau href yang berisi href="#" berarti tidak ada action ke link . atau kah kosong Links[count]["href"] == "" dan juga ada os.path.isfile(Links[count]["href"]):
yang berarti mengecek apa kah file sudah ada . dan jika salah satu kondisi benar maka akan di lakukan statement

Code:
print 'page available or got filter'
        count +=1
  
   - yang berarti page sudah ada atau di kena dengan filter .


Code:
elif url_match:
        print 'Fetch page %s'%Links[count]["href"] ##--> cetak link URL
        download(Links[count]["href"]) # lempar ke fungsi download
        download_css(Links[count]["href"]) # lempar ke fungsi download_css
        download_image(Links[count]["href"]) # lempar ke fungsi download_image
        download_js(Links[count]["href"]) # lempar ke fungsi download_js
        count += 1  ##--> increment
        
       else:
        print 'Fetch page %s'%Links[count]["href"] ##--> cetak link URL
        download(url+'/'+Links[count]["href"])# lempar ke fungsi download
        download_css(url+'/'+Links[count]["href"])# lempar ke fungsi download_css
        download_image(url+'/'+Links[count]["href"])# lempar ke fungsi download_image
        download_js(url+'/'+Links[count]["href"]) # lempar ke fungsi download_js
        count += 1  ##--> increment


Next untuk code2 di fungsi . saya hanya akan menjelaskan 2 fungsi karena saya rasa yang lain sama saja
Fungsi 1
Code:
Di sini adalah fungsi untuk mendownload pagenya ..
   def download(url):
        url_request = urllib.urlopen(url) ##->Request url page yang akan di download
        try:
            localFile = open(url.split('/')[-1], 'w') #open dan split index -1 dan mode 'w'
            localFile.write(url_request.read()) #write hasil request ke local
            url_request.close() # akhiri request
            localFile.close() # close file setelah di write
        except:
            pass


Fungsi 2
Code:
def download_image(url):
        soup = ziachow(urlopen(url)) # merequest sebuah page hampir sama dengan urllib cuman di sini saya mengunakan urlopen dan sekaligus memparse
        #url tersebut
        parsed = list(urlparse.urlparse(url)) # sama dengan yang di atas cmn di sini hasil sy jadikan list
        for image in soup.findAll("img"): # dapatkan tag img
            try:
               filename = image["src"].split("/")[-1] # split result image["src"] dengan /
               if os.path.isfile(filename) or os.path.isfile(parsed[2]):break # cek jika isi file ada jika ada maka akan di break
               else:  
                  print "Image Download: %(src)s" % image #print image source
                  parsed[2] = image["src"] #masukan ke dalam list dengan index ke 2 result dari image["src"]
                  outpath = os.path.join(out_folder, filename) #gabungkan out_folder dan filename yang dimana outfolder di sini adalah output
                  #dir folder yang sy set satu folder dengan code dan filename yang akan di save . silahkan di ganti sesukanya untuk output
                  #dirnya.
                  if image["src"].lower().startswith("http"):
                     # nah di sini saya menjadian teksnya dengan huruf kecil .lower() dan mengecek apakah teks berisi http jika ia maka
                     urlretrieve(image["src"], outpath)
                     #kenapa karena tanpa pengenal protokol maka urlretrieve() tidak akan jalan.
                  else:
                     #nah jika tidak saya akan
                     #urlretrieve(urlparse.urlunparse(parsed), outpath) #jika tidak gunakan urlunparse yang hampir sama fungsi tapi memparse url
                     #yang ada di list
            except:
               break

Code lengkap :
Code:
#!/usr/bin/env python
# Hardcoding by Jimmyromanticdevil aka rahmat ramadhan iryanto
# [email protected]
# you can distribution anything do you want
# http://jimmyromanticdevil.wordpress.com
# webcrawler(romanticdevil-crawler.py)
import urllib2
import BeautifulSoup
import sys
import urllib
from BeautifulSoup import BeautifulSoup as ziachow
import urlparse
from urllib2 import urlopen
from urllib import urlretrieve
import os
import os.path
import re
import random
out_folder = ""
user_agent    = ['Mozilla/4.0 (compatible; MSIE 5.0; SunOS 5.10 sun4u; X11)',
        'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.2pre) Gecko/20100207 Ubuntu/9.04 (jaunty) Namoroka/3.6.2pre',
        'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Avant Browser;',
        'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0)',
            'Mozilla/4.0 (compatible; MSIE 7.0b; Windows NT 5.1)',
            'Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.0.6)',
            'Microsoft Internet Explorer/4.0b1 (Windows 95)',
            'Opera/8.00 (Windows NT 5.1; U; en)',
        'amaya/9.51 libwww/5.4.0',
        'Mozilla/4.0 (compatible; MSIE 5.0; AOL 4.0; Windows 95; c_athome)',
        'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)',
        'Mozilla/5.0 (compatible; Konqueror/3.5; Linux) KHTML/3.5.5 (like Gecko) (Kubuntu)',
        'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; ZoomSpider.net bot; .NET CLR 1.1.4322)',
        'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; QihooBot 1.0 [email protected])',
        'Mozilla/4.0 (compatible; MSIE 5.0; Windows ME) Opera 5.11 [en]'
        ]


#fungsi untuk mendownload page
def download(url):
    url_request = urllib.urlopen(url)
    try:
         localFile = open(url.split('/')[-1], 'w')
         localFile.write(url_request.read())
         url_request.close()
         localFile.close()
    except:
         pass

#fungsi untuk mendownload image
def download_image(url):
    soup = ziachow(urlopen(url))
    parsed = list(urlparse.urlparse(url))

    for image in soup.findAll("img"):
        try:
           filename = image["src"].split("/")[-1]
           if os.path.isfile(filename) or os.path.isfile(parsed[2]):
              break
           else:  
              print "Image Download: %(src)s" % image
              parsed[2] = image["src"]
              outpath = os.path.join(out_folder, filename)
              if image["src"].lower().startswith("http"):
                 urlretrieve(image["src"], outpath)
              else:
                 urlretrieve(urlparse.urlunparse(parsed), outpath)

        except:
            break
                

#fungsi untuk mendownload css                
def download_css(url):
  try:
    soup = ziachow(urlopen(url))
    parsed = list(urlparse.urlparse(url))
    for image in soup.findAll("link"):
        try:
            filename = image["href"].split("/")[-1]
            parsed[2] = image["href"]
            if os.path.isfile(filename) or os.path.isfile(parsed[2]):
               break
            else:  
               print "Css Download: %(href)s" % image
               outpath = os.path.join(out_folder, filename)
               if image["href"].lower().startswith("http"):
                  urlretrieve(image["href"], outpath)
               else:
                  urlretrieve(urlparse.urlunparse(parsed), outpath)
        except:
            break
  except:
     pass        


#fungsi untuk mendownload js
def download_js(url):
  try:
    soup = ziachow(urlopen(url))
    parsed = list(urlparse.urlparse(url))
    for image in soup.findAll("script"):
        try:
            filename = image["src"].split("/")[-1]
            if os.path.isfile(filename) or os.path.isfile(parsed[2]):
               break
            else:  
               print "Javascript/Jquery Download: %(src)s" % image
               parsed[2] = image["src"]
               outpath = os.path.join(out_folder, filename)
               if image["src"].lower().startswith("src"):
                  urlretrieve(image["src"], outpath)
               else:
                  urlretrieve(urlparse.urlunparse(parsed), outpath)
        except:
            break

  except:
     pass        

def main(url):
    opener = urllib2.build_opener()
    opener.addheaders = [('User-agent', random.choice(user_agent))]
    page = opener.open(url)
    htmlcode_page = page.read()
    dump_isihtml = BeautifulSoup.BeautifulSoup(htmlcode_page)
    print dump_isihtml.title.string
    Links = dump_isihtml.findAll("a", {"href": True})
    leng = len(Links)  
    count = 0  
    while count < leng:
      try:  
         url_match = re.findall("((http\://|https\://|ftp\://)|(www.))+(([a-zA-Z0-9\.-]+\.[a-zA-Z]{2,4})|([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}))(/[a-zA-Z0-9%:/-_\?\.'~]*)?", Links[count]["href"])
    
     if Links[count]["href"] == "#" or Links[count]["href"] == "" or os.path.isfile(Links[count]["href"]):
        print 'page available or got filter'
        count +=1
     elif url_match:
        print 'Fetch page %s'%Links[count]["href"]
        download(Links[count]["href"])
        download_css(Links[count]["href"])
        download_image(Links[count]["href"])
        download_js(Links[count]["href"])
        count += 1  
        
     else:
        print 'Fetch page %s'%Links[count]["href"]
        download(url+'/'+Links[count]["href"])
        download_css(url+'/'+Links[count]["href"])
        download_image(url+'/'+Links[count]["href"])
        download_js(url+'/'+Links[count]["href"])
        count += 1
      except:
            count +=1
            
if __name__ == '__main__':
    if len(sys.argv) == 2:
           try:
           main(sys.argv[1])
       except Exception,err:
        print err
        else:
       print 'usage: %s http://server.com/ ' % os.path.basename(sys.argv[0])

atau jika terdapat indent error di atas maka kalian bisa mencopy codenya dari sini
http://pastebin.com/6fzEH5eZ
ok saya rasa cukup untuk penjelasan .kalau masih kurang jangan sungkan untuk comment saya akan perjelas.,selanjutnya jika proses selesai maka kalian bisa klick file html yang di save dan open with browser2 yang kalian gunakan maka akan tampil hasil copyan sitenya .
oia source code yang sy buat dan sediakan masa tergolong masih boros dan belum rapi tapi sy rasa sudah cukup untuk simplenya dan juga masih bersifat single thread jadi kalian yang ingin mengembangkannya silahkan . atau mau di tambahin multithreader jg silahkan bebas . sy sendiri masih belum sempat mengopreknya di karenakan kesibukan research yang padat .. Sad kpn2 sy lanjutkan lagi .. ok selamat mencoba .. hapy explore ..

WARNING :
dan juga hati-hati mengunakan ini terutama pada website kalian Selain pengambilan konten untuk kepentingan tertentu, Web Crawler dapat mengakibatkan kerugian lain bagi pemilik website. Diantaranya yaitu penggunaan resource yang meningkat, seperti pemakaian bandwidth dan CPU server, apalagi jika ada dua atau lebih Web Crawler mengakses website yang sama.nah tapi ini tidak berlaku jika bandwidth pada server bersifat unlimited.


Special thanks to my refensi wikipeadia "web crawling" & Google Keyword "web crawling explain" and pypi "kumpulan lib python"


#2
Keren gannn.. Big Grin

#3
thanks bang,ijin nyobain..
Big Grin

#4
wah mantep nih...
ntar saya review ah kalo bisa =))
Yang putih, yang seharusnya ber-aksi dan berbakat!
Linuxtivist blog

#5
keren bang heheheh ..ijin sedot kalo soal python abang kita satu ini gk ada obatnye !

#6
sama kayak ini gak ya konsepnya?

http://forum.indonesianbacktrack.or.id/s...p?tid=1104

Bedanya yang om jimmi itu coding sendiri Smile
Yang putih, yang seharusnya ber-aksi dan berbakat!
Linuxtivist blog

#7
iyap itu sama konsepnnya yang biasa di namakan web crawler ,,,

#8
owh Smile
sipdeh... keren om romanticdevilnya Smile
Yang putih, yang seharusnya ber-aksi dan berbakat!
Linuxtivist blog

#9
ane udah coba bro, setelah di jalanin kok web yg di-crawl kok ga ditaruh hasilnya di satu folder ya? jadi berantakan nih, gmn caranya biar rapi? Big Grin

#10
nah kl memang mau seperti itu kamu bisa tambah sebuah parameter arg untuk fungsinya
jadi perintah pada saat code akan di jalankan seperti : python namafile.py outputpath
yang dimana arg2 akan di lempar ke fungsi
main(sys.argv[1],sys.argv[2])

def main(url,outputpath):
..........
print 'Fetch page %s'%Links[count]["href"]
download(Links[count]["href"],outputpath)##--> cetak link URL
download_css(Links[count]["href"],outputpath)
download_image(Links[count]["href"],outputpath)
download_js(Links[count]["href"],outputpath)

dan dilempar lagi ke fungsi2 lainnya ... cb deh explore sendiri ......Smile

atau bisa mengedit di out_folder = "" misal sy mau taruh di folder jimm out_folder = "jimmy" tapi buat dlu folder jimmy






Users browsing this thread: 1 Guest(s)