Güncelleme
Benden istedikleri belirli markalara ait müşterilerin şikayetlerini “sikayetvar.com” üzerinden almaktı. Muhtemelen elle tek tek yapmak, onlarca şikayet için epey zor olur. Önce Github‘da biraz taradım, hatta bununla ilgili aynı domaine özgü örnek de buldum. Bu konuda script hazırlayan Mehmet’e de teşekkür ederim.
Neler yaptım?
Tabiki de güncel olmadığı için hataları vardı. Olması da normal çünkü sikayetvar.com da yapısını değiştiriyor ve python kütüphaneleri gelişiyor. Yeni bir iki kütüphane ekledim. Biraz eski kodları düzelttim, onun haricinde çok fazla şikayet verisi toplamaktan mıdır yoksa başka bir nedenden dolayı mı bilmiyorum URL uzunluğundan bir problem yaşadım. Aldığım hatanın çözümünü keşfedemedim ama 32 karakterden uzun şikayet başlıkları olunca sıkıntı olmadı. Bunun yanı sıra şikayetler toplanırken tekrar aynı kayıtlar oluşuyordu, bazen bir sonraki sayfaya gidemiyordu. Bunun için foreach yerine for döngüsüyle sayfa numaralarını tek tek gönderdim. Hazır bu kadar uğraşmışken, her markayı ayrı kaydedeyim dedim.
Velhasıl kelam, temiz çalışan güzel bir örnek oluşturdum. Kodu da sizlerle paylaşıyorum. İyi kodlamalar…
import requests import codecs import csv from requests.exceptions import RequestException from contextlib import closing from bs4 import BeautifulSoup def simple_get(url): """ GET isteği yaparak url almaya çalışır. Yanıt HTML veya XML ise, içeriğini döndürür. Aksi halde None döner. """ try: with closing(requests.get(url, stream=True)) as resp: if is_good_response(resp): return resp.content else: return None except RequestException as e: log_error('{0} için yapılan istekte hata döndü : {1}'.format(url, str(e))) return None def is_good_response(resp): #Yanıt HTML ise True, aksi takdirde False döndürür. content_type = resp.headers['Content-Type'].lower() return (resp.status_code == 200 and content_type is not None and content_type.find('html') > -1) def log_error(e): #Hataları kaydeder. print(e) BASE_URL = "https://www.sikayetvar.com" brand_names = ["marka1","marka2"] #Markalar ["marka1","marka2",...] scraped_data = [] for brand in brand_names: BRAND_URL = BASE_URL + "/" + brand my_page = simple_get(BRAND_URL) parsing = BeautifulSoup(my_page, "html.parser") pages = parsing.find("section",{"class":"pagination row"}) num_of_pages = pages.find_all("a") page_numbs = [] for page_no in num_of_pages: page_numbs.append(page_no.text) last_page_no = int(page_numbs[-2])+1 #Sonraki sayfalar için döngü for x in range(1, last_page_no): page_num=x log = "\n "+ brand + " için " + str(page_num) + ". sayfa okunuyor...\n" print(log) raw_html = simple_get(BRAND_URL+"?page="+str(page_num)) soup = BeautifulSoup(raw_html, "html.parser") item_pages = [] for complaint in soup.find_all("a", {"class":"complaint-link-for-ads"}): item_pages.append(complaint["href"]) for page in item_pages: """ URL uzunluğundan dolayı aldığım bir hata sonucu 32 karakter sınırı koydum. """ if len(page) <=32: continue else: my_url = BASE_URL + page print("Okunan sayfa: " + my_url + "...") raw_html = simple_get(my_url) soup = BeautifulSoup(raw_html, "html.parser") title = soup.find("h1",{"class":"title"}) if title != None: title = title.text.strip('\n') description = soup.find("div", {"class":"description"}) if description != None: description = description.text.strip('\n') date = soup.find("span",{"class":"date date-tips"}) if date != None: date = date["title"][:-5] views = soup.find("span",{"class":"view-count-detail"}) if views != None: views = views.b.text hashtags = soup.find_all("a",{"class":"highlight"}) tags = [] for tag in hashtags: tags.append(tag["title"]) row = [brand,title,description,date,views,tags] scraped_data.append(row) with open(brand+".csv", "w", encoding="utf8", newline="") as csvfile: print(brand+" Bitti!") writer = csv.writer(csvfile, delimiter=';', quotechar='"') headers = ["Marka","Başlık","Açıklama","Tarih","Görüntüleme Sayısı","Etiketler"] writer.writerow(headers) for row in scraped_data: writer.writerow(row) scraped_data.clear() print("Tüm işlemler bitti!")