โ๐ป ๋ฐฐ์ด์
selenium ๋ฟ ๋ง ์๋๋ผ api ๋ ์ฌ์ฉํ์ฌ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๋ ๋ฐฉ๋ฒ์ ๋ํด ๋ฐฐ์ธ ์ ์์๊ณ , DataFrame ์ ๋ค๋ฃจ๋ ๋ฐฉ๋ฒ์ ๋ํด ๋ ์๊ฒ ๋์๋ค.
๐ ๋ชฉ์ฐจ
1. webdriver Option
2. ์ ๊ตญ ์ธ๋ธ์ผ๋ ๋ธ ์ง์ ์ ๋ณด ๊ฐ์ ธ์ค๊ธฐ by selenium
3. ์ ๊ตญ ์ธ๋ธ์ผ๋ ๋ธ ์ง์ ์ ๋ณด ๊ฐ์ ธ์ค๊ธฐ by API
4. pandas concat
5. DataFrame ์์ index ์ ๊ฑฐํ๊ธฐ
6. DataFrame ์์ ์ค๋ณต ์ ๊ฑฐํ๊ธฐ
7. DataFrame ์์ ๊ณ ์ ํ ๊ฐ ์ฐพ๊ธฐ
8. DataFrame ์ excel ๋ก ์ ์ฅํ๊ธฐ
๋ค์ด๊ฐ๋ฉฐ
์ด๋ฒ์๋ ์ธ๋ธ์ผ๋ ๋ธ ํธ์์ ์ ํฌ ๊ธฐ์ค์ผ๋ก ๊ธ์ ์์ฑํ์ต๋๋ค. ์ฐธ๊ณ ๋ถํ๋๋ฆฝ๋๋ค :)
webdriver Options
webdriver ๋ฅผ ์ฌ์ฉํ์ฌ Chrome ์ฐฝ์ ๋์ธ ๋, ์ฐ๋ฆฌ ๋์ ๋ณด์ด์ง ์๊ณ ๋ฐฑ๊ทธ๋ผ์ด๋ ํ๊ฒฝ์์ ๋๊ฒ ํ ์ ์๋ค.
import selenium import webdriver
options = webdriver.ChromeOptions()
options.add_argument('headless')
ChromeOption ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ฉด ํฌ๋กฌ ํ์ด์ง๊ฐ ๋ณด์ด์ง ์์๋ ์ ์คํ๋ ์ ์๋ค.
์ ๊ตญ ์ธ๋ธ์ผ๋ ๋ธ ์ง์ ์ ๋ณด ๊ฐ์ ธ์ค๊ธฐ by selenium
์ ๊ตญ์ ์๋ ์ธ๋ธ์ผ๋ ๋ธ ํธ์์ ์ง์ ์ ๋ณด๋ฅผ ๊ฐ์ ธ์ค๋๋ก ํ์.
๋ฉ์ธ ํ์ด์ง์์ ์ ํฌ์ฐพ๊ธฐ ๋ฒํผ์ ํด๋ฆญํ๋ฉด get ๋ฐฉ์์ ํตํด ์น ํ์ด์ง์ ์ ๊ทผํด์ผ ํ๋ค๋ ๊ฒ์ ์ ์ ์๋ค.
๋ฉ์ธ ํ์ด์ง์์ ๋ฐ์ดํฐ๊ฐ ์๋ ๊ณณ๊น์ง ๊ฐ๊ธฐ์ํด '์ ํฌ์ฐพ๊ธฐ' ๋ผ๋ ๋ฒํผ์ ํด๋ฆญํด์ผ ํ๋ฏ๋ก selenium ์ ์ฌ์ฉํ์ฌ ์๋ํ ํด๋ฆญ์ ํ๋๋ก ํ๋ค.
from selenium import webdriver
from selenium.webdriver.common.by import By
import time
from bs4 import BeautifulSoup as BS
import requests
import re
import pandas as pd
driver = webdriver.Chrome()
url = "https://www.7-eleven.co.kr/"
driver.get(url) # get ๋ฐฉ์
# ์ ํฌ ์ฐพ๊ธฐ ๋ฒํผ ์์น
target_store = "#header > div > div > div.head_util > a.util_store.store_open"
# ์ ํฌ ์ฐพ๊ธฐ ๋ฒํผ ์๋ ํด๋ฆญ
driver.find_element(By.CSS_SELECTOR, target_store).click()
time.sleep(3) # ํ์ด์ง ๋ก๋ฉ ์๊ฐ ๊ธฐ๋ค๋ ค์ฃผ๊ธฐ
์์์ ๋งํ ์์ ์ ๋คํ๊ณ ์ด์ ์ง์ญ๋ณ ๋์ ์ด๋ฆ๋ค์ ๋ค ๋ฐ์์์ผ ํ๋ค.
๊ทธ๋ฌ๊ธฐ ์ํด ๋ selenium ์ ์ฌ์ฉํ์ฌ ์ ๋ณด๋ฅผ ์ป์ด์์ผ ํ๋ค.
city_dict = {} # dictionary ๋ก ์ ์ฅ
for x in range(2, 19): # ์, ๋ ๊ฐ์๋งํผ
driver.find_element(By.CSS_SELECTOR, f"#storeLaySido > option:nth-child({x})").click()
time.sleep(2)
# ์, ๋ ์ด๋ฆ ๊ฐ์ ธ์ค๊ธฐ
city = driver.find_element(By.CSS_SELECTOR, f"#storeLaySido > option:nth-child({x})").text
# key: ์/๋ , valaue: ๊ตฌ/๊ตฐ
city_dict[city] = [x.text for x in BS(drvier.page_source).find("select", id="storeLayGu")][3::2]
# ์ ์ ์ฅ๋์ด ์๋ ์ง ํ์ธํ๊ธฐ
for key, value in city_dict.items():
print(key, value)
css ๋ฌธ๋ฒ์ผ๋ก ์ ๊ทผํ๋ฉด ํธ๋ฆฌํ๊ธฐ์... ์ ์๋๋ก ํ์...
์ ๊ตญ ์ธ๋ธ์ผ๋ ๋ธ ์ง์ ์ ๋ณด ๊ฐ์ ธ์ค๊ธฐ by API
์ด๋ฒ์๋ ์ธ๋ธ์ผ๋ ๋ธ์์ ์ ๊ณตํ๋ API ๋ฅผ ์ด์ฉํด๋ณด์.
from selenium import webdriver
from selenium.webdriver.common.by import By
import time
from bs4 import BeautifulSoup as BS
import requests
import re
import pandas as pd
seven_url = "https://www.7-eleven.co.kr/util/storeLayerPop.asp"
payload = payload = {"storeLaySido": "์์ธ",
"storeLayGu": "๊ตฌ๋ก๊ตฌ",
"hiddentext": "none"}
r = requests.post(seven_url, data=payload)
def api_seven(page):
seven = BS(page)
seven_total = []
for temp in seven.find("div", class_="list_stroe").findAll("li"):
seven_dict = {}
# ์ง์ ๋ณ ์๋น์ค ํญ๋ชฉ ์ฐพ์์ ์ ์ฅ
seven_dict['offeringService'] = [ x['alt'] for x in temp.findAll("img")]
# ์ง์ ๋ช
์๋ ๊ณณ ์ฐพ์ ์ ์ฅ(๊ณต๋ฐฑ ์ ๊ฑฐ์ฉ strip ์ฌ์ฉ)
seven_dict['shopName'] = temp.find("span").text.strip()
try:
# ์ง์ ์ฃผ์ ์ฐพ์ ์ ์ฅ
seven_dict['address'] = " ".join(temp.findAll("span")[-2].text.split())
except:
return []
# ์ค๋ณต ์์ด ์ ์๋ ๊ฒฝ์ฐ
if len(seven_dict['address']) < 2:
seven_dict['address'] = " ".join(temp.findAll("span")[-3].text.split())
# ์๋ ๊ฒฝ๋ ์ฐพ์ ์ ์ฅ
_, lat, lon = re.findall("(?<=\().+(?=\))", temp.find('a')['href'])[0].split(",")
seven_dict['longs'] = lon
seven_dict['lat'] = lat
# seven_total ์ ๋ฃ๊ธฐ
seven_total.append(seven_dict)
return pd.DataFrame(seven_total)
seven_total ์ ์ง์ ๋ณ ์๋น์ค, ์ฃผ์, ์๋, ๊ฒฝ๋๋ฅผ ์ ์ฅํ์ฌ df ๋ก ๋ง๋๋ ํจ์์ด๋ค.
total = []
for key, value in city_dict.items(): # ์/๋(key), ๊ตฌ/๊ตฐ(value)
payload['storeLaySido'] = key
for x in value:
payload['storeLayGu'] = x
# total ์ ์์์ ๋ง๋ ์ ๋ณด ๋ค ์ ์ฅํ๊ธฐ
total.append(api_seven( requests.post(seven_url, data=payload).text ))
์ด์ api ๋ก ์ ๊ตญ ์ธ๋ธ ํธ์์ ์ ๋ณด์ ๋ํด total dictionary ์ ์ ์ฅํ๋ค.
pandas concat
pandas ์์ ์ ๊ณตํ๋ ๋ฉ์๋์ธ concat() ์ ์ฌ์ฉํ๋ฉด df ๋ผ๋ฆฌ ํฉ์ณ์ (์๋ณธ ๋ฐ์ดํฐ ๋ณ๊ฒฝ์์ด) ์๋ก์ด df ๋ฅผ ๋ง๋ค ์ ์๋ค.
total = pd.concat([x for x in total if type(x) == type(pd.DataFrame())])
total
๋ง์ฝ total ์์ df ๋ก ์ ๋ง๋ค์ด์ก๋ค๋ฉด, df ๋ก ์ ๋์ค๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
DataFrame ์์ index ์ ๊ฑฐํ๊ธฐ
ํ์ด์ฌ์์ DataFrame ์ ๊ธฐ๋ณธ index ๋ฅผ ์ ๊ฑฐํ ์ ์๋ค.
total.reset_index(drop=True, inplace=True)
pandas ์ ๋ฉ์๋์ธ reset_index ๋ฅผ ์ฌ์ฉํ๋ฉด, index column ์ ์ ๊ฑฐํ ๊ฒ์ธ์ง, ์๋ณธ df ๋ฅผ ๋ฐ๊ฟ ๊ฒ์ธ์ง ์ ํํ ์ ์๋ค.
DataFrame ์์ ์ค๋ณต ์ ๊ฑฐํ๊ธฐ
ํ์ด์ฌ์์ DataFrame ์ ํน์ column ์์ ๊ฐ์ด ์ค๋ณต๋ ๊ฒฝ์ฐ ์ ๊ฑฐํ ์ ์๋ค.
total.drop_duplicates('shopName')
pandas ์ ๋ฉ์๋์ธ drop_duplicates() ๋ฅผ ์ฌ์ฉํ๋ฉด, ํน์ column ๊ฐ์ด ์ค๋ณต๋ ๊ฒ๋ค์ df ์์ ์ ๊ฑฐํด์ค๋ค.
DataFrame ์์ ๊ณ ์ ํ ๊ฐ ์ฐพ๊ธฐ
ํ์ด์ฌ์์ DataFrame ์ ํน์ column ์์ ๊ณ ์ ํ ๊ฐ๋ง ์ฐพ์ ์ ์๋ค.
total['shopName'].unique() # .size() ๋ง ๋ถ์ด๋ฉด ๊ณ ์ ๊ฐ ๊ฐ์ ๊ตฌํ ์ ์์
์ค๋ณต๋ ๊ฐ ์์ด, ๊ณ ์ ํ ๊ฐ์ด ๋ฌด์์ธ์ง ์ฐพ๋๋ฐ ์ฌ์ฉ๋๋ค.
DataFrame ์ excel ๋ก ์ ์ฅํ๊ธฐ
ํ์ด์ฌ์์ DataFrame ์ excel ํ์ผ๋ก ์ ์ฅํ ์ ์๋ค.
total.to_excel("./์ธ๋ธ์ผ๋ ๋ธ_์ ๊ตญ_ํํฉ.xlsx")
pandas ์ ๋ฉ์๋์ธ to_excel() ์ ์ฌ์ฉํ๋ฉด ์์ ํ์ผ๋ก ๋ง๋ค ์ ์๋ค.
'Python > [๊ธฐ์ด ๊ฐ์ ์ ๋ฆฌ]' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
python ๊ธฐ์ด 9 (0) | 2023.03.01 |
---|---|
python ๊ธฐ์ด 8 (0) | 2023.02.26 |
python ๊ธฐ์ด 6 (0) | 2023.02.26 |
python ๊ธฐ์ด 5 (0) | 2023.02.26 |
python ๊ธฐ์ด 4 (1) | 2023.02.25 |