예제 #1
0
파일: models.py 프로젝트: smallbee3/Melon
    def update_or_create_from_melon(self, album_id):
        result = album_detail_crawler(album_id)

        album_title = result.get('album_title')
        # album_cover = result.get('album_cover')
        album_cover_url = result.get('album_cover_url')
        rel_date = result.get('rel_date')

        album, album_created = self.update_or_create(
            album_id=album_id,
            defaults={
                'title': album_title,
                # 'img_cover': album_cover,
                'release_date': datetime.strptime(rel_date, '%Y.%m.%d'),
            })

        temp_file = download(album_cover_url)
        file_name = '{album_id}.{ext}'.format(
            album_id=album_id,
            ext=get_buffer_ext(temp_file),
        )
        # 방법1 - 지우고 다시 만들기
        if album.img_cover:
            album.img_cover.delete()
        album.img_cover.save(file_name, File(temp_file))

        return album, album_created
예제 #2
0
파일: models.py 프로젝트: seokjaehong/melon
    def update_or_create_from_melon(self, album_id):
        album_data = AlbumData(album_id)
        album_data.get_detail()

        album_id = album_data.album_id
        title = album_data.title
        url_img_cover = album_data.url_img_cover
        release_date_str = album_data.release_date

        album, album_created = self.update_or_create(
            melon_id=album_id,
            defaults={
                'title':
                title,
                'release_date':
                datetime.strptime(release_date_str, '%Y.%m.%d')
                if release_date_str else None,
            })

        temp_file = download(url_img_cover)

        file_name = '{album_id}.{ext}'.format(
            album_id=album_id,
            ext=get_buffer_ext(temp_file),
        )
        # 중복데이터 제거
        if album.img_cover:
            album.img_cover.delete()
        album.img_cover.save(file_name, File(temp_file))
        return album, album_created
예제 #3
0
    def add_from_search(self, request, url):
        search_result = CheckURL(url)
        search_result.check_url_from_parser()

        item_category = request.POST['category']
        item_img = request.FILES.get('img', '')
        item_public_visibility = request.POST['public_visibility']
        item_price = request.POST['price'].replace(',', '')
        item_name = request.POST['name']
        if item_public_visibility == 'on' or item_public_visibility:
            item_public_visibility = True
        else:
            item_public_visibility = False

        item = self.create(
            user=request.user,
            name=item_name,
            purchase_url=search_result.item_data.url,
            price=item_price,
            category=item_category,
            img=item_img,
            public_visibility=item_public_visibility,
        )

        if not item.img and search_result.item_data.item_img:
            item_img_url = search_result.item_data.item_img
            temp_file = download(item_img_url)
            file_name = '{urlparse}.{ext}'.format(
                urlparse=urlparse(item_img_url).path.split('/')[-1].split(
                    '.')[0],
                ext=get_buffer_ext(temp_file))
            item.img.save(file_name, File(temp_file))

        return item
예제 #4
0
    def update_or_create_from_melon(self, artist_id):
        from .artist import Artist
        artist = ArtistData(artist_id)
        artist.get_detail()
        name = artist.name
        url_img_cover = artist.url_img_cover
        real_name = artist.personal_information.get('본명', '')
        nationality = artist.personal_information.get('국적', '')
        birth_date_str = artist.personal_information.get('생일', '')
        constellation = artist.personal_information.get('별자리', '')
        blood_type = artist.personal_information.get('혈액형', '')

        # blood_type과 birth_date_str이 없을때 처리할것

        # 튜플의 리스트를 순회하며 blood_type을 결정
        for short, full in Artist.CHOICES_BLOOD_TYPE:
            if blood_type.strip() == full:
                blood_type = short
                break
        else:
            # break가 발생하지 않은 경우
            # (미리 정의해놓은 혈액형 타입에 없을 경우)
            # 기타 혈액형값으로 설정
            blood_type = Artist.BLOOD_TYPE_OTHER

        artist, artist_created = self.update_or_create(
            melon_id=artist_id,
            defaults={
                'name':
                name,
                'real_name':
                real_name,
                'nationality':
                nationality,
                'birth_date':
                datetime.strptime(birth_date_str, '%Y.%m.%d')
                if birth_date_str else None,
                'constellation':
                constellation,
                'blood_type':
                blood_type,
            })
        # img_profile필드에 저장할 파일확장자를 바이너리 데이터 자체의 MIME_TYPE에서 가져옴
        # 파일명은 artist_id를 사용
        temp_file = download(url_img_cover)
        file_name = '{artist_id}.{ext}'.format(
            artist_id=artist_id,
            ext=get_buffer_ext(temp_file),
        )
        # artist.img_profile필드의 save를 따로 호출, 이름과 File객체를 전달
        #   (Django)File객체의 생성에는 (Python)File객체를 사용,
        #           이 때 (Python)File객체처럼 취급되는 BytesIO를 사용
        if artist.img_profile:
            artist.img_profile.delete()
        artist.img_profile.save(file_name, File(temp_file))
        return artist, artist_created
예제 #5
0
    def authenticate(self, request, code):
        def get_access_token(auth_code):
            params_access_token = {
                'client_id': self.CLIENT_ID,
                'redirect_uri': 'http://localhost:8000/facebook-login/',
                'client_secret': self.CLIENT_SECRET,
                'code': auth_code,
            }
            response = requests.get(self.URL_ACCESS_TOKEN, params_access_token)
            response_dict = response.json()
            return response_dict['access_token']

        def get_user_info(user_access_token):

            params = {
                'access_token':
                user_access_token,
                'fields':
                ','.join([
                    'id',
                    'name',
                    'picture.width(2500)',
                    'first_name',
                    'last_name',
                ])
            }
            response = requests.get(self.URL_ME, params)
            response_dict = response.json()
            return response_dict

        try:
            access_token = get_access_token(code)
            user_info = get_user_info(access_token)

            facebook_id = user_info['id']
            name = user_info['name']
            first_name = user_info['first_name']
            last_name = user_info['last_name']
            url_picture = user_info['picture']['data']['url']

            try:
                user = User.objects.get(username=facebook_id)
            except User.DoseNotExist:
                user = User.objects.create_user(
                    username=facebook_id,
                    first_name=first_name,
                    last_name=last_name,
                )
            if not user.img_profile:
                temp_file = download(url_picture)
                ext = get_buffer_ext(temp_file)
                user.img_profile.save(f'{user.pk}.{ext}', File(temp_file))
            return user
        except Exception:
            return None
