mirror of
https://github.com/Gabi-Zar/Images-Scrapper-JS.git
synced 2026-04-17 05:36:06 +02:00
Improve images scrapping from bing and show images on the client
This commit is contained in:
28
main.js
28
main.js
@@ -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) {
|
||||||
|
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);
|
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);
|
||||||
|
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user