Changeset cd64b06


Ignore:
Timestamp:
01/11/25 01:23:10 (4 days ago)
Author:
Kristijan <kristijanzafirovski26@…>
Branches:
master
Children:
0a7426e
Parents:
1c51912
Message:

Added info scraping for escape travel

Files:
14 edited

Legend:

Unmodified
Added
Removed
  • backend/GlobeGuru-backend/src/main/java/DatabaseUtil.java

    r1c51912 rcd64b06  
    151151                "FROM options o " +
    152152                "LEFT JOIN optionDetails od ON o.id = od.optionId " +
    153                 "WHERE (o.country LIKE ? OR o.hotelName LIKE ?)";
     153                "WHERE (o.country LIKE ? OR o.hotelName LIKE ?) " +
     154                "AND od.type IS NOT NULL " +
     155                "AND od.board IS NOT NULL " +
     156                "AND od.price > 0";
    154157
    155158        if (dateQuery != null && !dateQuery.isEmpty() && !dateFlag) {
     
    200203        return options;
    201204    }
     205
    202206
    203207
  • backend/GlobeGuru-backend/src/main/java/FrontendHandler.java

    r1c51912 rcd64b06  
    130130            return;
    131131        }
    132 
    133132        Server.sendResponse(exchange, 200, mapper.writeValueAsString(options));
    134133    }
  • backend/GlobeGuru-backend/src/main/java/ScraperThread.java

    r1c51912 rcd64b06  
    9696                            } else if (optionSet.add(option)) {
    9797                                uniqueOptions.add(option);
    98                                 DatabaseUtil.saveOptionToDatabase(option);
     98                                option.setId(DatabaseUtil.saveOptionToDatabase(option));
     99                                scrapeOptionInfo(option);
    99100                                System.out.println("Parsed " + option);
    100101                            }
     
    149150
    150151             String board = roomOption.select(".rezervacija-objekt").text();
    151              if(board.length() > 2){
    152                  board = board.substring(0,2);
     152             if(board.length() > 2) {
     153                 board = board.substring(0, 2);
    153154             }
    154              if(board.isEmpty() || type.isEmpty()){
    155                  continue;
    156              }
     155             if(board.isEmpty() || type.isEmpty()) continue;
     156
    157157             Elements amenityElement = roomOption.select(".objekt-opis");
    158158             String amenity = (amenityElement != null ? amenityElement.text() : "");
     
    166166             DatabaseUtil.saveOptionDetails(option.getId(), type,board,amenity, price);
    167167         }
     168        }
     169        else if(url.contains("booking.escapetravel.mk")){
     170            System.out.println("Scraping info for " + url);
     171
     172            driver.get(url);
     173            try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } //data fetch
     174            String pageSource = driver.getPageSource();
     175            Document doc = Jsoup.parse(pageSource);
     176            Elements roomOptions = doc.select("#hotel-rooms-container .hotel-room-row");
     177            for(Element roomOption : roomOptions){
     178                String type = roomOption.select("td.align-middle").first().text();
     179                String board = roomOption.select("td.align-middle.text-primary.lead").text();
     180                if (board.isEmpty() || type.isEmpty())  continue;
     181                String priceText = roomOption.select("td.align-middle.text-end .text-success.d-block.lead").text().replace("€", "").trim();
     182                float price;
     183                if (!priceText.isEmpty()) {
     184                    price = Float.parseFloat(priceText.replace(",", ""));
     185                } else continue;
     186
     187                Elements amenityElements = doc.select("div.row > div.col-6.col-md-3.col-xl-2");
     188                StringBuilder amenities = new StringBuilder();
     189                for (Element amenityElement : amenityElements) {
     190                    amenities.append(amenityElement.text()).append(", ");
     191                }
     192                if (!amenities.isEmpty()) {
     193                    amenities.setLength(amenities.length() - 2);
     194                }
     195                System.out.println(type + board + price + amenities);
     196                DatabaseUtil.saveOptionDetails(option.getId(), type, board, amenities.toString(), price);
     197            }
     198
    168199        }
    169200    }
  • backend/GlobeGuru-backend/src/main/java/Server.java

    r1c51912 rcd64b06  
    196196
    197197    public static void sendResponse(HttpExchange exchange, int statusCode, String response) throws IOException {
     198        byte[] responseBytes = response.getBytes(StandardCharsets.UTF_8);
    198199        exchange.getResponseHeaders().add("Cross-Origin-Opener-Policy", "unsafe-none");
    199200        exchange.getResponseHeaders().add("Cross-Origin-Embedder-Policy", "require-corp");
    200201        exchange.getResponseHeaders().add("Content-Type", "application/json");
    201         exchange.sendResponseHeaders(statusCode, response.length());
    202         exchange.getResponseBody().write(response.getBytes());
    203         exchange.getResponseBody().close();
    204     }
    205 
     202        exchange.getResponseHeaders().add("Transfer-Encoding", "chunked");
     203        exchange.sendResponseHeaders(statusCode, 0);
     204        try (OutputStream os = exchange.getResponseBody()) {
     205            os.write(responseBytes);
     206        }
     207    }
    206208}
    207209
  • backend/GlobeGuru-backend/src/main/resources/URLsJSON.json

    r1c51912 rcd64b06  
    22  "agencyurls":
    33          [
    4             "https://magelantravel.mk/"
    5 
     4            "https://magelantravel.mk/",
     5            "https://booking.escapetravel.mk/"
    66          ]
    77}
  • backend/GlobeGuru-backend/target/classes/URLsJSON.json

    r1c51912 rcd64b06  
    22  "agencyurls":
    33          [
    4             "https://magelantravel.mk/"
    5 
     4            "https://booking.escapetravel.mk/"
    65          ]
    76}
  • backend/GlobeGuru-backend/target/classes/lastUpdateTime.json

    r1c51912 rcd64b06  
    11{
    2   "lastUpdateTime" : "2025-01-10T18:31:22.019011800"
     2  "lastUpdateTime" : "2025-01-11T00:07:21.694581100"
    33}
  • frontend/css.css

    r1c51912 rcd64b06  
    1515    right: 20px;
    1616}
    17 
     17.infoDiv{
     18    width:400px;
     19}
    1820.login-button {
    1921    background-color: #007bff;
  • frontend/js/formHandler.js

    r1c51912 rcd64b06  
    44
    55    form.addEventListener('submit', function(event) {
    6         event.preventDefault(); // Prevent the default form submission
     6        event.preventDefault();
    77
    8         // Collect form data
    98        const formData = new FormData(form);
    109        const data = {};
     
    1211        let errorMessage = "";
    1312
    14         // Validate form data
    1513        formData.forEach((value, key) => {
    1614            data[key] = value;
     
    3634        loadingOverlay.style.display = 'flex';
    3735
    38         // Send form data to the server
    3936        fetch('/submit', {
    4037            method: 'POST',
     
    4441            body: JSON.stringify(data)
    4542        })
    46             .then(response => response.json())
     43            .then(response => {
     44                if (!response.ok) {
     45                    throw new Error('Network response was not ok ' + response.statusText);
     46                }
     47                return response.json();
     48            })
    4749            .then(data => {
    4850                loadingOverlay.style.display = 'none';
    49 
    5051                const dataList = document.getElementById('givenOptions');
    5152                dataList.innerHTML = '';
     
    5657                    wrapper.appendChild(text);
    5758                    dataList.appendChild(wrapper);
     59                } else {
     60                    data.forEach(item => {
     61                        const optionDiv = document.createElement('div');
     62                        optionDiv.classList.add('option');
     63
     64                        const img = document.createElement('img');
     65                        img.classList.add('image');
     66                        img.src = item.imgSrc || '';
     67                        optionDiv.appendChild(img);
     68                        const WrapperDiv = document.createElement('div');
     69                        optionDiv.appendChild(WrapperDiv);
     70
     71                        const nameParagraph = document.createElement('p');
     72                        nameParagraph.id = 'name';
     73                        nameParagraph.textContent = item.hotelName || 'N/A';
     74                        WrapperDiv.appendChild(nameParagraph);
     75
     76                        const countryParagraph = document.createElement('p');
     77                        countryParagraph.id = 'country';
     78                        countryParagraph.style.fontSize = '20px';
     79                        countryParagraph.textContent = item.country || 'N/A';
     80                        WrapperDiv.appendChild(countryParagraph);
     81
     82                        const dateParagraph = document.createElement('h2');
     83                        dateParagraph.id = 'date';
     84                        dateParagraph.textContent = item.dateRange || 'N/A';
     85                        WrapperDiv.appendChild(dateParagraph);
     86
     87                        const peopleParagraph = document.createElement('p');
     88                        peopleParagraph.id = 'numPeople';
     89                        peopleParagraph.textContent = item.numPeople === 1 ? item.numPeople + " лице" : item.numPeople + " лица";
     90                        WrapperDiv.appendChild(peopleParagraph);
     91
     92                        const priceHeading = document.createElement('h1');
     93                        priceHeading.textContent = 'Цена:';
     94                        WrapperDiv.appendChild(priceHeading);
     95                        const priceParagraph = document.createElement('h2');
     96                        priceParagraph.id = 'price';
     97                        priceParagraph.textContent = (item.price || 0) + " EUR";
     98                        WrapperDiv.appendChild(priceParagraph);
     99
     100                        const infoDiv = document.createElement('div');
     101                        infoDiv.classList.add("infoDiv");
     102                        const typeRoom = document.createElement('p');
     103                        typeRoom.textContent = "Тип на соба: " + (item.type || 'N/A');
     104                        infoDiv.appendChild(typeRoom);
     105                        const plan = document.createElement('p');
     106                        plan.textContent = "Услуга: " + (item.board || 'N/A');
     107                        infoDiv.appendChild(plan);
     108                        const amenities = document.createElement('p');
     109                        amenities.textContent = item.amenities && item.amenities.length > 0 ? "Поволности: " + item.amenities : "Нема информации од агенцијата за вклучените поволности.";
     110                        infoDiv.appendChild(amenities);
     111                        optionDiv.appendChild(infoDiv);
     112
     113                        const link = document.createElement('a');
     114                        link.id = 'link';
     115                        link.href = item.link || '#';
     116                        link.target = '_blank';
     117
     118                        const button = document.createElement('button');
     119                        button.classList.add('btn', 'login-button');
     120                        button.textContent = 'Линк до страна';
     121                        const btnWrapDiv = document.createElement('div');
     122                        btnWrapDiv.classList.add('btnWrapper');
     123                        const favBtn = document.createElement('button');
     124                        favBtn.classList.add('favBtn', 'btn');
     125                        favBtn.id = 'favBtnId';
     126                        favBtn.textContent = 'Додадете во омилени';
     127                        favBtn.setAttribute('data-option-id', item.id);
     128                        favBtn.addEventListener('click', function () {
     129                            const optionId = this.getAttribute('data-option-id');
     130                            saveFavoriteOption(optionId);
     131                        });
     132
     133                        btnWrapDiv.appendChild(link);
     134                        link.appendChild(button);
     135                        btnWrapDiv.appendChild(favBtn);
     136
     137                        optionDiv.appendChild(btnWrapDiv);
     138                        dataList.appendChild(optionDiv);
     139                    });
     140                    console.log('Finished processing data.');
    58141                }
    59                 data.forEach(item => {
    60 
    61                     const optionDiv = document.createElement('div');
    62                     optionDiv.classList.add('option');
    63 
    64                     //image
    65                     const img = document.createElement('img');
    66                     img.classList.add('image');
    67                     img.src = item.imgSrc;
    68                     optionDiv.appendChild(img);
    69                     const WrapperDiv = document.createElement('div');
    70                     optionDiv.appendChild(WrapperDiv);
    71                     //hotel
    72                     const nameParagraph = document.createElement('p');
    73                     nameParagraph.id = 'name';
    74                     nameParagraph.textContent = item.hotelName;
    75                     WrapperDiv.appendChild(nameParagraph);
    76                     //Destination
    77                     const countryParagraph = document.createElement('p');
    78                     countryParagraph.id = 'country';
    79                     countryParagraph.style.fontSize = '20px';
    80                     countryParagraph.textContent = item.country;
    81                     WrapperDiv.appendChild(countryParagraph);
    82                     const dateParagraph = document.createElement('h2');
    83                     dateParagraph.id = 'date';
    84                     dateParagraph.textContent = item.dateRange;
    85                     WrapperDiv.appendChild(dateParagraph);
    86                     const peopleParaghraph = document.createElement('p');
    87                     peopleParaghraph.id = 'numPeople';
    88                     if(item.numPeople === 1){
    89                     peopleParaghraph.textContent = item.numPeople + " лице";
    90                     }
    91                     else peopleParaghraph.textContent = item.numPeople + " лица";
    92                     WrapperDiv.appendChild(peopleParaghraph);
    93                     //price
    94                     const priceHeading = document.createElement('h1');
    95                     priceHeading.textContent = 'Цена:';
    96                     WrapperDiv.appendChild(priceHeading);
    97                     const priceParagraph = document.createElement('h2');
    98                     priceParagraph.id = 'price';
    99                     priceParagraph.textContent = item.price + "EUR";
    100                     WrapperDiv.appendChild(priceParagraph);
    101 
    102 
    103                     const infoDiv = document.createElement('div');
    104                     const typeRoom = document.createElement('p');
    105                     typeRoom.textContent = "Тип на соба: " + item.type;
    106                     infoDiv.appendChild(typeRoom);
    107                     const plan = document.createElement('p');
    108                     plan.textContent = "Услуга: " + item.board;
    109                     infoDiv.appendChild(plan);
    110                     const amenities = document.createElement('p');
    111                     if(item.amenities.length === 0){
    112                         amenities.textContent = "Нема информации од агенцијата за вклучените поволности. ";
    113                     }else amenities.textContent = "Поволности: " + item.amenities;
    114                     infoDiv.appendChild(amenities);
    115                     optionDiv.appendChild(infoDiv);
    116 
    117 
    118                     //  link and button
    119                     const link = document.createElement('a');
    120                     link.id = 'link';
    121                     link.href = item.link; // Use item.link if available
    122                     link.target = '_blank'; // Open link in new tab
    123 
    124                     const button = document.createElement('button');
    125                     button.classList.add('btn', 'login-button');
    126                     button.textContent = 'Линк до страна';
    127                     const btnWrapDiv = document.createElement('div');
    128                     btnWrapDiv.classList.add('btnWrapper');
    129                     const favBtn = document.createElement('button');
    130                     favBtn.classList.add('favBtn','btn');
    131                     favBtn.id = 'favBtnId';
    132                     favBtn.textContent = 'Додадете во омилени';
    133                     favBtn.setAttribute('data-option-id', item.id);
    134                     favBtn.addEventListener('click', function () {
    135                         const optionId = this.getAttribute('data-option-id');
    136                         saveFavoriteOption(optionId);
    137                     });
    138 
    139                     btnWrapDiv.appendChild(link);
    140                     link.appendChild(button);
    141                     btnWrapDiv.appendChild(favBtn);
    142 
    143                     optionDiv.appendChild(btnWrapDiv);
    144                     dataList.appendChild(optionDiv);
    145                 });
    146142                updateFavoriteButtons();
    147143            })
Note: See TracChangeset for help on using the changeset viewer.