carbot-mixtral / scraper.py
imstevenleo's picture
Updated CarBot with Falcon-Arabic-7B-Instruct and enhanced database
ce348e1
raw
history blame
6.7 kB
import requests
from bs4 import BeautifulSoup
import logging
import json
import time
from typing import List, Dict
from random import choice
from datetime import datetime
# Logging setup
logging.basicConfig(
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
level=logging.INFO,
handlers=[logging.FileHandler("scraper.log", encoding='utf-8'), logging.StreamHandler()]
)
logger = logging.getLogger(__name__)
# قائمة User-Agent عشوائية لتجنب الحظر
USER_AGENTS = [
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.1 Safari/605.1.15",
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.107 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:89.0) Gecko/20100101 Firefox/89.0"
]
# Headers لمحاكاة متصفح حقيقي
def get_headers() -> dict:
return {
"User-Agent": choice(USER_AGENTS),
"Accept-Language": "en-US,en;q=0.9",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
"Connection": "keep-alive"
}
def scrape_website(url: str, retries: int = 3) -> List[Dict]:
"""
جمع بيانات السيارات من موقع ويب معين مع إعادة المحاولة عند الفشل.
"""
for attempt in range(retries):
try:
response = requests.get(url, headers=get_headers(), timeout=10)
response.raise_for_status()
soup = BeautifulSoup(response.content, "html.parser")
cars_data = []
# محددات عامة (يجب تعديلها حسب هيكلية كل موقع)
car_listings = soup.select(".car-item, .listing-item, .product-item, .car-listing, .ad-item, .vehicle-item")
if not car_listings:
logger.warning(f"لم يتم العثور على قوائم سيارات في {url}. تحققي من المحددات.")
return cars_data
for car in car_listings:
try:
car_data = {}
# تحقق من وجود العنصر قبل استخراج النص
name_elem = car.select_one(".car-title, .product-title, .listing-title, .ad-title, .vehicle-title, h2, h3")
car_data["name"] = name_elem.text.strip() if name_elem else "غير محدد"
price_elem = car.select_one(".car-price, .price, .product-price, .listing-price, .ad-price")
car_data["price"] = price_elem.text.strip() if price_elem else "غير محدد"
year_elem = car.select_one(".car-year, .year, .model-year")
car_data["model_year"] = year_elem.text.strip() if year_elem else "غير محدد"
location_elem = car.select_one(".car-location, .location, .city")
car_data["location"] = location_elem.text.strip() if location_elem else "غير محدد"
desc_elem = car.select_one(".car-description, .description, .details")
car_data["description"] = desc_elem.text.strip() if desc_elem else "غير محدد"
# إضافة بيانات الصيانة وقطع الغيار
maintenance_elem = car.select_one(".maintenance, .service-info")
car_data["maintenance"] = maintenance_elem.text.strip() if maintenance_elem else "غير محدد"
spare_parts_elem = car.select_one(".spare-parts, .parts-info")
car_data["spare_parts"] = spare_parts_elem.text.strip() if spare_parts_elem else "غير محدد"
car_data["source"] = url.split("//")[1].split("/")[0]
car_data["scraped_at"] = datetime.now().isoformat()
cars_data.append(car_data)
logger.info(f"تم جمع بيانات: {car_data['name']} - {car_data['price']} من {url}")
except Exception as e:
logger.error(f"خطأ في استخراج بيانات سيارة من {url}: {str(e)}")
continue
return cars_data
except requests.exceptions.RequestException as e:
logger.error(f"خطأ في الاتصال بـ {url} (محاولة {attempt + 1}/{retries}): {str(e)}")
if attempt < retries - 1:
time.sleep(5 * (attempt + 1)) # تأخير متزايد
else:
return []
except Exception as e:
logger.error(f"خطأ غير متوقع في scrape_website لـ {url}: {str(e)}")
return []
def save_data(data: List[Dict], filename: str = "cars_data.json"):
"""
تخزين البيانات في ملف JSON.
"""
try:
with open(filename, "w", encoding="utf-8") as f:
json.dump(data, f, ensure_ascii=False, indent=4)
logger.info(f"تم تخزين {len(data)} عنصر في {filename}")
except Exception as e:
logger.error(f"خطأ في تخزين البيانات في {filename}: {str(e)}")
if __name__ == "__main__":
websites = [
"https://iq.labeb.com/ct/cars-for-sale-558",
"https://www.akosayara.com/",
"https://www.iqcars.net/",
"https://alrashad.com.iq/",
"https://website.tao.iq/index.php/ar/",
"https://www.quattro-iq.com/home-ar",
"https://iq.opensooq.com/ar/%D9%85%D8%B1%D8%A7%D9%83%D8%B2-%D8%AE%D8%AF%D9%85%D8%A7%D8%AA-%D8%A7%D9%84%D8%B3%D9%8A%D8%A7%D8%B1%D8%A7%D8%AA/%D8%A7%D9%84%D8%AE%D8%AF%D9%85%D8%A7%D8%AA/%D9%82%D8%B7%D8%B9-%D8%BA%D9%8A%D8%A7%D8%B1",
"https://ghiarati.com/",
"https://www.motors.iq/",
"https://www.alsayyara.com/"
]
while True:
all_cars_data = []
for url in websites:
logger.info(f"جمع البيانات من {url}")
cars_data = scrape_website(url)
all_cars_data.extend(cars_data)
time.sleep(5) # تأخير 5 ثواني لتجنب الحظر
save_data(all_cars_data)
logger.info("تم الانتهاء من جمع البيانات. النوم لمدة ساعة...")
time.sleep(3600) # تحديث كل ساعة