import requests
from bs4 import BeautifulSoup
import os
from PIL import Image
from urllib.parse import urlparse
from facer.facer import load_images, detect_face_landmarks, create_average_face
import matplotlib.pyplot as plt
Giriş
Türkiye Süper Lig’deki tüm oyuncuların fotoğraflarını bir araya getirerek her takım için ortalama yüz görselleri oluşturacağız.
Kullanılacak Kütüphaneler
Veri Setinin Hazırlanması
Transfermarkt’tan alacağımız ligdeki 19 takımın URL’lerini sözlüğe atarak başlıyoruz. Yüz hesaplamalarında hata verdiği için Türkçe karakter kullanmadan oluşturalım. Sonrasında tekrar Türkçe karakterler ile değiştireceğiz.
= {
team_urls "Galatasaray": "https://www.transfermarkt.com.tr/galatasaray-istanbul/startseite/verein/141/saison_id/2024",
"Fenerbahce": "https://www.transfermarkt.com.tr/fenerbahce-istanbul/startseite/verein/36/saison_id/2024",
"Besiktas JK": "https://www.transfermarkt.com.tr/besiktas-istanbul/startseite/verein/114/saison_id/2024",
"Trabzonspor": "https://www.transfermarkt.com.tr/trabzonspor/startseite/verein/449/saison_id/2024",
"Istanbul Basaksehir FK": "https://www.transfermarkt.com.tr/istanbul-basaksehir-fk/startseite/verein/6890/saison_id/2024",
"Samsunspor": "https://www.transfermarkt.com.tr/samsunspor/startseite/verein/152/saison_id/2024",
"Caykur Rizespor": "https://www.transfermarkt.com.tr/caykur-rizespor/startseite/verein/126/saison_id/2024",
"Eyupspor": "https://www.transfermarkt.com.tr/eyupspor/startseite/verein/7160/saison_id/2024",
"Alanyaspor": "https://www.transfermarkt.com.tr/alanyaspor/startseite/verein/11282/saison_id/2024",
"Kayserispor": "https://www.transfermarkt.com.tr/kayserispor/startseite/verein/3205/saison_id/2024",
"Adana Demirspor": "https://www.transfermarkt.com.tr/adana-demirspor/startseite/verein/3840/saison_id/2024",
"Kasimpasa": "https://www.transfermarkt.com.tr/kasimpasa/startseite/verein/10484/saison_id/2024",
"Sivasspor": "https://www.transfermarkt.com.tr/sivasspor/startseite/verein/2381/saison_id/2024",
"Antalyaspor": "https://www.transfermarkt.com.tr/antalyaspor/startseite/verein/589/saison_id/2024",
"Konyaspor": "https://www.transfermarkt.com.tr/konyaspor/startseite/verein/2293/saison_id/2024",
"Hatayspor": "https://www.transfermarkt.com.tr/hatayspor/startseite/verein/7775/saison_id/2024",
"Goztepe": "https://www.transfermarkt.com.tr/goztepe/startseite/verein/1467/saison_id/2024",
"Bodrum FK": "https://www.transfermarkt.com.tr/bodrumspor/startseite/verein/44006/saison_id/2024",
"Gaziantep FK": "https://www.transfermarkt.com.tr/gaziantep-fk/startseite/verein/2832/saison_id/2024"
}
Web kazıma ile verileri çekmeden önce üç adet dosya oluşturmamız iyi olur. photos
adlı klasör takım fotoğraflarını, average_faces
adlı klasör ortalama yüzleri ve logos
adlı klasör ise takımların logolarını saklayacak.
= 'photos'
file1 = 'average_faces'
file2 = 'logos'
file3
for directory in [file1,file2,file3]:
if not os.path.exists(directory):
os.makedirs(directory)
Fotoğrafları indirecek kodu yazalım.
= {
headers 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.106 Safari/537.36'
}
for team, url in team_urls.items():
= requests.get(url, headers=headers)
response
if response.status_code == 200:
= BeautifulSoup(response.text, 'html.parser')
soup = soup.select('.inline-table img')
images
= os.path.join(file1, team)
team_folder if not os.path.exists(team_folder):
os.makedirs(team_folder)
for index, img in enumerate(images):
= img.get('data-src')
img_url if img_url:
= requests.get(img_url)
img_response if img_response.status_code == 200:
= urlparse(img_url)
parsed_url = os.path.splitext(parsed_url.path)[1]
img_extension = os.path.join(team_folder, f'{team}_image_{index}{img_extension}')
file_name with open(file_name, 'wb') as file:
file.write(img_response.content)
else:
print(f"Failed to download image {index} from {team}")
else:
print(f"No image URL found for image {index} from {team}")
else:
print(f"Failed to retrieve URL for {team}")
Yukarıdaki kodun kilit yerlerine bakalım.
= {
headers 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.106 Safari/537.36'
}
Bir HTTP isteği gönderirken kullanılacak başlıkları (headers
) tanımlar ve bunları bir Python sözlüğü olarak belirtir. Bu başlıklar, sunucuya hangi tarayıcıyı ve işletim sistemini kullandığımızı bildirmek için kullanılır. Özellikle User-Agent
başlığı, web tarayıcılarının kendilerini tanıttıkları bir başlıktır ve sunucular tarafından kullanıcıyı ve kullanılan yazılımı tanımak için kullanılır.
# Burayı çalıştırmayın
= BeautifulSoup(response.text, 'html.parser')
soup = soup.select('.inline-table img') images
BeautifulSoup
kütüphanesini kullanarak gelen HTML yanıtını parse’lıyoruz ve sayfadaki .inline-table
sınıfına sahip tablo içindeki img
etiketlerini seçiyoruz.
# Burayı çalıştırmayın
= os.path.join(file1, team)
team_folder if not os.path.exists(team_folder):
os.makedirs(team_folder)
Takım adıyla bir klasör yolu oluşturuyoruz (file1
ana dizin, team
takım adı). Eğer bu klasör yoksa, os.makedirs
kullanarak bu klasörü oluşturuyoruz.
# Burayı çalıştırmayın
= img.get('data-src')
img_url if img_url:
= requests.get(img_url)
img_response if img_response.status_code == 200:
= urlparse(img_url)
parsed_url = os.path.splitext(parsed_url.path)[1]
img_extension = os.path.join(team_folder, f'{team}_image_{index}{img_extension}')
file_name with open(file_name, 'wb') as file:
file.write(img_response.content)
img.get('data-src')
ifadesiyle, resim URL’ini alıyoruz. Eğer img_url
varsa, bu URL’e bir HTTP GET isteği gönderiyoruz. İstek başarılı olursa, URL’in yolunu ayrıştırıyoruz ve resim dosya uzantısını (.jpg veya .png olabilir) alıyoruz. Resim dosyasını takım klasörüne uygun ad ile (örneğin team_image_0.jpg
) kaydediyoruz.
photos
dosyasının aşağıdaki gibi olmasını bekleriz.
Reponun Klonlanması
Ortalama yüz hesaplamasında faydalanacağımız repoyu proje klasörümüze klonlayalım.
git clone https://github.com/johnwmillr/facer.git Facer
Klonlama işleminden sonra bulunduğumuz dizinde sadece Facer
klasöründeki facer
klasörünü bırakabiliriz. facer
klasörünün içinde ise facer.py
ve utils.py
dosyaları kalabilir.
Yukarıdaki işlemden sonra aşağıdaki gibi zip’li dosyayı indirip unzip’liyor ve dosyayı bulunduğumuz dizinde açtığımız model
adlı klasöre taşıyoruz.
curl -O http://dlib.net/files/shape_predictor_68_face_landmarks.dat.bz2
bunzip2 shape_predictor_68_face_landmarks.dat.bz2
mkdir model
mv shape_predictor_68_face_landmarks.dat model
Ortalama bir yüze ulaşmak için uygulanan adımlar burada detaylı bir şekilde veriliyor.
Ortalama Yüzlerin Hesaplanması
= list(team_urls.keys())
teams = [f'./{file1}/' + team for team in teams] folders
team_urls
sözlüğündeki anahtar değerleri alarak takımları teams
değişkenine, her bir takımın fotoğraflarının bulunduğu dosya adlarını folders
değişkenine atıyoruz.
Hesaplama bölümüne geçebiliriz. Bu bölüm, buradaki repoda verilen örnek kod ile rahatlıkla anlaşılabilir.
for index, folder in enumerate(folders):
try:
= load_images(folder)
images = detect_face_landmarks(images)
landmarks, faces = create_average_face(faces, landmarks, save_image=False)
average_face = f'{teams[index]}_average_face'
file_name
plt.imshow(average_face)'off')
plt.axis(
plt.savefig(os.path.join(file2, file_name))
plt.show()except Exception as e:
print(f"Error processing {teams[index]}: {e}")
average_faces
dosyasının aşağıdaki gibi olmasını bekleriz.
Takım Logolarının İndirilmesi
for team, url in team_urls.items():
= requests.get(url, headers=headers)
response if response.status_code == 200:
= BeautifulSoup(response.content, 'html.parser')
soup
= soup.find('div', class_='data-header__profile-container')
profile_container if profile_container:
= profile_container.find('img')
img_tag if img_tag and 'src' in img_tag.attrs:
= img_tag['src']
img_url = requests.get(img_url)
img_response if img_response.status_code == 200:
= os.path.join(file3, f"{team}.png")
img_filename with open(img_filename, 'wb') as f:
f.write(img_response.content)print(f"Logo for {team} downloaded and saved.")
else:
print(f"Failed to download logo image for {team}.")
else:
print(f"Logo image not found for {team}.")
else:
print(f"Profile container not found for {team}.")
else:
print(f"Failed to fetch {url}. Status code: {response.status_code}")
logos
dosyasının aşağıdaki gibi olmasını bekleriz.
Türkçe Karakterlerin Oluşturulması
= {
teams_turkish "Besiktas JK": "Beşiktaş JK",
"Caykur Rizespor": "Çaykur Rizespor",
"Eyupspor": "Eyüpspor",
"Fenerbahce": "Fenerbahçe",
"Goztepe": "Göztepe",
"Istanbul Basaksehir FK": "İstanbul Başakşehir FK",
"Kasimpasa": "Kasımpaşa"
}
= [file2, file3]
directories
for directory in directories:
= os.listdir(directory)
logo_files
for filename in logo_files:
= os.path.splitext(filename)
name, ext
for key, value in teams_turkish.items():
if key in name:
= name.replace(key, value)
new_name = new_name + ext
new_filename
= os.path.join(directory, filename)
old_path = os.path.join(directory, new_filename)
new_path
os.rename(old_path, new_path)print(f"Renamed {filename} to {new_filename} in {directory}.")
for i in range(len(teams)):
for key, value in teams_turkish.items():
if key in teams[i]:
= value teams[i]
Görselin Oluşturulması
5 satır ve 4 sütundan oluşan bir alt grafik ızgarası oluşturalım.
= plt.subplots(5, 4, figsize=(32, 32))
fig, axs
for i, team in enumerate(teams):
= f"{file2}/{team}_average_face.png"
filename = Image.open(filename)
img
= f"{file3}/{team}.png"
logo_filename_png = f"{file3}/{team}.jpg"
logo_filename_jpg
if os.path.exists(logo_filename_png):
= Image.open(logo_filename_png).convert("RGBA")
logo_img elif os.path.exists(logo_filename_jpg):
= Image.open(logo_filename_jpg).convert("RGBA")
logo_img else:
print(f"Logo image for {team} not found.")
continue
= img.width // 6
new_logo_width = logo_img.resize((new_logo_width, logo_img.height * new_logo_width // logo_img.width), Image.Resampling.LANCZOS)
logo_img
= Image.new("RGBA", logo_img.size, "WHITE")
white_bg = Image.alpha_composite(white_bg, logo_img).convert("RGB")
logo_img
= Image.new('RGB', (img.width, img.height + logo_img.height), "WHITE")
combined_img
= (img.width - logo_img.width) // 2
logo_x 0))
combined_img.paste(logo_img, (logo_x, 0, logo_img.height))
combined_img.paste(img, (
= i // 4
row = i % 4
col
axs[row, col].imshow(combined_img)'off')
axs[row, col].axis(
0.5, 0.77), xycoords='axes fraction', ha='center', va='top', fontsize=20, fontweight='bold')
axs[row, col].annotate(team, (
for j in range(len(teams), 20):
fig.delaxes(axs.flatten()[j])
"Türkiye Süper Lig 2024/25 Takım Kadrolarının Ortalama Yüzü", fontsize=54, fontweight='bold')
fig.suptitle(=[0, 0, 1, 0.96])
plt.tight_layout(rect"average_faces_final.png")
plt.savefig( plt.show()
Gelecek içeriklerde görüşmek dileğiyle.