Spaces:
No application file
No application file
Delete app.py
Browse files
app.py
DELETED
|
@@ -1,134 +0,0 @@
|
|
| 1 |
-
import streamlit as st
|
| 2 |
-
import requests
|
| 3 |
-
from bs4 import BeautifulSoup
|
| 4 |
-
import pandas as pd
|
| 5 |
-
from concurrent.futures import ProcessPoolExecutor, as_completed
|
| 6 |
-
import base64
|
| 7 |
-
|
| 8 |
-
# Informations personnelles
|
| 9 |
-
photo_url = "https://github.com/CodingYayaToure/Premier_projet/blob/main/yaya_cncs-modified%20(1).png?raw=true"
|
| 10 |
-
prenom = "Yaya"
|
| 11 |
-
nom = "Toure"
|
| 12 |
-
email = "yaya.toure@unchk.edu.sn"
|
| 13 |
-
whatsapps_url = "https://wa.me/message/GW7RWRW3GR4WN1"
|
| 14 |
-
linkedin_url = "https://www.linkedin.com/in/yaya-toure-8251a4280/"
|
| 15 |
-
github_url = "https://github.com/CodingYayaToure"
|
| 16 |
-
universite = "UNCHK"
|
| 17 |
-
formation = "Licence Analyse Numerique et Modelisation | Master Calcul scientifique et Modelisation"
|
| 18 |
-
certification = "Collecte et Fouille de Donnees (UADB-CNAM Paris)"
|
| 19 |
-
|
| 20 |
-
# URL de base pour le scraping avec pagination
|
| 21 |
-
base_urls = {
|
| 22 |
-
"Voitures": "https://dakar-auto.com/senegal/voitures-4?page={}",
|
| 23 |
-
"Location voitures": "https://dakar-auto.com/senegal/location-de-voitures-19?page={}",
|
| 24 |
-
"Motos": "https://dakar-auto.com/senegal/motos-and-scooters-3?page={}"
|
| 25 |
-
}
|
| 26 |
-
|
| 27 |
-
def scrape_page(page_number, base_url, category):
|
| 28 |
-
url = base_url.format(page_number)
|
| 29 |
-
response = requests.get(url)
|
| 30 |
-
data = []
|
| 31 |
-
|
| 32 |
-
if response.status_code == 200:
|
| 33 |
-
soup = BeautifulSoup(response.text, 'html.parser')
|
| 34 |
-
listings = soup.find_all('div', class_='listing-card')
|
| 35 |
-
|
| 36 |
-
for listing in listings:
|
| 37 |
-
try:
|
| 38 |
-
title_element = listing.find('h2', class_='listing-card__header__title')
|
| 39 |
-
marque_modele = title_element.text.strip() if title_element else 'N/A'
|
| 40 |
-
marque, modele = marque_modele.split()[:2] if len(marque_modele.split()) >= 2 else (marque_modele, 'N/A')
|
| 41 |
-
année = marque_modele.split()[-1] if marque_modele.split()[-1].isdigit() else 'N/A'
|
| 42 |
-
attributes = listing.find('ul', class_='listing-card__attribute-list')
|
| 43 |
-
kilometrage, boite_de_vitesse, carburant, référence = 'N/A', 'N/A', 'N/A', 'N/A'
|
| 44 |
-
if attributes:
|
| 45 |
-
for li in attributes.find_all('li', class_='listing-card__attribute'):
|
| 46 |
-
if 'km' in li.text:
|
| 47 |
-
kilometrage = li.text.strip()
|
| 48 |
-
elif category != "Motos":
|
| 49 |
-
if 'Automatique' in li.text or 'Manuelle' in li.text:
|
| 50 |
-
boite_de_vitesse = li.text.strip()
|
| 51 |
-
elif 'Essence' in li.text or 'Diesel' in li.text:
|
| 52 |
-
carburant = li.text.strip()
|
| 53 |
-
if 'Ref.' in li.text:
|
| 54 |
-
référence = li.text.strip().replace('Ref. ', '')
|
| 55 |
-
price_element = listing.find('h3', class_='listing-card__header__price')
|
| 56 |
-
prix = price_element.text.strip() if price_element else 'N/A'
|
| 57 |
-
town_element = listing.find('span', class_='town-suburb')
|
| 58 |
-
province_element = listing.find('span', class_='province')
|
| 59 |
-
town = town_element.text.strip() if town_element else ''
|
| 60 |
-
province = province_element.text.strip() if province_element else ''
|
| 61 |
-
adresse_de_vente = f"{town}_{province}".replace(' ', '_').replace(',', '_').strip('_')
|
| 62 |
-
owner_element = listing.find('p', class_='time-author')
|
| 63 |
-
proprietaire = owner_element.text.strip().replace(' ', '_') if owner_element else 'N/A'
|
| 64 |
-
|
| 65 |
-
if category == "Motos":
|
| 66 |
-
data.append([marque, modele, année, kilometrage, prix, référence, adresse_de_vente, proprietaire])
|
| 67 |
-
else:
|
| 68 |
-
data.append([marque, modele, année, kilometrage, boite_de_vitesse, carburant, prix, référence, adresse_de_vente, proprietaire])
|
| 69 |
-
except AttributeError as e:
|
| 70 |
-
print(f"Error processing listing on page {page_number}: {e}")
|
| 71 |
-
continue
|
| 72 |
-
return data
|
| 73 |
-
|
| 74 |
-
def scrape_data(max_pages, category):
|
| 75 |
-
base_url = base_urls[category]
|
| 76 |
-
data = []
|
| 77 |
-
with ProcessPoolExecutor(max_workers=10) as executor:
|
| 78 |
-
futures = {executor.submit(scrape_page, page, base_url, category): page for page in range(1, max_pages + 1)}
|
| 79 |
-
for future in as_completed(futures):
|
| 80 |
-
page_number = futures[future]
|
| 81 |
-
try:
|
| 82 |
-
result = future.result()
|
| 83 |
-
if result:
|
| 84 |
-
data.extend(result)
|
| 85 |
-
print(f"Page {page_number} scraped successfully.")
|
| 86 |
-
except Exception as e:
|
| 87 |
-
print(f"Error scraping page {page_number}: {e}")
|
| 88 |
-
|
| 89 |
-
if category == "Motos":
|
| 90 |
-
columns = ['Marque', 'Modèle', 'Année', 'Kilométrage', 'Prix', 'Référence', 'Adresse_de_Vente', 'Propriétaire']
|
| 91 |
-
else:
|
| 92 |
-
columns = ['Marque', 'Modèle', 'Année', 'Kilométrage', 'Boîte_de_Vitesse', 'Carburant', 'Prix', 'Référence', 'Adresse_de_Vente', 'Propriétaire']
|
| 93 |
-
df = pd.DataFrame(data, columns=columns)
|
| 94 |
-
return df
|
| 95 |
-
|
| 96 |
-
# Interface Streamlit
|
| 97 |
-
st.sidebar.title("Informations personnelles")
|
| 98 |
-
st.sidebar.image(photo_url, caption=f"{prenom} {nom}", width=200)
|
| 99 |
-
st.sidebar.write(f"Nom: {prenom} {nom}")
|
| 100 |
-
st.sidebar.write(f"Email: {email}")
|
| 101 |
-
st.sidebar.markdown(f"[Whatsapps]({whatsapps_url})")
|
| 102 |
-
st.sidebar.markdown(f"[LinkedIn]({linkedin_url})")
|
| 103 |
-
st.sidebar.markdown(f"[GitHub]({github_url})")
|
| 104 |
-
st.sidebar.write(f"Université: {universite}")
|
| 105 |
-
st.sidebar.write(f"**Formations:** {formation}")
|
| 106 |
-
st.sidebar.write(f"**Certification:** {certification}")
|
| 107 |
-
|
| 108 |
-
st.title("Scraping des données de véhicules")
|
| 109 |
-
|
| 110 |
-
|
| 111 |
-
st.write("""
|
| 112 |
-
Bienvenue sur Fluide WEBScrapping, une application professionnelle dédiée à l'extraction automatisée de données de véhicules de https://dakar-auto.com. Que vous soyez à la recherche de voitures, de voitures en location ou de motos, notre outil vous permet de scraper les informations essentielles de manière efficace et en un temps record grâce à la parallélisation. Voici les détails que nous collectons : marque, modèle, année, kilométrage, boîte de vitesse, carburant, prix, référence, adresse de vente, et propriétaire.
|
| 113 |
-
|
| 114 |
-
### Avantages de la parallélisation dans le web scraping
|
| 115 |
-
|
| 116 |
-
La parallélisation optimise le web scraping en permettant l'exécution simultanée de multiples tâches de scraping, ce qui réduit considérablement le temps de traitement global. Elle exploite les capacités multicœurs des processeurs, maximisant l'efficacité des ressources matérielles. Cette technique améliore la réactivité de l'application, la rendant idéale pour les mises à jour fréquentes de données. De plus, la parallélisation permet de gérer de grands volumes de données de manière scalable, assurant une collecte fiable et robuste même en cas de défaillance partielle.
|
| 117 |
-
|
| 118 |
-
En somme, la parallélisation rend Fluide WEBScrapping plus rapide, efficace et fiable, offrant ainsi une expérience optimale pour l'extraction de données de véhicules.
|
| 119 |
-
""")
|
| 120 |
-
|
| 121 |
-
category = st.selectbox("Choisissez la catégorie", ["Voitures", "Location voitures", "Motos"])
|
| 122 |
-
max_pages = st.number_input("Nombre de pages à scraper", min_value=1, max_value=2049, value=1)
|
| 123 |
-
scrape_button = st.button("Scraper les données")
|
| 124 |
-
|
| 125 |
-
if scrape_button:
|
| 126 |
-
with st.spinner("Scraping en cours..."):
|
| 127 |
-
df = scrape_data(max_pages, category)
|
| 128 |
-
st.success("Scraping terminé!")
|
| 129 |
-
st.dataframe(df)
|
| 130 |
-
|
| 131 |
-
csv = df.to_csv(index=False, encoding='utf-8')
|
| 132 |
-
b64 = base64.b64encode(csv.encode()).decode() # some strings
|
| 133 |
-
href = f'<a href="data:file/csv;base64,{b64}" download="{category}_data.csv">Télécharger le fichier CSV</a>'
|
| 134 |
-
st.markdown(href, unsafe_allow_html=True)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|