예제 #6
0
    def authenticate(self, request, access_token):
        params = {
            'access_token':
            access_token,
            'fields':
            ','.join([
                'id',
                'name',
                'picture.width(2500)',
                'first_name',
                'last_name',
                'email',
            ])
        }
        response = requests.get('https://graph.facebook.com/v2.12/me', params)

        if response.status_code == status.HTTP_200_OK:
            user_info = response.json()

            facebook_id = user_info['id']
            name = user_info['name']
            url_img_profile = user_info['picture']['data']['url']

            # facebook유저중에 email이 없는 경우가 있어서 없는경우는 email을 빈값으로 입력
            if 'email' in user_info:
                email = user_info['email']
            else:
                email = ''

            try:
                # email이 unique이기 때문에 email로 구분한다.
                user = User.objects.get(username=facebook_id)

            except:
                user = User.objects.create_user(
                    email=email,
                    username=facebook_id,
                    first_name=name,
                    is_facebook_user=True,
                    # img_profile=img_profile,
                    # 이미지는 따로 저장한다.
                )

            temp_file = download(url_img_profile)

            file_name = '{username}.{ext}'.format(
                username=facebook_id,
                ext=get_buffer_ext(temp_file),
            )
            if user.img_profile:
                user.img_profile.delete()
            user.img_profile.save(file_name, File(temp_file))

            return user
예제 #7
0
    def update_or_create_from_melon(self, album_id):
        url = 'https://www.melon.com/album/detail.htm'
        params = {
            'albumId': album_id,
        }
        response = requests.get(url, params)
        soup = BeautifulSoup(response.text, 'lxml')
        info = soup.select_one('div.section_info')
        entry = info.select_one('div.entry')
        src = info.select_one('div.thumb img').get('src')

        title = entry.select_one('div.info > .song_name').contents[2].strip()
        img_cover = re.search(r'(.*?)/melon/quality.*', src).group(1)
        # if re.findall('http.*?\.jpg', url_img_cover):
        #     url_img_cover = re.findall('http.*?\.jpg', url_img_cover)[0]
        # else:
        #     url_img_cover = "http://cdnimg.melon.co.kr/resource/image/web/default/noAlbum_500_160727.jpg"

        meta_dict = get_dict_from_dl(entry.select_one('div.meta dl'))

        # response = requests.get(url_img_cover)
        # binary_data = response.content
        # temp_file = BytesIO()
        # temp_file.write(binary_data)
        # # temp_file.seek(0)

        try:
            release_date = datetime.strptime(meta_dict['발매일'], '%Y.%m.%d')
        except ValueError:
            try:
                release_date = datetime.strptime(meta_dict['발매일'], '%Y.%m')
            except ValueError:
                try:
                    release_date = datetime.strptime(meta_dict['발매일'], '%Y')
                except ValueError:
                    release_date = None

        album, album_created = Album.objects.update_or_create(
            melon_id=album_id,
            defaults={
                'title': title,
                'release_date': release_date,
            })
        # file_name = Path(url_img_cover).name
        # file_name, temp_file = download(img_cover, album_id)

        temp_file = download(img_cover)
        file_name = '{album_id}.{ext}'.format(
            album_id=album_id,
            ext=get_buffer_ext(temp_file),
        )
        album.img_cover.save(file_name, File(temp_file))
        return album, album_created
예제 #8
0
파일: models.py 프로젝트: shdbsghxg/Melon
    def update_or_create_from_melon(self, artist_id):
        artist = ArtistData(artist_id)
        artist.get_detail()

        name = artist.name
        url_img_cover = artist.url_img_cover
        print(url_img_cover)
        real_name = artist.personal_information.get('본명', '')
        nationality = artist.personal_information.get('국적', '')
        birth_date_str = artist.personal_information.get('생일', '')
        constellation = artist.personal_information.get('별자리', '')
        blood_type = artist.personal_information.get('혈액형', '')

        for short, full in Artist.CHOICES_BLOOD_TYPE:
            if blood_type.strip() == full:
                blood_type = short
                break
        else:
            blood_type = Artist.BLOOD_TYPE_OTHER

        # if artist w/ melon_id = artist_id already exists,
        # update date in DB,
        # or add new artist in DB
        artist, artist_created = self.update_or_create(
            melon_id=artist_id,
            defaults={
                'name':
                name,
                'real_name':
                real_name,
                'nationality':
                nationality,
                'birth_date':
                datetime.strptime(birth_date_str, '%Y.%m.%d')
                if birth_date_str else None,
                'constellation':
                constellation,
                'blood_type':
                blood_type,
            })

        temp_file = download(url_img_cover)
        file_name = '{artist_id}.{ext}'.format(
            artist_id=artist_id,
            ext=get_buffer_ext(temp_file),
        )

        if artist.img_profile:
            artist.img_profile.delete()
        artist.img_profile.save(file_name, File(temp_file))

        return artist, artist_created
