Improve images scrapping from bing and show images on the client

This commit is contained in:
2026-03-05 21:58:07 +01:00
parent 7dddb7e0e4
commit ff702d74aa
4 changed files with 73 additions and 10 deletions

30
main.js
View File

@@ -12,21 +12,45 @@ app.listen(PORT, () => {
app.get("/api/getImagesURL", async (req, res) => { app.get("/api/getImagesURL", async (req, res) => {
try { try {
const { q, offset = 0, count = 100 } = req.query; let { q, offset = 1, count = 1000, smart = true } = req.query;
offset = Number(offset);
count = Number(count);
smart = smart === "true";
if (!q) { if (!q) {
return res.status(400).send("Missing 'q' parameter"); return res.status(400).send("Missing 'q' parameter");
} }
let imagesUrls = []; let imagesUrls = [];
let noNewCount = 0;
do { do {
const url = `https://www.bing.com/images/async?q=${encodeURIComponent(q)}&offset=${offset}&count=30`; const url = `https://www.bing.com/images/async?q=${encodeURIComponent(q)}&first=${String(offset)}`;
const response = await fetch(url); const response = await fetch(url);
const html = await response.text(); const html = await response.text();
const urls = extractImageUrls(html); const urls = extractImageUrls(html);
offset += urls.length;
let newImageCount = 0;
for (const url of urls) { for (const url of urls) {
imagesUrls.push(url); if (!imagesUrls.includes(url)) {
if (smart == true) {
try {
const response = await fetch(url, { method: "HEAD" });
const contentType = response.headers.get("content-type");
if (contentType && contentType.startsWith("image/")) {
imagesUrls.push(url);
newImageCount += 1;
}
} catch {}
} else {
imagesUrls.push(url);
newImageCount += 1;
}
}
}
noNewCount = newImageCount == 0 ? noNewCount + 1 : 0;
if (noNewCount > 32) {
break;
} }
} while (imagesUrls.length < count); } while (imagesUrls.length < count);

View File

@@ -1,7 +1,7 @@
<!doctype html> <!doctype html>
<html lang="en"> <html lang="en">
<head> <head>
<title>Ma Web App</title> <title>Images Scrapper JS</title>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="style.css" /> <link rel="stylesheet" href="style.css" />
@@ -11,7 +11,7 @@
<div class="app"> <div class="app">
<main class="content"> <main class="content">
<h1>Images Scrapper JS</h1> <h1>Images Scrapper JS</h1>
<div class="view"> <div class="view" id="view">
<div class="horizontal-div"> <div class="horizontal-div">
<form class="horizontal-div input-form" id="search-form"> <form class="horizontal-div input-form" id="search-form">
<input id="search-input" type="text" placeholder="Search For Images..." /> <input id="search-input" type="text" placeholder="Search For Images..." />
@@ -19,10 +19,17 @@
</form> </form>
<button onclick="download()">Download Images</button> <button onclick="download()">Download Images</button>
</div> </div>
<div id="images-div" class="images-div"></div>
</div> </div>
</main> </main>
</div> </div>
<template id="image-template">
<div class="image-box">
<img id="image" />
</div>
</template>
<script src="script.js"></script> <script src="script.js"></script>
</body> </body>
</html> </html>

View File

@@ -1,7 +1,8 @@
const starsNumber = 1000; const starsNumber = 1000;
const searchInput = document.getElementById("search-input"); const searchInput = document.getElementById("search-input");
const searchForm = document.getElementById("search-form"); const searchForm = document.getElementById("search-form");
const imagesDiv = document.getElementById("images-div");
const imageTemplate = document.getElementById("image-template");
let imagesUrls = []; let imagesUrls = [];
starsCanvas(starsNumber); starsCanvas(starsNumber);
@@ -81,16 +82,20 @@ function starsCanvas(number) {
animate(); animate();
} }
async function getImagesURL(query, offset = 0, count = 100) { async function getImagesURL(query, offset, count, smart) {
const url = `/api/getImagesURL?q=${encodeURIComponent(query)}&offset=${offset}&count=${count}`; const url = `/api/getImagesURL?q=${encodeURIComponent(query)}&offset=${offset}&count=${count}&smart=${smart}`;
const response = await fetch(url); const response = await fetch(url);
const data = await response.json(); const data = await response.json();
for (const url of data) { for (const url of data) {
imagesUrls.push(url); imagesUrls.push(url);
const imageTemplateCopy = imageTemplate.content.cloneNode(true);
imageTemplateCopy.getElementById("image").src = url;
imagesDiv.append(imageTemplateCopy);
} }
console.log(imagesUrls);
} }
async function search() { async function search() {
await getImagesURL(searchInput.value); imagesDiv.replaceChildren();
await getImagesURL(searchInput.value, 1, 1000, true);
} }

View File

@@ -98,3 +98,30 @@ body {
position: fixed; position: fixed;
z-index: -1; z-index: -1;
} }
.images-div {
display: grid;
grid-template-columns: repeat(auto-fill, 150px);
gap: 20px;
justify-content: center;
margin-top: 50px;
}
.image-box {
width: 150px;
height: 150px;
border-radius: 16px;
overflow: hidden;
transition: transform 0.2s;
}
.image-box:hover {
transform: scale(3);
border-radius: 8px;
}
.image-box img {
width: 100%;
height: 100%;
object-fit: cover;
}