Scraping Situs Secara Rekursif

By | March 24, 2022
1,173 Views

Scraping situs mempunyai banyak tujuannya seperti melakukan otomatisasi pengambil URL/Link atau feed tertentu. Algoritma Scraping dilakukan secara rekursif yaitu persatu-satu link akan dikunjungi. Tak heran bila sebuah website bisa berisi ribuan link. Agar Scraping berjalan dengan baik, tentu kita membutuhkan library/tools yang mampu melakukan parsing.

Bila kalian pengguna bahasa Java, saya sarankan menggunakan JSOUP untuk scraping situs. Jsoup adalah perpustakaan Java open-source yang terdiri dari metode yang dirancang untuk mengekstrak dan memanipulasi konten dokumen HTML. Itu ditulis pada tahun 2009 oleh Jonathan Hedley, seorang manajer pengembangan perangkat lunak untuk Amazon Seattle. Jika Anda terbiasa dengan jQuery, kalian tidak akan kesulitan bekerja dengan metode Jsoup. Kegunaan JSoup yaitu

  • scrape and parse HTML from a URL, file, or string
  • find and extract data, using DOM traversal or CSS selectors
  • manipulate the HTML elements, attributes, and text
  • clean user-submitted content against a safe white-list, to prevent XSS attacks
  • output tidy HTML

Library JSOUP tersedia dari mulai ant, maven, ataupun gradle. Kalian bisa kunjungi https://jsoup.org/download, tapi lebih suka menggunakan gradle saja

// jsoup HTML parser library @ https://jsoup.org/
implementation ‘org.jsoup:jsoup:1.14.3’

Setelah kalian menambahkan kode diatas pada gradle, kita coba saja untuk scraping situs