예제 #9
0
파일: views.py 프로젝트: smallbee3/Melon
def video_add(request):
    if request.method == 'POST':
        # video_id = request.POST.get('video_id')
        #
        # video, _ = Video.objects.update_or_create_from_melon(video_id)
        #
        # # 1) 위에서 생성한 video를 Artist에 연결해주기위해
        # #    artist_detail.html에 artist의 pk를 이곳으로 전달.
        # # 2) 덤으로 기존에 있던 페이지로 redirect하는데도 써먹자
        # artist_pk = request.POST.get('artist_pk')
        # artist = get_object_or_404(Artist, pk=artist_pk)
        # artist.videos.add(video)
        #
        # return redirect('artist:artist-detail', artist_pk=artist_pk)

        video_id = request.POST.get('video_id')
        title = request.POST.get('title')
        thumbnails = request.POST.get('thumbnails')

        video, _ = Video.objects.update_or_create(
            video_id=video_id,
            defaults={
                'title': title,
                # 'thumbnail': thumbnails,
            })

        # Artist에 video 넣어주기
        artist_pk = request.POST.get('artist_pk')
        artist = get_object_or_404(Artist, pk=artist_pk)
        artist.videos.add(video)

        print('')
        print(title)
        print(f'{title[:15]}')

        # 2) video 저

        # Video thumbnaili 사진저장
        temp_file = download(thumbnails)
        file_name = f'{title[:15]}.{get_buffer_ext(temp_file)}'
        video.thumbnail.save(file_name, File(temp_file))

        next_path = request.POST.get(
            'next-path',
            # reverse('artist:artist-detail', args=[artist_pk]),
            reverse('artist:artist-detail', kwargs={'artist_pk': artist_pk}),
        )
        print('')
        print(next_path)
        print('')

        return redirect(next_path)
예제 #10
0
    def update_or_create_from_melon(self, artist_id):
        from .artist import Artist
        artist = ArtistData(artist_id)
        artist.get_detail()
        name = artist.name
        url_img_cover = artist.url_img_cover
        real_name = artist.personal_information.get('본명', '')
        nationality = artist.personal_information.get('국적', '')
        birth_date_str = artist.personal_information.get('생일', '')
        constellation = artist.personal_information.get('별자리', '')
        blood_type = artist.personal_information.get('혈액형', '')

        # blood_type과 birth_date_str이 없을때 처리할것

        # 튜플의 리스트를 순회하며 blood_type을 결정
        for short, full in Artist.CHOICES_BLOOD_TYPE:
            if blood_type.strip() == full:
                blood_type = short
                break
        else:
            # break가 발생하지 않은 경우
            # (미리 정의해놓은 혈액형 타입에 없을 경우)
            # 기타 혈액형값으로 설정
            blood_type = Artist.BLOOD_TYPE_OTHER

        # artist_id가 melon_id에 해당하는 Artist가 이미 있다면
        #   해당 Artist의 내용을 update
        # 없으면 Artist를 생성

        artist, artist_created = self.update_or_create(
            melon_id=artist_id,
            defaults={
                'name': name,
                'real_name': real_name,
                'nationality': nationality,
                'birth_date': datetime.strptime(
                    birth_date_str, '%Y.%m.%d') if birth_date_str else None,
                'constellation': constellation,
                'blood_type': blood_type,
            }
        )
        temp_file = download(url_img_cover)
        file_name = '{artist_id}.{ext}'.format(
            artist_id=artist_id,
            ext=get_buffer_ext(temp_file)
        )
        if artist.img_profile:
            artist.img_profile.delete()
        artist.img_profile.save(file_name, File(temp_file))
        return artist, artist_created
예제 #11
0
    def update_or_create_from_melon(self, album_id):
        album_data = AlbumData(album_id)
        album_data.get_detail()

        album, album_created = self.update_or_create(
            melon_id=album_id,
            defaults={
                'title': album_data.title,
                'release_date': album_data.release_date,
            })

        temp_file = download(album_data.url_img_cover)
        file_name = '{album_id}.{ext}'.format(
            album_id=album_id,
            ext=get_buffer_ext(temp_file),
        )
        album.img_cover.save(file_name, File(temp_file))
        return album, album_created
예제 #12
0
파일: models.py 프로젝트: shdbsghxg/Melon
    def update_or_create_from_melon(self, album_id):
        # crawl
        url = 'https://www.melon.com/album/detail.htm'
        params = {
            'albumId': album_id,
        }

        response = requests.get(url, params)
        soup = BeautifulSoup(response.text, 'lxml')

        url_img_cover_cont = soup.find('div', class_='thumb')
        info_cont = soup.find('div', class_='entry')

        # rsplit( separator, number of splits ) --> list
        url_img_cover = url_img_cover_cont.select_one(
            'a.image_typeAll > img').get('src').rsplit('?', 1)[0]
        print(url_img_cover)
        title = info_cont.select_one(
            'div.info > div.song_name strong').next_sibling.strip()
        release_date = info_cont.select_one(
            'div.meta > dl.list > dd:nth-of-type(1)').text

        album, album_created = self.update_or_create(melon_id=album_id,
                                                     defaults={
                                                         'title':
                                                         title,
                                                         'release_date':
                                                         datetime.strptime(
                                                             release_date,
                                                             '%Y.%m.%d')
                                                     })

        temp_file = download(url_img_cover)
        file_name = '{album_id}.{ext}'.format(
            album_id=album_id,
            ext=get_buffer_ext(temp_file),
        )
        # saving an img in a row creates new img file
        # why??
        if album.img_cover:
            album.img_cover.delete()
        album.img_cover.save(file_name, File(temp_file))

        return album, album_created
예제 #13
0
    def save(self, *args, **kwargs):
        if Item.objects.filter(pk=self.pk):
            super().save()
        else:
            if self.purchase_url and not self.img:
                url = self.purchase_url
                search_result = CheckURL(url)
                search_result.check_url_from_parser()

                item_img_url = search_result.item_data.item_img
                if item_img_url:
                    temp_file = download(item_img_url)
                    file_name = '{urlparse}.{ext}'.format(
                        urlparse=urlparse(item_img_url).path.split(
                            '/')[-1].split('.')[0],
                        ext=get_buffer_ext(temp_file))
                    self.purchase_url = search_result.item_data.url
                    self.img.save(file_name, File(temp_file))
            super().save()
예제 #14
0
파일: models.py 프로젝트: pyheejin/ohou
    def save(self, *args, **kwargs):
        # ImageField에 파일이 없고, url이 존재하는 경우에만 실행
        if self.purchase_url and not self.image_file:
            # 우선 purchase_url의 대표 이미지를 크롤링하는 로직은 생략하고, 크롤링 결과 이미지 url을 임의대로 설정
            item_image_url = 'https://cdn.pixabay.com/photo/2016/08/27/11/17/bag-1623898_960_720.jpg'

            if item_image_url:
                temp_file = download(item_image_url)
                file_name = '{urlparse}.{ext}'.format(
                    # url의 마지막 '/' 내용 중 확장자 제거
                    # ex) url = 'https://~~~~~~/bag-1623898_960_720.jpg'
                    #     -> 'bag-1623898_960_720.jpg'
                    #     -> 'bag-1623898_960_720'
                    urlparse=urlparse(item_image_url).path.split('/')[-1].split('.')[0],
                    ext=get_buffer_ext(temp_file)
                )
                self.image_file.save(file_name, File(temp_file))
                super().save()
            else:
                super().save()
