22년 5월의 공부 - DataFrame & Dict, mouse hover in 크롤링
포스트
취소

22년 5월의 공부 - DataFrame & Dict, mouse hover in 크롤링

2022년 5월 동안 검색하고 공부한 것들을 정리한 내용입니다.

1. DataFrame & Dictionary

dictionary 객체를 pandas의 DataFrame으로 변환할 경우, key값은 컬럼명으로 각 key에 대한 value는 컬럼값으로 들어갑니다.

1
2
3
4
5
6
import pandas as pd

dict1 = {'A':[1,2,3],'B':[4,5,6]}

df1 = pd.DataFrame(dict1)
df1

image

DataFrame을 dictionary로 변경하는 방법은 2가지가 있습니다.

  1. pd.Series : index가 key가 되고, Series의 값이 value가 됩니다.
  2. pd.DataFrame : 2개의 컬럼만 있는 DataFrame의 value만 가져오는 경우, 앞의 컬럼이 key 그리고 뒤의 컬럼이 value가 됩니다.
1
2
3
4
5
# pd.Series with index
dict(df1['A']) # {0: 1, 1: 2, 2: 3}

# value of pd.DataFrame with 2 columns
dict(df1.values) # {1: 4, 2: 5, 3: 6}

2. 크롤링(Crawling) - 동적 웹페이지 & 마우스 오버

  • 동적 웹페이지
    • 동적 웹페이지란 url만으로는 들어갈 수 없는 웹페이지를 말합니다.
    • 혹시 들어가지더라도 url의 변화가 없는데도 실시간으로 내용이 계속해서 추가되거나 수정된다면 동적 웹 페이지입니다.
    • 여기서 무언가를 클릭해서 페이지가 변경되는 것은 다른 경우입니다.
  • 사례
    1. 로그인을 해야만 접속 가능한 네이버 메일
    2. 보고 있는 위치에 출력 결과와 url이 계속 변하는 네이버 지도
    3. 드래그를 아래로 내리면 계속 새로운 사진과 영상이 나타나는 인스타그램과 유튜브

출처 : 사장님 몰래 하는 파이썬 업무자동화(부제 : 들키면 일 많아짐), 정용범, 손상우 외 1명

아래와 같이 마우스의 위치에 따라 카테고리 정보가 바뀌는 ‘네이버 쇼핑’의 카테고리 정보를 얻고자 합니다.

image

마우스 위치 조정 in selenium

ActionChains() 함수를 이용해 마우스의 행동을 제어할 수 있습니다. perform()을 명시해줘야 실행됩니다.

1
2
3
4
5
# 마우스 위치 지정
move1 = driver.find_element(By.XPATH,"/html/body/div[1]/div[1]/div/div[1]/div/div/div[2]/div/div[3]/div/div/div[1]/ul/li["+str(i)+"]/a")

# 마우스 이동
ActionChains(driver).move_to_element(move1).perform()

string → list

string타입의 데이터를 list로 변경하는 방법은 list(a)[a] - 2가지가 있습니다. 하지만 string타입은 iterable 하므로 2가지 방법의 결과물은 차이가 있습니다.

1
2
3
4
5
6
7
a = '가나다라'

# 1.
list(a) # ['가', '나',' 다',' 라']

# 2.
[a] # ['가나다라']

다른 길이의 list 조합 생성

for 반복문을 실행하며 지정된 ‘대분류’, ‘중분류’와 이에 대한 ‘소분류’ 간의 조합을 만들고자 합니다. cycle 함수를 통해 element를 반복 입력하여 원하는 조합을 생성할 수 있습니다.

1
2
3
4
5
from itertools import cycle

a = ['a']
b = ['b','c','d']
list(zip(cycle(a),b)) # [('a', 'b'), ('a', 'c'), ('a', 'd')]

전체코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# naver_shopping_category.py
import selenium
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from selenium.webdriver.common.action_chains import ActionChains

import time
from itertools import cycle
import pandas as pd

# 옵션 설정
s = Service('./chromedriver')
options = webdriver.ChromeOptions()
options.add_argument('headless')
options.add_argument('window-size=1920x1080')
options.add_argument("disable-gpu")
options.add_argument("user-agent=Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36")
driver = webdriver.Chrome(service=s, options=options)

driver.get('https://shopping.naver.com/home/p/index.naver')

# '카테고리 더보기' 클릭
driver.find_element(By.XPATH,'/html/body/div[1]/div[1]/div/div[1]/div/div/div[2]/div/div[3]/button').click()

time.sleep(2)

# '대분류'명 수집
element1 = driver.find_element(By.CLASS_NAME,"_categoryLayer_main_category_2A7mb").text.split("\n")[1:]

cat_lst = []
for i in range(1,len(element1)):
    # '대분류' 항목으로 마우스 오버
    move1 = driver.find_element(By.XPATH,"/html/body/div[1]/div[1]/div/div[1]/div/div/div[2]/div/div[3]/div/div/div[1]/ul/li["+str(i)+"]/a")
    ActionChains(driver).move_to_element(move1).perform()

    time.sleep(1)

    # '중분류'명 수집
    element2 = driver.find_element(By.CLASS_NAME,"_categoryLayer_middle_category_2g2zY").text.split("\n")[1:]    

    for j in range(1,min(22,len(element2))):
        # '중분류' 항목으로 마우스 오버
        move2 = driver.find_element(By.XPATH,"/html/body/div[1]/div[1]/div/div[1]/div/div/div[2]/div/div[3]/div/div/div[2]/ul/li["+str(j)+"]/a")
        ActionChains(driver).move_to_element(move2).perform()
        time.sleep(1)

        # '소분류'명 수집
        try:
            element3 = driver.find_element(By.CLASS_NAME,"_categoryLayer_subclass_1K649").text.split("\n")[1:]
        except:
            element3 = []
        a = [element1[i-1]]
        b = [element2[j-1]]
        c = element3

        # (대분류,중분류,소분류) 조합 생성
        zip_lst = zip(cycle(a),cycle(b),c)
        cat_lst.append(list(zip_lst))

# 데이터 처리
df1 = pd.DataFrame(cat_lst)
df1 = pd.melt(df1,value_vars=df1.columns).dropna()
df1 = pd.DataFrame(df1.value.to_list(),columns=['대분류','중분류','소분류'])
df1 = df1.sort_values(['대분류','중분류','소분류'])
df1.reset_index().iloc[:,1:].to_csv("naver_shopping_category.csv")

# 종료
driver.quit()
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.