Spaces:
Paused
Paused
Download app.py from DsJASPREET/FKScraper: direct link, hf CLI and curl.
- Browser
- Download file 5.9 kB
-
https://huggingface.co/spaces/DsJASPREET/FKScraper/resolve/main/app.py
- Command line
-
hf download hf://spaces/DsJASPREET/FKScraper/app.py
-
curl -L -o app.py https://huggingface.co/spaces/DsJASPREET/FKScraper/resolve/main/app.py
5.9 kB
| """Gradio version of the Flipkart ISBN price scraper. | |
| Run with: | |
| python "Gradio version.py" | |
| """ | |
| from __future__ import annotations | |
| import random | |
| import tempfile | |
| import time | |
| from pathlib import Path | |
| from typing import Optional | |
| import gradio as gr | |
| import pandas as pd | |
| import requests | |
| from bs4 import BeautifulSoup | |
| USER_AGENTS = ( | |
| "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 " | |
| "(KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36", | |
| "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:141.0) " | |
| "Gecko/20100101 Firefox/141.0", | |
| "Mozilla/5.0 (Macintosh; Intel Mac OS X 15_5) AppleWebKit/537.36 " | |
| "(KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36", | |
| "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 " | |
| "(KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36", | |
| "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/605.1.15 " | |
| "(KHTML, like Gecko) Version/18.5 Safari/605.1.15", | |
| "Mozilla/5.0 (Macintosh; Intel Mac OS X 15_5; rv:141.0) " | |
| "Gecko/20100101 Firefox/141.0", | |
| "Mozilla/5.0 (X11; Linux x86_64; rv:141.0) Gecko/20100101 Firefox/141.0", | |
| "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 " | |
| "(KHTML, like Gecko) Edge/138.0.0.0", | |
| "Mozilla/5.0 (Macintosh; Intel Mac OS X 15_5) AppleWebKit/537.36 " | |
| "(KHTML, like Gecko) Edge/138.0.0.0", | |
| "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 " | |
| "(KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36", | |
| ) | |
| REQUEST_TIMEOUT_SECONDS = 20 | |
| REQUEST_DELAY_SECONDS = 0.01 # Retains the small delay used by the Streamlit app. | |
| def load_workbook(file_path: Optional[str]): | |
| """Read the ISBN column once, when the user uploads a workbook.""" | |
| if not file_path: | |
| return "Upload an Excel file to begin.", None | |
| try: | |
| source = pd.read_excel( | |
| file_path, | |
| header=None, | |
| dtype={0: "string"}, | |
| keep_default_na=False, | |
| ) | |
| except Exception as exc: | |
| return f"Could not read the workbook: {exc}", None | |
| if source.empty: | |
| return "The workbook does not contain any ISBN rows.", None | |
| # The original app expects one input column. Ignore accidental extra columns | |
| # rather than letting them overwrite the position reserved for Price. | |
| dataframe = source.iloc[:, [0]].copy() | |
| dataframe.columns = ["ISBN"] | |
| return f"File loaded successfully ({len(dataframe)} rows). Click Start processing.", dataframe | |
| def get_flipkart_price(session: requests.Session, isbn: str) -> Optional[str]: | |
| """Return the last price found by the selector used in the original app.""" | |
| response = session.get( | |
| "https://www.flipkart.com/books/pr", | |
| params={ | |
| "sid": "bks", | |
| "q": isbn, | |
| "otracker": "categorytree", | |
| }, | |
| headers={"User-Agent": random.choice(USER_AGENTS)}, | |
| timeout=REQUEST_TIMEOUT_SECONDS, | |
| ) | |
| response.raise_for_status() | |
| prices = [ | |
| price.get_text(strip=True).lstrip("₹") | |
| for price in BeautifulSoup(response.text, "lxml").select("div.hZ3P6w") | |
| ] | |
| return prices[-1] if prices else None | |
| def process_isbns(dataframe, progress=gr.Progress(track_tqdm=False)): | |
| """Fetch prices and produce an ISBN/Price CSV file.""" | |
| if dataframe is None or len(dataframe) == 0: | |
| return "Please upload a non-empty Excel file first.", None, gr.DownloadButton(visible=False) | |
| result = dataframe.copy() | |
| result["Price"] = pd.NA | |
| failures = 0 | |
| total_rows = len(result) | |
| with requests.Session() as session: | |
| for row_number, (index, isbn) in enumerate(result["ISBN"].items(), start=1): | |
| isbn_text = str(isbn).strip() | |
| if isbn_text: | |
| try: | |
| result.at[index, "Price"] = get_flipkart_price(session, isbn_text) | |
| except requests.RequestException: | |
| failures += 1 | |
| progress( | |
| (row_number, total_rows), | |
| desc=f"Processing row {row_number} of {total_rows}", | |
| ) | |
| time.sleep(REQUEST_DELAY_SECONDS) | |
| with tempfile.NamedTemporaryFile( | |
| mode="w", | |
| suffix=".csv", | |
| prefix="flipkart_prices_", | |
| encoding="utf-8-sig", | |
| newline="", | |
| delete=False, | |
| ) as output_file: | |
| result.to_csv(output_file, index=False) | |
| output_path = Path(output_file.name) | |
| message = "Processing complete!" | |
| if failures: | |
| message += f" {failures} request(s) could not be completed; their prices are blank." | |
| return message, result, gr.DownloadButton( | |
| value=str(output_path), | |
| label="Download processed file", | |
| visible=True, | |
| ) | |
| with gr.Blocks(title="Flipkart Scraper") as app: | |
| gr.Markdown( | |
| """ | |
| # Flipkart Scraper | |
| ### Instructions | |
| - Upload an **Excel (.xlsx, .xls, or .xlsm)** file. | |
| - The workbook should have ISBNs in the first column, with no header row. | |
| - Use one ISBN per row. | |
| - Click **Start processing**, then download the resulting CSV. | |
| - Uploaded data is used only for the current session. | |
| """ | |
| ) | |
| workbook_state = gr.State(value=None) | |
| workbook = gr.File( | |
| label="Upload an Excel file", | |
| file_types=[".xlsx", ".xls", ".xlsm"], | |
| type="filepath", | |
| ) | |
| status = gr.Markdown("Upload an Excel file to begin.") | |
| start_button = gr.Button("Start processing", variant="primary") | |
| preview = gr.Dataframe(label="Processed data", interactive=False) | |
| download = gr.DownloadButton("Download processed file", visible=False) | |
| workbook.change( | |
| load_workbook, | |
| inputs=workbook, | |
| outputs=[status, workbook_state], | |
| ) | |
| start_button.click( | |
| process_isbns, | |
| inputs=workbook_state, | |
| outputs=[status, preview, download], | |
| ) | |
| if __name__ == "__main__": | |
| app.queue().launch() | |