예제 #15
0
    def authenticate(self, request, access_token):
        params = {
            'access_token':
            access_token,
            'fields':
            ','.join([
                'id',
                'name',
                'picture.width(2500)',
                'first_name',
                'last_name',
                'email',
            ])
        }
        response = requests.get('https://graph.facebook.com/v2.12/me', params)
        if response.status_code == status.HTTP_200_OK:
            # 응답상태 코드 200 이라면
            response_dict = response.json()
            facebook_id = response_dict['id']
            name = response_dict['name']
            if name == '':
                first_name = response_dict['first_name']
                last_name = response_dict['last_name']
                name = last_name + first_name
            url_picture = response_dict['picture']['data']['url']
            user, _ = User.objects.get_or_create(username=facebook_id,
                                                 email=None,
                                                 nickname=name)
            if not user.img_profile:
                temp_file = download(url_picture)

                ext = get_buffer_ext(temp_file)
                im = Image.open(temp_file)
                large = im.resize((200, 200))
                temp_file = BytesIO()
                large.save(temp_file, ext)

                user.img_profile.save(f'{user.pk}.{ext}', File(temp_file))
            return user
 def update_or_create_from_melon(self, album_id):
     album_data = AlbumData(album_id)
     album_data.get_detail()
     album, album_created = self.update_or_create(
         melon_id=album_id,
         defaults={
             'title': album_data.title,
             'release_date': album_data.release_date,
         }
     )
     # response = requests.get(album_data.url_img_cover)
     # binary_data = response.content
     # temp_file = BytesIO()
     # temp_file.write(binary_data)
     # temp_file.seek(0)
     # file_name = Path(album_data.url_img_cover).name
     temp_file = download(album_data.url_img_cover)
     file_name = '{album_id}.{ext}'.format(
         album_id=album_id,
         ext=get_buffer_ext(temp_file),
     )
     album.img_cover.save(file_name, File(temp_file))
     return album, album_created
예제 #17
0
    def update_or_create_from_melon(self, artist_id):
        from artist.models import Artist

###################### add_from_melon.py ######################

        ################# 크롤러 #################
        import requests
        from bs4 import BeautifulSoup
        url = f'https://www.melon.com/artist/detail.htm'
        params = {
            'artistId': artist_id,
        }
        response = requests.get(url, params)
        source = response.text
        soup = BeautifulSoup(source, 'lxml')

        # name
        name = soup.select_one('p.title_atist').strong.next_sibling

        # url_img_cover
        url_img = soup.select_one('span#artistImgArea > img').get('src')
        url_img_cover = re.search(r'(.*.jpg)', url_img).group(1)


        # real_name, nationality, birth_date, constellation, blood_type
        personal_information = {}
        if re.search(r'신상정보</h3>', source, re.DOTALL):
            dl_list = re.search(r'신상정보</h3>.*?-->(.*?)</dl>', source, re.DOTALL)
            # dt = re.findall('<dt>.*?</dt>', dl_list.group(1))
            # dd = re.findall('<dd>.*?</dd>', dl_list.group(1))
            soup = BeautifulSoup(dl_list.group(), 'lxml')
            dt = soup.select('dt')
            dd = soup.select('dd')

            dd_dt = list(zip(dt, dd))
            # print(dd_dt)

            for i, j in dd_dt:
                i = i.get_text(strip=True)
                j = j.get_text(strip=True)
                personal_information[i] = j
            # print(self._personal_information)
        else:
            personal_information = ''
        #######################################



        # url_img_cover = artist.url_img_cover
        real_name = personal_information.get('본명', '')
        nationality = personal_information.get('국적', '')
        birth_date_str = personal_information.get('생일', '')
        constellation = personal_information.get('별자리', '')
        blood_type = personal_information.get('혈액형', '')

        # 예외처리 1
        # 튜플의 리스트를 순회하며 blood_type을 결정
        for short, full in Artist.CHOICES_BLOOD_TYPE:
            if blood_type.strip() == full:
                blood_type = short
                break
        else:
            # break가 발생하지 않은 경우
            # (미리 정의해놓은 혈액형 타입에 없을 경우)
            # 기타 혈액형값으로 설정
            blood_type = Artist.BLOOD_TYPE_OTHER

        # 예외처리 2 - 생년월일 없을 경우
        # if birth_date_str == '':
        #     birth_date = None
        # else:
        #     birth_date = datetime.strptime(birth_date_str, '%Y.%m.%d')

        # 예외처리 2-2 - 위의 4줄을 한 줄로 줄임
        # datetime.strptime(birth_date_str, '%Y.%m.%d') if birth_date_str else None,



        # 1단계 - Artist 생성
        # Artist.objects.create(
        #     melon_id=artist_id,
        #     name=name,
        #     real_name=real_name,
        #     nationality=nationality,
        #     birth_date=datetime.strptime(birth_date_str, '%Y.%m.%d'),
        #     constellation=constellation,
        #     blood_type=blood_type,
        # )


        # artist_id가 melon_id에 해당하는 Artist가 이미 있다면
        # 해당 Artist의 내용을 update,
        # 없으면 Artist를 생성

        # 2단계 - 코드가 두번 반복됨, 암걸릴 것 같음.
        # if Artist.objects.filter(melon_id=artist_id).exists():
        #     artist = Artist.objects.get(melon_id=artist_id)
        #     artist.melon_id = artist_id
        #     artist.name = name
        #     artist.real_name = real_name
        #     artist.nationality = nationality
        #     artist.birth_date = datetime.strptime(birth_date_str, '%Y.%m.%d')
        #     artist.constellation = constellation
        #     artist.blood_type = blood_type
        #     artist.save()
        # else:
        #     Artist.objects.create(
        #         melon_id=artist_id,
        #         name=name,
        #         real_name=real_name,
        #         nationality=nationality,
        #         birth_date=datetime.strptime(birth_date_str, '%Y.%m.%d'),
        #         constellation=constellation,
        #         blood_type=blood_type,
        #     )


        # 3단계 - get_or_create() 사용
        # artist, artist_created = Artist.objects.get_or_create(melon_id=artist_id)
        # artist.name = name
        # artist.real_name = real_name
        # artist.nationality = nationality
        # artist.birth_date = datetime.strptime(birth_date_str, '%Y.%m.%d')
        # artist.constellation = constellation
        # artist.blood_type = blood_type
        # artist.save()
        # return redirect('artist:artist-list')

        # -> 문제점: save()가 두번 발생함. 이미 존재하면 가져오고
        #     속성을 변경하고 save()를 하면 되는데, created할 때는
        #     객체를 만들 때 save()를 한번 하고 밑에서 또 한번 save()를 함.


        ######## Save file to ImageField ########
        from io import BytesIO
        from pathlib import Path
        from django.core.files import File
        from django.core.files.base import ContentFile

        # response = requests.get(url_img_cover)

        # binary_data = response.content