public class Crawler {
    public static void main(String[] args) {
        try {            
            Document doc = Jsoup.connect("https://softscients.com/").get();
            Elements links = doc.select("a[href]");
            for (Element link : links) {                
                System.out.println("nlink: " + link.attr("href"));                
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Namun kode diatas hanya menghasilkan scraping terhadap situs alamat situs utama saja. Harusnya kita bisa melakukan semua link yang berada di situs tersebut. Untuk membuat hal tersebut kita butuh sebuah method yang akan dijadikan rekursif. Caranya adalah

  • Kita membuat variable array list yang berisi link yang sudah pernah dikunjungi sehingga tidak terjadi looping tak hingga karena looping dialamat yang sama.
  • Mendefisiniskan MAIN_HOST yang digunakan untuk mengabaikan alamat website yang lain. Misalkan ketika melakukan scraping link https://softscients.com bila mendapatkan link https://facebook.com, maka situs facebook tidak akan discraping tingkat lanjut hanya sebatas link tersebut saja.
  • Membuat extension untuk diabaikan, misalkan URL yang seperti gambar akan diabaikan, header, link comment juga

Saya coba otak-atik kodenya untuk menghasilkan scraping situs secara rekursif. Berikut kode yang saya buat

public class CrawlerRekursif {

    ArrayList <String> VISITED_URL;
    String MAIN_URL;
    String MAIN_HOST;
    int COUNT_INDEX = 1;
    public CrawlerRekursif(String url){
        try {
            VISITED_URL = new ArrayList();
            this.MAIN_URL=url;
            MAIN_HOST = new URL(url).getHost();
            Thread tr = new Thread(new Runnable(){
                @Override
                public void run() {
                    scrap(url);
                }
            }){                
            };
            tr.start();
            
        } catch (MalformedURLException ex) {
            Logger.getLogger(CrawlerRekursif.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        
        //https://softscients.com/
        //http://www.detik.com/
        //https://idschool.net/
        //https://www.reyneraea.com/
        CrawlerRekursif m = new CrawlerRekursif("https://www.reyneraea.com/");
        
    }
    public void scrap(String f){       
        try {
            Document doc = Jsoup.connect(f).userAgent("Mozilla").get();
            Elements links = doc.select("a[href]");
            if(links.isEmpty()){
                return;
            }
            ArrayList <String> local_url = new ArrayList();
            for (Element link : links) {
              String lnk = link.attr("href");
              //abaikan link yang mengandung image
              //comment, header, atau link kosong
              if(!local_url.contains(lnk) & !lnk.equals("") & !lnk.contains("#")&!lnk.contains(".png")&!lnk.contains(".jpg")&!lnk.contains(".jpeg")&!lnk.contains(".xlsx")&!lnk.contains("tag")&!lnk.contains(".csv")&!lnk.contains("category")){
                  String host = new URL(lnk).getHost();
                  //jika link tersebut milik HOST, lanjutkan saja                  
                  if(host.equals(MAIN_HOST) & !lnk.equals(MAIN_URL)){ 
                      local_url.add(lnk);
                      if(!VISITED_URL.contains(lnk)){ //masukan link jika belum pernah dikunjungi                         
                          System.out.println("\t"+COUNT_INDEX+" : "+lnk);
                          COUNT_INDEX++;                          
                          VISITED_URL.add(lnk);
                          scrap(lnk);                          
                      }
                  }
              }
              Thread.sleep(100);
            }
                
        } catch (IOException e) {
        } catch (InterruptedException ex) {
            Logger.getLogger(CrawlerRekursif.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}

Melalui kode diatas Scraping Situs akan sangat mudah dan menghasilkan semua link yang berada pada MAIN_HOST dan menghasilkan Scraping Situs Secara Rekursif

Menyimpan hasil scraping ke database

Tidak lengkap rasanya bila hasil scraping yang banyak tidak disimpan dalam bentuk database.  Nah kita bisa menggunakan sqlite saja. Kalian tambahkan saja kode di gradle untuk sqlitenya

implementation ‘org.xerial:sqlite-jdbc:3.30.1’

Kode dibawah ini sudah agak beda dengan kode diatas untuk penamaan variabelnya agar sesuai dengan fungsi / tujuaanya. Berikut kode lengkap untuk menyimpan hasil scraping ke database

public class CrawlerRekursif {
    ArrayList <String> VISITED_URL;
    String MAIN_URL;
    String MAIN_HOST;
    int COUNT_INDEX = 1;
    Connection conn = null;
    PreparedStatement pstmt;
    public CrawlerRekursif(String url){
        try {
            String db = "jdbc:sqlite:D:/softcsients.db";
            // create a connection to the database
            conn = DriverManager.getConnection(db);            
            System.out.println("Connection to SQLite has been established.");
            // SQL statement for creating a new table
            String sql = "CREATE TABLE IF NOT EXISTS link (\n"
                    + "	id integer PRIMARY KEY,\n"
                    + "	name text NOT NULL, \n"
                    + "	error text \n"
                    + ");";
            Statement stmt = conn.createStatement();
            // create a new table
            stmt.execute(sql);
            String insert = "INSERT INTO link (name,error) VALUES(?,?)";
            pstmt = conn.prepareStatement(insert);
        
            VISITED_URL = new ArrayList();
            this.MAIN_URL=url;
            MAIN_HOST = new URL(url).getHost();
            Thread tr = new Thread(new Runnable(){
                @Override
                public void run() {
                    scrap(url);
                }
            }){                
            };
            tr.start();
        } catch (MalformedURLException ex) {
            Logger.getLogger(CrawlerRekursif.class.getName()).log(Level.SEVERE, null, ex);
        } catch (SQLException e){
        }
    }
    
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        
        //https://softscients.com/
        //http://www.detik.com/
        //https://idschool.net/
        //https://www.reyneraea.com/
        CrawlerRekursif m = new CrawlerRekursif("https://softscients.com/");
        
    }
    public void scrap(String f){       
        try {
            Document doc = Jsoup.connect(f).userAgent("Mozilla").get();
            Elements links = doc.select("a[href]");
            if(links.isEmpty()){
                return;
            }
            ArrayList <String> local_url = new ArrayList();
            for (Element link : links) {
              String lnk = link.attr("href");
              //abaikan link yang mengandung image
              //comment, header, atau link kosong
              if(!local_url.contains(lnk) & 
                      !lnk.equals("") & 
                      !lnk.contains("#") & 
                      !lnk.contains(".png") & 
                      !lnk.contains(".jpg") &
                      !lnk.contains(".jpeg") &
                      !lnk.contains(".bmp") &
                      !lnk.contains(".xlsx") &
                      !lnk.contains(".xls") &
                      !lnk.contains(".txt") &
                      !lnk.contains(".docx") &
                      !lnk.contains(".rar") &
                      !lnk.contains(".gif") &
                      !lnk.contains(".zip") &
                      !lnk.contains("tag") &
                      !lnk.contains("page") &
                      !lnk.contains(".csv") &
                      !lnk.contains("category")){
                  String host = new URL(lnk).getHost();
                  //jika link tersebut milik HOST, lanjutkan saja                  
                  if(host.equals(MAIN_HOST) & !lnk.equals(MAIN_URL)){ 
                      local_url.add(lnk);
                      if(!VISITED_URL.contains(lnk)){ //masukan link jika belum pernah dikunjungi    
                          pstmt.setString(1,lnk); //tambahkan ke db
                          pstmt.setString(2,""); //tambahkan ke db
                          pstmt.executeUpdate();
                          System.out.println("\t"+COUNT_INDEX+" : "+lnk);
                          COUNT_INDEX++;                          
                          VISITED_URL.add(lnk);
                          scrap(lnk);                          
                      }
                  }
              }
              Thread.sleep(10);
            }                
        } catch (IOException e) {
            
        } catch (InterruptedException ex) {
            Logger.getLogger(CrawlerRekursif.class.getName()).log(Level.SEVERE, null, ex);
        }catch (SQLException e) {
            System.out.println(e.getMessage());
        }
    }
}

Kode diatas sudah saya coba untuk scraping situs, 100% link akan ter extract dengan baik! Untuk kodenya bisa kalian peroleh di https://github.com/mulkan/scrapingsitus

See also  Hello World dengan notepad