Image-hub-api / app.py
Wasifali95's picture
Upload app.py
6a8112b verified
Raw
History Blame Contribute Delete
8.29 kB
import requests
import re
import random
import json
from fastapi import FastAPI, Query
from fastapi.middleware.cors import CORSMiddleware
app = FastAPI(
title="ImageHub API",
description="Search high-quality images from multiple sources.",
version="3.2.0"
)
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_methods=["*"],
allow_headers=["*"],
)
# ------------------------------------------------------------------
# BING IMAGES SCRAPER
# ------------------------------------------------------------------
def scrape_bing(query: str, page: int = 1, per_page: int = 30):
offset = (page - 1) * per_page + 1
url = f"https://www.bing.com/images/search?q={requests.utils.quote(query)}&first={offset}"
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
}
try:
resp = requests.get(url, headers=headers, timeout=10)
if resp.status_code != 200:
return []
html = resp.text
pattern = r'm="\{([^"]*)\}"'
matches = re.findall(pattern, html)
images = []
for match in matches:
json_str = '{"' + match.replace('"', '"') + '"}'
try:
data = json.loads(json_str)
except:
data = {}
murl = re.search(r'murl":"([^"]+)"', json_str)
if murl:
data['murl'] = murl.group(1)
turl = re.search(r'turl":"([^"]+)"', json_str)
if turl:
data['turl'] = turl.group(1)
title = re.search(r't":"([^"]+)"', json_str)
if title:
data['t'] = title.group(1)
w = re.search(r'w":"(\d+)"', json_str)
if w:
data['w'] = w.group(1)
h = re.search(r'h":"(\d+)"', json_str)
if h:
data['h'] = h.group(1)
img_id = re.search(r'id":"([^"]+)"', json_str)
if img_id:
data['id'] = img_id.group(1)
if data.get('murl'):
images.append({
"id": data.get('id', f"img_{len(images)}"),
"url": data['murl'],
"thumbnail": data.get('turl', data['murl']),
"width": int(data.get('w', 0)),
"height": int(data.get('h', 0)),
"tags": data.get('t', query)[:200],
"likes": 0
})
if len(images) >= per_page:
break
return images[:per_page]
except Exception as e:
print(f"Bing error: {e}")
return []
# ------------------------------------------------------------------
# PINTEREST API 1 (Working - from bj-devs)
# ------------------------------------------------------------------
def fetch_pinterest_api_1(query: str, per_page: int = 30):
"""Primary Pinterest API - https://pinterest-search.apis-bj-devs.workers.dev/"""
url = f"https://pinterest-search.apis-bj-devs.workers.dev/?search={requests.utils.quote(query)}&limit={per_page}"
try:
resp = requests.get(url, timeout=10)
if resp.status_code != 200:
return []
data = resp.json()
if not data.get("status"):
return []
pins = data.get("result", {}).get("pins", [])
images = []
for pin in pins:
media = pin.get("media", {})
images_data = media.get("images", {})
img_url = images_data.get("orig") or images_data.get("large") or images_data.get("medium") or ""
if img_url:
images.append({
"id": pin.get("id", f"img_{len(images)}"),
"url": img_url,
"thumbnail": images_data.get("small", img_url),
"width": 0,
"height": 0,
"tags": pin.get("title", query)[:200],
"likes": 0
})
return images
except Exception as e:
print(f"Pinterest API 1 error: {e}")
return []
# ------------------------------------------------------------------
# PINTEREST API 2 (Backup/Alternative)
# ------------------------------------------------------------------
def fetch_pinterest_api_2(query: str, per_page: int = 30):
"""Secondary Pinterest scraper as backup"""
url = f"https://www.pinterest.com/resource/BaseSearchResource/get/"
params = {
"source_url": f"/search/pins/?q={requests.utils.quote(query)}",
"data": json.dumps({
"options": {
"query": query,
"page_size": per_page,
"scope": "pins",
"field_set_key": "unauth_react"
}
})
}
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
"Accept": "application/json"
}
try:
resp = requests.get(url, params=params, headers=headers, timeout=10)
if resp.status_code != 200:
return []
data = resp.json()
results = data.get("resource_response", {}).get("data", {}).get("results", [])
images = []
for i, pin in enumerate(results[:per_page]):
images_data = pin.get("images", {})
if images_data:
best_quality = max(images_data.keys(), key=lambda x: images_data[x].get("width", 0))
img_url = images_data[best_quality].get("url")
if img_url:
images.append({
"id": f"img_{pin.get('id', i)}",
"url": img_url,
"thumbnail": img_url,
"width": images_data[best_quality].get("width", 0),
"height": images_data[best_quality].get("height", 0),
"tags": pin.get("title", query)[:200],
"likes": pin.get("like_count", 0)
})
return images
except Exception as e:
print(f"Pinterest API 2 error: {e}")
return []
# ------------------------------------------------------------------
# MAIN HANDLER (Bing + Both Pinterest APIs)
# ------------------------------------------------------------------
def search_handler(q: str, per_page: int = 30, page: int = 1):
all_results = []
# 1. Bing (with pagination)
bing_images = scrape_bing(q, page, per_page)
all_results.extend(bing_images)
# 2. Primary Pinterest API (first page only)
needed = per_page - len(all_results)
if needed > 0 and page == 1:
pinterest_images_1 = fetch_pinterest_api_1(q, needed)
all_results.extend(pinterest_images_1)
needed = per_page - len(all_results)
# 3. Secondary Pinterest API (if still needed)
if needed > 0 and page == 1:
pinterest_images_2 = fetch_pinterest_api_2(q, needed)
all_results.extend(pinterest_images_2)
# Shuffle for variety
random.shuffle(all_results)
all_results = all_results[:per_page]
return {
"status": "success",
"query": q,
"page": page,
"total": len(all_results),
"results": all_results,
"developer": {
"name": "WASIF ALI",
"telegram": "@THE_FREE_HACKS"
}
}
# ------------------------------------------------------------------
# FASTAPI ENDPOINTS
# ------------------------------------------------------------------
@app.get("/search.json")
def search_json(
q: str = Query(..., description="Search keyword"),
per_page: int = Query(30, ge=1, le=100),
page: int = Query(1, ge=1)
):
return search_handler(q, per_page, page)
@app.get("/search")
def search(
q: str = Query(...),
per_page: int = Query(30, ge=1, le=100),
page: int = Query(1, ge=1)
):
return search_handler(q, per_page, page)
@app.get("/")
def root():
return {
"message": "ImageHub API is live. Use /search.json?q=keyword",
"developer": {
"name": "WASIF ALI",
"telegram": "@THE_FREE_HACKS"
}
}