# img_profile필드에 저장할 파일명을 전체 URL경로에서 추출 (Path라이브러리)
#         file_name = Path(url_img_cover).name
        # print(f'file_name: {file_name}')



        # 방법1 - 2/20 수업시간
# 파일처럼 취급되는 메모리 객체 temp_file를 생성
#         temp_file = BytesIO()

# temp_file에 이진데이터를 기록
#         temp_file.write(binary_data)

# 파일객체의 포인터를 시작부분으로 되돌림
#         temp_file.seek(0)

# artist.img_profile필드의 save를 따로 호출, 이름과 File객체를 전달
# (Django)File객체의 생성에는 (Python)File객체를 사용,
# 이때 (Python)File객체처럼 취급되는 BytesIO를 사용
        # artist.img_profile.save(file_name, File(temp_file))

# -> update_or_create에서 반환된 obj인 'artist'를 활용하기 때문에
#    이 방법1 을 실행하려면 아래쪽으로 이동시킬 것.





        # 방법2 - ContentFile이용 by che1
        #
        # artist.img_profile.save(file_name, ContentFile(binary_data))
        # -> update_or_create에서 반환된 obj인 'artist'를 활용하기 때문에
        #    이 방법2 를 실행하려면 아래쪽으로 이동시킬 것.

        # 방법 3 - update_or_create 이용해서 이미지 저장하기
        #
        # 아래에서
        # 'img_profile': ContentFile(binary_data, name='test.jpg'),
        # 이 부분이 방법 3


        # 방법 4 - 위 방법으로 사진 중복저장을 막지 못해서 이 방법 4 생각해냄.
        # if (파일이 안같으면):
        #   기존 사진 지우는 코드 (기존 사진에서 업데이트 되었으므로)
        #   img = ContentFile(binary_data, filename)
        # else: (파일이 같으면)
        #   pass


        # 4단계 -update_or_create() 사용
        # 1)
        # artist, artist_created = Artist.objects.update_or_create(
        # 2) self.model이라는 이름으로 자신의 클래스에 접근가능
        # artist, artist_created = self.model.update_or_create(
        # 3) objects라는 것 자체가 매니저 객체였으니까 매니저 객체에 있는
        #    이 update_or_create를 그대로 실행하면 되는 거죠.
        #   (밖으로 나갔다가 다시 들어올 필요없이)
        artist, artist_created = self.update_or_create(

            melon_id=artist_id,
            defaults={
                'name': name,
                'real_name': real_name,
                'nationality': nationality,
                # 'birth_date': birth_date,
                # 위의 예외처리 4줄 대신 '조건표현식' 한줄로 Pythonic하게!
                'birth_date': datetime.strptime(birth_date_str, '%Y.%m.%d') if birth_date_str else None,
                'constellation': constellation,
                'blood_type': blood_type,

                # 방법 3
                # 'img_profile': ContentFile(binary_data, name='test.jpg'),
                #  이런식으로 name에다가 값을 전달해주면 해당 값이 파일명이 됨.
                # 'img_profile': ContentFile(binary_data, name=file_name),

                # 방법 4
                # 'img_profile': img #-> 방법 4 쓴다면
            }
        )

        # 2/23
        # import magic
        #
        # mime_type = magic.from_buffer(temp_file.read(), mime=True)
        # file_name = '{artist_id}.{ext}'.format(
        #     artist_id=artist_id,
        #     ext=mime_type.split('/')[-1]
        # )

        # 위 코드를 utils/file.py로 분리함
        # 전달인자로 url과 artist_id를 전달함 (원래 두번째 인자는 artist_id는 아님)
        # file_name, temp_file = download(url_img_cover, artist_id)

# img_profile필드에 저장할 파일확장자를 바이너리 데이터 자체의 MIME_TYPE에서 가져옴
# 파일명은 artist_id를 사용
        temp_file = download(url_img_cover)
        file_name = '{artist_id}.{ext}'.format(
            artist_id=artist_id,
            ext=get_buffer_ext(temp_file),
        )


        # 2/23 - 사진 중복저장 방지 코드
        #       : 해당필드에 사진이 있는지 확인
        # 방법1 - 지우고 다시 만들기
        if artist.img_profile:
            artist.img_profile.delete()
        artist.img_profile.save(file_name, File(temp_file))

        # 방법2 - 있을경우 안만들기
        # if not artist.img_profile:
        #     artist.img_profile.save(file_name, File(temp_file))

        return artist, artist_created
