ElegantSolutions's picture
Creating app.py File
56a1920 verified
Raw
History Blame Contribute Delete
8.12 kB
# Importing Necessary Libraries
import streamlit as st
import requests
import json
from datetime import datetime
import time
from docx import Document
import tempfile
import pandas as pd
import zipfile
import os
# Function to Scrape the User Profile and Save the Result in the DOCx File
def process_dataset(api_token, input_url, email_id, phone_number):
"""
Triggers a dataset and fetches the snapshot from BrightData API, saving the result to a DOCx file.
Parameters:
api_token (str): The authorization token for API access.
input_url (str): The LinkedIn URL to be processed.
email_id (str): The email ID to be added to the profile data.
phone_number (str): The phone number to be added to the profile data.
Returns:
str: Path to the DOCx file.
"""
print("Starting process_dataset")
print(f"API Token: {api_token[:5]}***") # Masked for security
print(f"Input URL: {input_url}")
print(f"Email ID: {email_id}, Phone Number: {phone_number}")
headers = {
"Authorization": f"Bearer {api_token}",
"Content-Type": "application/json"
}
# Trigger the BrightData API to fetch the data
trigger_url = "https://api.brightdata.com/datasets/v3/trigger"
trigger_payload = [{"url": input_url}]
trigger_params = {"dataset_id": "gd_l1viktl72bvl7bjuj0", "include_errors": "true"}
try:
print("Triggering BrightData API...")
trigger_response = requests.post(trigger_url, json=trigger_payload, headers=headers, params=trigger_params)
print(f"Trigger Response Status Code: {trigger_response.status_code}")
if trigger_response.status_code == 200:
trigger_data = trigger_response.json()
print(f"Trigger Response Data: {trigger_data}")
snapshot_id = trigger_data.get('snapshot_id', None)
if not snapshot_id:
print("Snapshot ID not found in response.")
return "Error: Snapshot ID not found in the response"
else:
print("Failed to trigger dataset.")
return f"Error: Failed to trigger dataset with status code {trigger_response.status_code}"
except Exception as e:
print(f"Exception during API trigger: {e}")
return f"Error: {str(e)}"
# Fetch the snapshot
snapshot_url = f"https://api.brightdata.com/datasets/v3/snapshot/{snapshot_id}"
snapshot_params = {"format": "json"}
attempts = 0
max_retries = 10
retry_interval = 10 # seconds
snapshot_data = None
while attempts < max_retries:
try:
print(f"Fetching snapshot (Attempt {attempts + 1})...")
snapshot_response = requests.get(snapshot_url, headers=headers, params=snapshot_params)
print(f"Snapshot Response Status Code: {snapshot_response.status_code}")
if snapshot_response.status_code == 200:
snapshot_data = snapshot_response.json()
print("Snapshot data retrieved successfully.")
break
elif snapshot_response.status_code == 202:
print("Snapshot not ready yet. Retrying...")
time.sleep(retry_interval)
attempts += 1
else:
print("Failed to fetch snapshot.")
return f"Error: Failed to fetch snapshot with status code {snapshot_response.status_code}"
except Exception as e:
print(f"Exception during snapshot fetch: {e}")
return f"Error: {str(e)}"
if not snapshot_data:
print("Snapshot data could not be retrieved after retries.")
return "Error: Snapshot data could not be retrieved after multiple retries"
if isinstance(snapshot_data, list) and len(snapshot_data) > 0:
profile_data = snapshot_data[0]
print(f"Profile Data: {profile_data}")
else:
print("No data found in snapshot.")
return "Error: No data found in snapshot"
profile_data['Email_ID'] = email_id
profile_data['Phone_Number'] = phone_number
# Generate DOCx file from the scraped data
print("Generating DOCx file...")
doc = Document()
doc.add_heading('LinkedIn Profile Data', 0)
def add_json_to_word(data, parent=None):
if isinstance(data, dict):
for key, value in data.items():
parent.add_paragraph(f"{key}:")
add_json_to_word(value, parent=parent)
elif isinstance(data, list):
for item in data:
add_json_to_word(item, parent=parent)
else:
parent.add_paragraph(f"{data}")
add_json_to_word(profile_data, parent=doc)
temp_file = tempfile.NamedTemporaryFile(delete=False, suffix=".docx")
doc.save(temp_file.name)
print(f"DOCx file saved at {temp_file.name}")
return temp_file
# Streamlit Interface
def create_streamlit_interface():
st.title("LinkedIn Profile Scraper Using BrightData")
api_token = st.text_input("BrightData Token", placeholder="Enter BrightData Token", type="password")
uploaded_file = st.file_uploader("Upload CSV File", type=["csv"])
if uploaded_file and api_token:
print("CSV file and API token received.")
df = pd.read_csv(uploaded_file)
valid_rows = df[df['LinkedIn Link'].notna()]
print(f"Number of valid rows: {len(valid_rows)}")
temp_files = [] # List to store file paths
for index, row in valid_rows.iterrows():
try:
email = row['Email Address'] if pd.notna(row['Email Address']) else "None"
phone = row['Mobile Number'] if pd.notna(row['Mobile Number']) else "None"
linkedin = row['LinkedIn Link']
print(f"Processing LinkedIn Profile: {linkedin}")
result_file = process_dataset(api_token, linkedin, email, phone)
if isinstance(result_file, str) and result_file.startswith("Error"):
print(f"Error for {linkedin}: {result_file}")
st.error(f"Error for {linkedin}: {result_file}")
continue
temp_files.append(result_file.name)
print(f"Successfully processed {linkedin}")
with open(result_file.name, "rb") as f:
st.download_button(
label=f"Download Resume for {row.get('Applicant Name', 'Unknown')}",
data=f,
file_name=f"Resume_{row.get('Applicant Name', 'Unknown')}_{datetime.now().strftime('%Y%m%d_%H%M%S')}.docx",
mime="application/vnd.openxmlformats-officedocument.wordprocessingml.document"
)
except Exception as e:
print(f"Unexpected error for {row['LinkedIn Link']}: {e}")
st.error(f"Unexpected error for {row['LinkedIn Link']}: {str(e)}")
if temp_files:
print("Creating ZIP file for all resumes...")
zip_file_path = tempfile.NamedTemporaryFile(delete=False, suffix=".zip").name
with zipfile.ZipFile(zip_file_path, 'w') as zipf:
for file_path in temp_files:
arcname = os.path.basename(file_path)
zipf.write(file_path, arcname=arcname)
print(f"ZIP file created at {zip_file_path}")
# Provide the ZIP file for download
with open(zip_file_path, "rb") as f:
st.download_button(
label="Download All Resumes as ZIP",
data=f,
file_name=f"All_Resumes_{datetime.now().strftime('%Y%m%d_%H%M%S')}.zip",
mime="application/zip"
)
elif not api_token:
print("API token not provided.")
st.warning("Please enter your BrightData API Token.")
elif not uploaded_file:
print("CSV file not uploaded.")
st.warning("Please upload a CSV file.")
# Run the Streamlit app
if __name__ == "__main__":
print("Starting Streamlit application...")
create_streamlit_interface()