from urllib import request
from bs4 import BeautifulSoup as BS
from PIL import Image
from time import time
import requests, os, threading, queue

def get_html(url):
    '''ф-ция возвращает html код страницы для выборки данных'''
    headers = {'User-Agent': 'abonnent'}
    response = requests.get(url, headers = headers, timeout = 5)
    if response.status_code == requests.codes.ok:
        return response.text
    else:
        print('ошибка 404')
        print(url)
        print('=' * 100)

def get_next_page(url):
    '''ф-ция определяет наличие следующей страницы для прохождения по циклу'''
    html = get_html(url)
    soup = BS(html, 'lxml')
    disabled = soup.find('ul', {'class': 'pagination'}).find_all('li')[-1].find('a').get('href')
    if disabled is None:
        return False
    else:
        return True

def get_product_urls(html, manufacturer_url):
    '''ф-ция получает все ссылки на товары, находящиеся на текущей странице'''
    soup = BS(html, 'lxml')
    rows = soup.find('table', {'class': 'price-list'}).find('tbody').find_all('tr')

    product_urls = []
    for row in rows:
        product_slug = row.find('a').get('href')
        product_url = manufacturer_url + product_slug
        product_urls.append(product_url)

    return product_urls

def get_product(q, l, product_url, manufacturer_id, current_path, products_folder):
    '''ф-ция собирает все данные о текущем товаре'''
    with l:
        html = get_html(product_url)
        soup = BS(html, 'lxml')

        product = {}
        manufacturer_product_id = int(soup.find('div', {'class': 'sizes-row'}).get('id').split('-')[2])
        name = soup.find('div', {'class': 'info'}).find('h1').get_text().strip()

        product_folder = '{}-{}'.format(manufacturer_id, manufacturer_product_id)
        if os.path.exists(os.path.join(current_path, products_folder, product_folder)):
            os.chdir(os.path.join(current_path, products_folder, product_folder))
        else:
            os.mkdir(product_folder)
            os.chdir(os.path.join(current_path, products_folder, product_folder))

        try:
            html_photoes = soup.find('div', {'class': 'thumbnails'}).find_all('a')
            for html_photo in html_photoes:
                photo_url = html_photo.get('data-image')
                if photo_url:
                    photo_name = photo_url.split('/')[-1]
                    request.urlretrieve(photo_url, photo_name) # загрузка изображений товара
                    image_cleaning(photo_name) # очистка изображений товара (удаление мета-данных exif)
                else:
                    photo_url = html_photo.find('img')['src']
                    photo_name = photo_url.split('/')[-1]
                    request.urlretrieve(photo_url, photo_name) # загрузка изображений товара
                    image_cleaning(photo_name) # очистка изображений товара (удаление мета-данных exif)
        except:
            pass

        os.chdir(os.path.join(current_path, products_folder))  # выходит из папки с загруженными изображениями для товара

        product['_NAME_'] = name
        q.put(product)

def page_looper(manufacturer_url):
    '''ф-ция проходит в цикле все страницы, и возвращает список всех ссылок на товары'''
    product_urls = []

    i = 395
    flag = True
    while flag:
        page_url = '{}/catalog/price-list?page={}'.format(manufacturer_url, i)
        html = get_html(page_url)
        product_urls += get_product_urls(html, manufacturer_url)
        i += 1

        if not get_next_page(page_url):
            flag = False

    return product_urls

def create_products_folder(current_path, products_folder):
    '''ф-ция создает папку для изображений товаров'''
    os.chdir(current_path)
    if os.path.exists(os.path.join(current_path, products_folder)):
        os.chdir(os.path.join(current_path, products_folder))
    else:
        os.mkdir(products_folder)
        os.chdir(os.path.join(current_path, products_folder))

def image_cleaning(photo_name):
    '''ф-ция удаляет мета-данные у изображений'''
    image = Image.open(photo_name)
    data = list(image.getdata())
    image_without_exif = Image.new(image.mode, image.size)
    image_without_exif.putdata(data)
    image_without_exif.save(photo_name)

def main():
    l = threading.Lock()
    q = queue.Queue()

    current_path = os.getcwd()

    products_folder = 'products'
    create_products_folder(current_path, products_folder)

    manufacturer_id = 13
    manufacturer_url = 'https://natali37.ru'

    start = time()

    product_urls = page_looper(manufacturer_url)

    print('Всего ссылок: {}'.format(len(product_urls)))

    thread_list = []
    products = []
    for product_url in product_urls:
        t = threading.Thread(target=get_product, args=[q, l, product_url, manufacturer_id, current_path, products_folder])
        thread_list.append(t)

    for thread in thread_list:
        thread.start()



    for i, t in enumerate(thread_list, 1):
        product = q.get()
        products.append(product)
        print('{}) {}'.format(i, product['_NAME_']))
        t.join()

    end = time()

    print(end - start)

if __name__ == '__main__':
    main()