예제 #18
0
    def update_or_create_from_song_id(self, song_id):
        """
        Song의 Album정보도 가져와서 AlbumManager.update_or_create_from_melon도 실행
            -> Album의 커버이미지도 저장
        """
        url_song = 'https://www.melon.com/song/detail.htm'
        params_song = {
            'songId': song_id,
        }
        response_song = requests.get(url_song, params_song)
        soup_song = BeautifulSoup(response_song.text, 'lxml')

        thumb_entry = soup_song.find('div', class_='thumb')
        url_img_cover = thumb_entry.find('img').get('src')
        # if re.findall('http.*?\.jpg', url_img_cover):
        #     url_img_cover = re.findall('http.*?\.jpg', url_img_cover)[0]
        # else:
        #     url_img_cover = "http://cdnimg.melon.co.kr/resource/image/web/default/noAlbum_500_160727.jpg"

        div_entry = soup_song.find('div', class_='entry')

        title = div_entry.find('div', class_='song_name').strong.next_sibling.strip()

        artist = div_entry.find('div', class_='artist').get_text(strip=True)
        if div_entry.select_one('div.artist a'):
            artist_id_a = div_entry.select_one('div.artist a').get('href')
            artist_id = re.findall(r'\(\'(.*?)\'\)', artist_id_a)[0]
        else:
            artist_id = '100014'

        # 앨범, 발매일, 장르...에 대한 Description list
        dl = div_entry.find('div', class_='meta').find('dl')
        # isinstance(인스턴스, 클래스(타입))
        # items = ['앨범', '앨범명', '발매일', '발매일값', '장르', '장르값']
        items = [item.get_text(strip=True) for item in dl.contents if not isinstance(item, str)]
        it = iter(items)
        description_dict = dict(zip(it, it))

        album = description_dict.get('앨범')
        album_id_a = str(dl.select_one('a'))
        album_id = re.findall(r'\(\'(.*?)\'\)', album_id_a)[0]
        # release_date = description_dict.get('발매일')
        genre = description_dict.get('장르')

        div_lyrics = soup_song.find('div', id='d_video_summary')

        lyrics_list = []
        if div_lyrics:
            for item in div_lyrics:
                if item.name == 'br':
                    lyrics_list.append('\n')
                elif type(item) is NavigableString:
                    lyrics_list.append(item.strip())
            lyrics = ''.join(lyrics_list)
        else:
            lyrics = '가사가 없습니다'

        # # if Album.objects.get(title=album):
        # # url_img_cover는 이미지의 URL
        # response = requests.get(url_img_cover)
        # # requests에 GET요청을 보낸 결과의 Binary data
        # binary_data = response.content
        # # 파일처럼 취급되는 메모리 객체 temp_file를 생성
        # temp_file = BytesIO()
        # # temp_file에 이진데이터를 기록
        # temp_file.write(binary_data)
        # # 파일객체의 포인터를 시작부분으로 되돌림
        # # temp_file.seek(0)

        # artist = ArtistData(artist_id)
        # artist.get_detail()
        #
        # name = artist.name
        # url_img_cover = artist.url_img_cover
        # url_img_cover = re.findall('http.*?\.jpg', url_img_cover)[0]
        # real_name = artist.personal_information.get('본명', '')
        # nationality = artist.personal_information.get('국적', '')
        # birth_date_str = artist.personal_information.get('생일', '')
        # if not birth_date_str or len(birth_date_str) <= 9:
        #     birth_date_str = '1900.01.01'
        # constellation = artist.personal_information.get('별자리', '')
        # blood_type = artist.personal_information.get('혈액형', '')
        #
        # for short, full in Artist.CHOICES_BLOOD_TYPE:
        #     if blood_type.strip() == full:
        #         blood_type = short
        #         break
        #     else:
        #         blood_type = Artist.BLOOD_TYPE_OTHER
        #
        # response = requests.get(url_img_cover)
        # binary_data = response.content
        # temp_file = BytesIO()
        # temp_file.write(binary_data)
        # temp_file.seek(0)
        #
        # artist, _ = Artist.objects.update_or_create(
        #     melon_id=artist_id,
        #     defaults={
        #         'name': name,
        #         'real_name': real_name,
        #         'nationality': nationality,
        #         'birth_date': datetime.strptime(birth_date_str, '%Y.%m.%d'),
        #         'constellation': constellation,
        #         'blood_type': blood_type,
        #     }
        # )
        #
        # file_name = Path(url_img_cover).name
        # artist.img_profile.save(file_name, File(temp_file))
        #
        album, _ = Album.objects.update_or_create_from_melon(album_id)
        # song.album.add(album)

        song, song_created = Song.objects.update_or_create(
            song_id=song_id,
            defaults={
                # 'album': Album.objects.get(title=album),
                'title': title,
                'genre': genre,
                'lyrics': lyrics,
                'album': album,
            }
        )

        artist, _ = Artist.objects.update_or_create_from_melon(artist_id)
        song.artists.add(artist)

        # file_name = Path(url_img_cover).name
        # file_name, temp_file = download(url_img_cover, song_id)
        temp_file = download(url_img_cover)
        file_name = '{song_id}.{ext}'.format(
            song_id=song_id,
            ext=get_buffer_ext(temp_file),
        )
        song.img_cover.save(file_name, File(temp_file))
        return song, song_created
