Jack1808's picture
Deploy Scrapling FastAPI scraper to Docker Space
76c00ef verified
Raw
History Blame Contribute Delete
3.84 kB
import sys
print(">>> STARTING APP INITIALIZATION <<<", flush=True)
from fastapi import FastAPI
from pydantic import BaseModel
print(">>> FASTAPI IMPORTED <<<", flush=True)
import urllib.parse
import re
import json
from fastapi.responses import RedirectResponse
app = FastAPI()
@app.get("/")
def read_root():
return RedirectResponse(url="/docs")
class QueryRequest(BaseModel):
query: str
@app.post("/scrape/geocode")
def scrape_geocode(req: QueryRequest):
from scrapling import Fetcher
fetcher = Fetcher()
url = f"https://nominatim.openstreetmap.org/search?q={urllib.parse.quote(req.query)}&format=json&limit=1"
try:
response = fetcher.get(url)
data = json.loads(response.text)
if data and len(data) > 0:
return {
"lat": float(data[0]["lat"]),
"lng": float(data[0]["lon"]),
"formattedAddress": data[0]["display_name"]
}
except Exception as e:
print("Geocode Error:", e)
pass
# Fallback coordinate regex (naive)
search_url = f"https://html.duckduckgo.com/html/?q={urllib.parse.quote(req.query + ' coordinates lat long')}"
try:
resp = fetcher.get(search_url)
matches = re.findall(r'(-?\d+\.\d{3,})[^\d]+(-?\d+\.\d{3,})', resp.text)
if matches:
return {"lat": float(matches[0][0]), "lng": float(matches[0][1]), "formattedAddress": req.query}
except Exception:
pass
return {"lat": 0, "lng": 0, "formattedAddress": req.query}
@app.post("/scrape/details")
def scrape_details(req: QueryRequest):
from scrapling import Fetcher
fetcher = Fetcher()
search_url = f"https://html.duckduckgo.com/html/?q={urllib.parse.quote(req.query + ' tourism description rating')}"
try:
resp = fetcher.get(search_url)
snippets = []
# In duckduckgo html, snippets are in .result__snippet
for el in resp.css('.result__snippet'):
if el.text:
snippets.append(el.text)
description = " ".join(snippets[:3])
if not description:
description = "A wonderful destination worth visiting."
return {
"rating": 4.5, # Static fallback as parsing HTML for real ratings is extremely fragile
"ratingsCount": 120,
"address": req.query,
"description": description[:350] + "..." if len(description) > 350 else description
}
except Exception as e:
print("Details error:", e)
return {
"rating": 4.5,
"ratingsCount": 100,
"address": req.query,
"description": f"Explore the beauty and culture of {req.query}. A highly recommended spot for travelers."
}
@app.post("/scrape/images")
def scrape_images(req: QueryRequest):
from scrapling import Fetcher
fetcher = Fetcher()
# Pexels allows scraping more easily than google images
search_url = f"https://www.pexels.com/search/{urllib.parse.quote(req.query)}/"
try:
resp = fetcher.get(search_url)
images = []
for img in resp.css('img'):
src = img.attrib.get('src')
if src and 'images.pexels.com/photos' in src:
# Remove query params to get high res
images.append(src.split('?')[0] + "?auto=compress&cs=tinysrgb&w=800")
if images:
# Deduplicate and return top 5
return {"images": list(dict.fromkeys(images))[:5]}
except Exception as e:
print("Images error:", e)
pass
return {"images": ["https://images.unsplash.com/photo-1476514525535-07fb3b4ae5f1?auto=format&fit=crop&q=80&w=1200"]}
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="127.0.0.1", port=8000)