회사에서 대내/외 로 사용중인 모바일 애플리케이션 정보를 자동으로 수집하기 위해 스크래핑에 대한 내용을 찾아보게 되었다.
Python에서 스크래핑을 위한 여러 패키지 라이브러리가 많이 개발되어 있었다. 그 중 가장 널리 쓰이고 있고 많은 구글링에서 보여주고 있어서, 우선 순위로 생각하고 있던 것이 아래 두개 라이브러리이다.
하지만 위 패키지를 적용하다 보니, 내가 원하는 데이터를 가져오지 못하는 이슈가 있었다.
참조 링크
# Python PATH
alias python="python3"
PATH="/Library/Frameworks/Python.framework/Version/3.11/bin:${PATH}" export PATH
python -V
Pycharm 사이트에서 무료 Pycharm 다운로드 및 설치( JetBrains에서 만든 Python 용 IDE )
- Android Studio 만든 곳에서 만들었다 보니깐 GUI가 아예 똑같음. 친숙한 느낌이 들어 사용해 보았다.
새로운 프로젝트 만들기
기본적으로 메인.py에 샘플코드가 들어가 있다. 바로 Configuration을 run 해보면 코드가 수행된다.
ex) BeautifulSoup 패키지 설치 시
https://pypi.org/project/beautifulsoup4/ 이동 해서 install command ctrl+c
terminal 에 ctrl+v
추가된 패키지 확인 가능
pip install beautifulsoup4
pip install requests
pip install datetime2
import json
import ssl
from bs4 import BeautifulSoup
import requests
from datetime import datetime
# iOS 앱 아이디 목록
app_id_list = [
'541164041', # microsoft-office
'586449534', # microsoft-powerpoint
'586447913', # microsoft-word
'586683407', # microsoft-excel
'1113153706', # microsoft-teams
'477537958', # microsoft-onedrive
'1091505266', # microsoft-sharepoint
'951937596', # microsoft-outlook
'410395246', # microsoft-onenote
'1401013624', # microsoft-stream
'289559439', # yammer
]
# 시간 포맷 변경
def convertDate(date_str):
real_date = datetime.strptime(date_str.replace('T', ' ').replace('Z', ''), '%Y-%m-%d %H:%M:%S')
return real_date.strftime("%Y%m%d")
# 앱 데이터 요청
def requestAppData():
# SSL 통신 혀용
ssl._create_default_https_context = ssl._create_unverified_context
# SSL인증서 확인 무시, 경고 표시 없애기
requests.packages.urllib3.disable_warnings(requests.packages.urllib3.exceptions.InsecureRequestWarning)
for app_id in app_id_list:
request_url = 'http://itunes.apple.com/kr/lookup?id=' + app_id
source_code = requests.get(request_url, verify=False)
html = source_code.text.encode('utf-8', 'replace')
soup = BeautifulSoup(html, "html.parser")
json_object = json.loads(str(soup))
# resultJson = json.dumps(jsonObject, indent="\t", ensure_ascii=False)
# print(resultJson)
for j_key, j_value in json_object.items():
if j_key == 'results':
for key, value in j_value[0].items():
if key == 'trackName':
name = value
if key == 'bundleId':
bundle_id = value
if key == 'version':
version = value
if key == 'releaseDate':
open_date = convertDate(value)
if key == 'currentVersionReleaseDate':
update = convertDate(value)
print('id : ' + app_id)
print('name : ' + name)
print('bundleId : ' + bundle_id)
print('version : ' + version)
print('update : ' + update)
print('openDate : ' + open_date)
print('appOs : ' + 'IOS')
print()
# TODO: - 정보 확보 후 처리할 동작 추가
requestAppData()
pip install selenium
pip install undetected-chromedriver
from time import sleep
from selenium.webdriver.common.by import By
import undetected_chromedriver as uc
aos_pkg_list = [
'com.microsoft.office.officehubrow',
'com.microsoft.office.powerpoint',
'com.microsoft.office.word',
'com.microsoft.office.excel',
'com.microsoft.teams',
'com.microsoft.skydrive',
'com.microsoft.sharepoint',
'com.microsoft.office.outlook',
'com.microsoft.office.onenote',
'com.microsoft.stream',
'com.yammer.v1',
]
# 크롬 드라이버 시작후, 구글 계정 로그인
def loginAccount(pkg_nm):
driver = uc.Chrome()
driver.get('https://play.google.com/store/apps/details?id=' + pkg_nm)
driver.implicitly_wait(1)
# 로그인 버튼 클릭
login_button = driver.find_element(By.XPATH, '//*[@id="kO001e"]/header/nav/div/c-wiz/div/div/div[1]/button')
login_button.click()
driver.implicitly_wait(1)
sleep(3)
# 구글 계정 입력
account_button = driver.find_element(By.XPATH,
'//*[@id="kO001e"]/header/nav/div/c-wiz/div/div/div[2]/div/ul/li[1]/span[3]')
account_button.click()
driver.implicitly_wait(1)
sleep(3)
email_input = driver.find_element(By.XPATH, '//*[@id="identifierId"]')
email_input.send_keys('본인 구글계정 기입')
driver.implicitly_wait(1)
next_button = driver.find_element(By.XPATH, '//*[@id="identifierNext"]/div/button')
next_button.click()
driver.implicitly_wait(1)
sleep(3)
# 비밀번호 입력
password_input = driver.find_element(By.XPATH, '//*[@id="password"]/div[1]/div/div[1]/input')
password_input.send_keys('본인 구글 패스워드 기입')
driver.implicitly_wait(1)
next_btn = driver.find_element(By.XPATH, '//*[@id="passwordNext"]/div/button')
next_btn.click()
driver.implicitly_wait(1)
sleep(3)
# 본인 확인을 위한 번호 정보
try:
check_number = driver.find_element(By.XPATH,
'//*[@id="view_container"]/div/div/div[2]/div/div[1]/div/form/span/section/div/div/span/figure/samp')
print('check number : ' + check_number.text)
sleep(10)
except:
print('keep going')
sleep(30)
# 본인 핸드폰에서 본인 확인 번호 입력
return driver
# 제일 낮은 버전 선택
def selectMinimumVersion(versions):
# for version in versions:
# print(version.text)
return versions[1].text
# 제일 낮은 업데이트 날짜 선택
def selectMinimumUpdate(updates):
# for update in updates:
# print(update.text)
return updates[1].text
# 날짜 포맷 변환
def convertDate(date):
try:
ymd_dates = date.split('.')
yyyy = ymd_dates[0].strip()
mm = ymd_dates[1].strip()
dd = ymd_dates[2].strip()
if int(mm) < 10:
mm = '0' + mm.strip()
if int(dd) < 10:
dd = '0' + dd.strip()
return yyyy + mm + dd
except:
return 'null'
# 앱의 버전정보, 업데이트 일자 등을 크롤링을 통해 가져온다.
def getUpdateInfoWithCrawl(driver, pkg_id):
driver.get('https://play.google.com/store/apps/details?id=' + pkg_id)
driver.implicitly_wait(1)
# 앱 정보 상세 팝업 클릭
try:
button = driver.find_element(By.XPATH,
'//*[@id="yDmH0d"]/c-wiz[2]/div/div/div[1]/div[2]/div/div[1]/c-wiz[6]/div/section/header/div/div[2]/button')
except:
button = driver.find_element(By.XPATH,
'//*[@id="yDmH0d"]/c-wiz[2]/div/div/div[1]/div[2]/div/div[1]/c-wiz[2]/div/section/header/div/div[2]/button/i')
button.click()
sleep(1)
driver.implicitly_wait(1)
# 앱 명칭
names = driver.find_element(By.XPATH, '//*[@id="yDmH0d"]/div[4]/div[2]/div/div/div/div/div[1]/div/div/h5')
name = names.text
# 앱 버전
versions = driver.find_elements(By.XPATH, '//div[text()="버전"]/following-sibling::div')
version = selectMinimumVersion(versions)
# 업데이트 날짜
updates = driver.find_elements(By.XPATH, '//div[text()="업데이트 날짜"]/following-sibling::div')
update = convertDate(selectMinimumUpdate(updates))
# 출시 날짜
try:
open_dates = driver.find_element(By.XPATH, '//div[text()="출시일"]/following-sibling::div')
open_date = convertDate(open_dates.text)
except:
open_date = '00000000'
print('name : ' + name)
print('packageId : ' + pkg_id)
print('version : ' + version)
print('openDate : ' + open_date)
print('upDate : ' + update)
print('appOs : ' + 'AOS')
print('')
# TODO: - 정보 확보 후 처리할 동작 추가
driver = loginAccount(aos_pkg_list[0])
lists = []
for pkg_id in aos_pkg_list:
getUpdateInfoWithCrawl(driver, pkg_id)