예제 #19
0
    def authenticate(self, request, code):
        def get_access_token(auth_code):
            """
            유저가 페이스북에서 우리 애플리케이션의 사용에 대해 '승인'한 경우,
            페이스북에서 우리 애플리케이션의 주소(redirect_uri)에 'code'라는 GET parameter로 전해주는
            인증 코드 (auth_code)를 사용해서
            페이스북 GraphAPI에 access_token요청, 결과를 가져와 리턴
            :param auth_code: 유저가 페이스북에 로그인/앱 승인한 결과로 돌아오는 'code' GET parameter
            :return:
            """
            redirect_uri = 'http://localhost:8000/facebook-login/'
            # 아래 엔드포인트에 GET요청을 보냄
            params_access_token = {
                'client_id': self.CLIENT_ID,
                'redirect_uri': redirect_uri,
                'client_secret': self.CLIENT_SECRET,
                'code': auth_code,
            }
            response = requests.get(self.URL_ACCESS_TOKEN, params_access_token)
            # 전송받은 결과는 JSON형식의 텍스트. requests가 제공하는 JSON 디코더를 사용해서
            # JSON텍스트를 Python dict로 변환해준다
            response_dict = response.json()
            return response_dict['access_token']

        def get_user_info(user_access_token):
            """
            User access token을 사용해서
            GraphAPI의 'User'항목을 리턴
                (엔드포인트 'me'를 사용해서 access_token에 해당하는 사용자의 정보를 가져옴)
            :param user_access_token: 정보를 가져올 Facebook User access token
            :return: User정보 (dict)
            """
            params = {
                'access_token':
                user_access_token,
                'fields':
                ','.join([
                    'id',
                    'name',
                    'picture.width(2500)',
                    'first_name',
                    'last_name',
                ])
            }
            response = requests.get(self.URL_ME, params)
            response_dict = response.json()
            return response_dict

        try:  # -> 아래 인증과정에서 오류가 발생할 경우
            #    None을 리턴할 수 있도록.
            access_token = get_access_token(code)
            user_info = get_user_info(access_token)

            facebook_id = user_info['id']
            name = user_info['name']
            first_name = user_info['first_name']
            last_name = user_info['last_name']
            url_picture = user_info['picture']['data']['url']

            try:  # -> 회원가입되지 않은 유저의 경우 예외처리
                user = User.objects.get(username=facebook_id)
            except User.DoesNotExist:
                user = User.objects.create_user(
                    username=facebook_id,
                    first_name=first_name,
                    last_name=last_name,
                    # img_profile=,
                )

                # file_name = '{album_id}.{ext}'.format(
                #     album_id=album_id,
                #     ext=get_buffer_ext(temp_file),
                # )
                # 방법1 - 지우고 다시 만들기
                # if album.img_cover:
                #     album.img_cover.delete()

            # 사진이 없을 때만 저장하는 것으로 간단하게 실습.
            if not user.img_profile:
                temp_file = download(url_picture)
                ext = get_buffer_ext(temp_file)
                user.img_profile.save(
                    f'{user.pk}-{user.first_name}{user.last_name}.{ext}',
                    File(temp_file))
            return user

            # binary_data = request.get(url_picture)
            # user.img_profile.save(facebook_id, ContentFile(binary_data))

        except Exception:
            return None
예제 #20
0
    def update_or_create_from_melon(self, artist_id):
        artist = ArtistData(artist_id)
        artist.get_detail()
        name = artist.name
        url_img_cover = artist.url_img_cover
        real_name = artist.personal_information.get('본명', '')
        nationality = artist.personal_information.get('국적', '')
        birth_date_str = artist.personal_information.get('생일', '')
        constellation = artist.personal_information.get('별자리', '')
        blood_type = artist.personal_information.get('혈액형', '')

        # blood_type과 birth_date_str이 없을때 처리할것

        # 튜플의 리스트를 순회하며 blood_type을 결정
        for short, full in Artist.CHOICES_BLOOD_TYPE:
            if blood_type.strip() == full:
                blood_type = short
                break
        else:
            # break가 발생하지 않은 경우
            # (미리 정의해놓은 혈액형 타입에 없을 경우)
            # 기타 혈액형값으로 설정
            blood_type = Artist.BLOOD_TYPE_OTHER

        # url_img_cover는 이미지의 URL
        response = requests.get(url_img_cover)
        # requests에 GET요청을 보낸 결과의 Binary data
        binary_data = response.content
        # 파일처럼 취급되는 메모리 객체 temp_file를 생성
        temp_file = BytesIO()
        # temp_file에 이진데이터를 기록
        temp_file.write(binary_data)

        # 파일객체의 포인터를 시작부분으로 되돌림
        # temp_file.seek(0)
        # 해보니 위 seek 이 없어도 저장됨..
        # url 뒤에 붙어서 확장자 이상하게 저장되는 것만 막으면 됨

        artist, artist_created = self.update_or_create(
            melon_id=artist_id,
            defaults={
                'name':
                name,
                'real_name':
                real_name,
                'nationality':
                nationality,
                'birth_date':
                datetime.strptime(birth_date_str, '%Y.%m.%d')
                if birth_date_str else None,
                'constellation':
                constellation,
                'blood_type':
                blood_type,
            })

        temp_file = download(url_img_cover)
        file_name = '{artist_id}.{ext}'.format(
            artist_id=artist_id,
            ext=get_buffer_ext(temp_file),
        )

        # artist.img_profile필드의 save를 따로 호출, 이름과 File객체를 전달
        #   (Django)File객체의 생성에는 (Python)File객체를 사용,
        #           이 때 (Python)File객체처럼 취급되는 BytesIO를 사용
        artist.img_profile.save(file_name, File(temp_file))
        return artist, artist_created
예제 #21
0
    def authenticate(self, request, code):
        def get_access_token(auth_code):
            """
            user가 facebook에서 melon 어플리케이션의 사용에 대해 '승인'한 경우
            facebook에서 melon 어플리케이션의 주소(redirect_uri)에 'code'라는 GET parameter로 전해주는
            인증코드(auth_code)를 사용해서
            페이스북 GraphAPI에 access_token요청, 결과를 가져와 리

            :param auth_code: 유저가 페이스북에 로그인/앱 승인한 결과로 돌아오는 'code' GET parameter
            :return:
            """
            redirect_uri = "http://localhost:8000/facebook-login/"
            params_access_token = {
                'client_id': self.CLIENT_ID,
                'redirect_uri': redirect_uri,
                'client_secret': self.CLIENT_SECRET,
                'code': auth_code,
            }
            response = requests.get(self.URL_ACCESS_TOKEN, params_access_token)
            response_dict = response.json()
            return response_dict['access_token']

        def get_user_info(user_access_token):
            """
            User access token을 사용해서 GraphAPI의 'User'항목을 리턴
            (엔드포인트 'me'를 사용해서 access_token에 해당하는 사용자의 정보를 가져옴)
            :param user_access_token: 정보를 가져올 facebook user access token
            :return: User 정보(dict)
            """
            params = {
                'access_token':
                user_access_token,
                'fields':
                ','.join([
                    'id',
                    'name',
                    'picture.width(2500)',
                    'first_name',
                    'last_name',
                ])
            }

            response = requests.get(self.URL_ME, params)
            response_dict = response.json()
            return response_dict

        # {'id': '1746683798704556', 'name': 'S eokJae Hong', 'picture': {'data': {'height': 1079, 'is_silhouette': False, 'url': 'https://scontent.xx.fbcdn.net/v/t31.0-1/16904750_1386387041400902_7254244577969287703_o.jpg?oh=4bfe02828716d67e65fa5b422f32c6a3&oe=5B0B6A0E', 'width': 1092}}, 'first_name': 'SeokJae', 'last_name': 'Hong'}

        try:
            access_token = get_access_token(code)
            user_info = get_user_info(access_token)

            facebook_id = user_info['id']
            name = user_info['name']
            first_name = user_info['first_name']
            last_name = user_info['last_name']
            url_picture = user_info['picture']['data']['url']

            try:
                user = User.objects.get(username=facebook_id)
            except:
                user = User.objects.create_user(
                    username=facebook_id,
                    first_name=first_name,
                    last_name=last_name,
                )

            temp_file = download(url_picture)

            file_name = '{username}.{ext}'.format(
                username=facebook_id,
                ext=get_buffer_ext(temp_file),
            )
            if user.img_profile:
                user.img_profile.delete()
            user.img_profile.save(file_name, File(temp_file))

            return user
        except Exception:
            return None
예제 #22
0
    def authenticate(self, request, code):
        def get_access_token(auth_code):
            """
            유저가 페이스북에서 우리 애플리케이션의 사용에 대해 '승인'한 경우,
            페이스북에서 우리 애플리케이션의 주소(redirect_uri)에 'code'라는 GET parameter로 전해주는
            인증 코드 (auth_code)를 사용해서
            페이스북 GraphAPI에 access_token요청, 결과를 가져와 리턴
            :param auth_code: 유저가 페이스북에 로그인/앱 승인한 결과로 돌아오는 'code' GET parameter
            :return:
            """
            redirect_uri = 'http://localhost:8000/facebook-login/'
            # 아래 엔드포인트에 GET요청을 보냄
            params_access_token = {
                'client_id': self.CLIENT_ID,
                'redirect_uri': redirect_uri,
                'client_secret': self.CLIENT_SECRET,
                'code': auth_code,
            }
            response = requests.get(self.URL_ACCESS_TOKEN, params_access_token)
            # 전송받은 결과는 JSON형식의 텍스트. requests가 제공하는 JSON 디코더를 사용해서
            # JSON텍스트를 Python dict로 변환해준다
            response_dict = response.json()
            return response_dict['access_token']

        def get_user_info(user_access_token):
            """
            User access token을 사용해서
            GraphAPI의 'User'항목을 리턴
                (엔드포인트 'me'를 사용해서 access_token에 해당하는 사용자의 정보를 가져옴)
            :param user_access_token: 정보를 가져올 Facebook User access token
            :return: User정보 (dict)
            """
            params = {
                'access_token':
                user_access_token,
                'fields':
                ','.join([
                    'id',
                    'name',
                    'picture.width(2500)',
                    'first_name',
                    'last_name',
                ])
            }
            response = requests.get(self.URL_ME, params)
            response_dict = response.json()
            return response_dict

        try:
            access_token = get_access_token(code)
            user_info = get_user_info(access_token)

            facebook_id = user_info['id']
            name = user_info['name']
            first_name = user_info['first_name']
            last_name = user_info['last_name']
            url_picture = user_info['picture']['data']['url']

            try:
                user = User.objects.get(username=facebook_id)
                file_name, temp_file = download(url_picture, facebook_id)
                if user.img_profile:
                    user.img_profile.delete()
                user.img_profile.save(file_name, File(temp_file))

            except User.DoesNotExist:
                user = User.objects.create_user(
                    username=facebook_id,
                    first_name=first_name,
                    last_name=last_name,
                )
                file_name, temp_file = download(url_picture, facebook_id)
                if user.img_profile:
                    user.img_profile.delete()
                user.img_profile.save(file_name, File(temp_file))
            return user
        except Exception:
            return None
예제 #23
0
    def update_or_create_from_melon(self, artist_id):
        artist = ArtistData(artist_id)
        artist.get_detail()
        name = artist.name
        url_img_cover = artist.url_img_cover
        # .get: dict에서 key있으면 반환 없으면 ''
        real_name = artist.personal_information.get('본명', '')
        nationality = artist.personal_information.get('국적', '')
        birth_date_str = artist.personal_information.get('생일', '')
        constellation = artist.personal_information.get('별자리', '')
        blood_type = artist.personal_information.get('혈액형', '')

        for short, full in Artist.CHOICE_BLOOD_TYPE:
            if blood_type.strip() == full:
                blood_type = short
                break
            else:
                blood_type = Artist.BLOOD_TYPE_OTHER

        artist, artist_created = self.update_or_create(
            melon_id=artist_id,
            defaults={
                'name':
                name,
                'real_name':
                real_name,
                'nationality':
                nationality,
                'birth_date':
                datetime.strptime(birth_date_str, '%Y.%m.%d')
                if birth_date_str else None,
                'constellation':
                constellation,
                'blood_type':
                blood_type,
            })
        # img_profile필드에 저장할 파일확장자를 바이너리 데이터 자체의 MIME_TYPE에서 가져옴
        # 파일명은 artist_id를 사용
        #
        # def download(url):
        #     # url로부터 다운받은 데이터를 BytesIO객체에 쓰고 리턴
        #     response = requests.get(url)
        #     binary_data = response.content
        #     temp_file = BytesIO()
        #     temp_file.write(binary_data)
        #     temp_file.seek(0)
        #     return temp_file
        # def get_buffer_ext(buffer):
        #     buffer.seek(0)
        #     mime_info = magic.from_buffer(buffer.read(), mime=True)
        #     buffer.seek(0)
        #     return mime_info.split('/')[-1]

        temp_file = download(url_img_cover)
        file_name = '{artist_id}.{ext}'.format(
            artist_id=artist_id,
            ext=get_buffer_ext(temp_file),
        )
        if artist.img_profile:
            artist.img_profile.delete()
        artist.img_profile.save(file_name, File(temp_file))
        return artist, artist_created