Intro
한국의 대표 알람 앱, 알라미의 리뷰들을 보고 싶은 데서 이번 실험은 시작됐다.
알라미는 딜라이트룸에서 개발한 앱으로, 2022년 기준 매출 192억원(!!!)을 낸,
전세계적으로 사랑받고 있는 알람 앱이다.
나도 꽤 오래전부터 이 알람 앱을 이용해왔고, 정말 좋은 앱이라고 생각한다.
스마트폰 앱스토어에서는 리뷰를 볼 수는 있지만 스크랩하기 어렵고,
웹에서는 제한된 숫자(약 30개)의 리뷰만을 볼 수 있어,
많은 리뷰를 한 번에 보기는 어렵다.
이에 최근 작성된 500개의 리뷰를 볼 수 있게 제공된 XML을 이용해 스크래퍼를 만들어보았고,
(1) 알라미 앱 뿐만 아니라 다른 앱의 리뷰도 스크래핑 할 수 있고
(2) 한국 뿐 아니라 다른 나라의 리뷰도 볼 수 있는 스크래퍼로 발전시켜보았다.
코드 git repository
https://github.com/whdrns2013/lab/tree/main/20230129_apple_app_review_scrapper
Environment
이번 실험에서 사용된 환경과 라이브러리는 아래와 같다.
- Python 3.8
- BeautifulSoup
- urllib
- pandas
Elements
리뷰 xml
앱스토어의 앱 리뷰 xml 경로는 아래와 같은 규칙을 가지고 있다.
https://itunes.apple.com/{country}/rss/customerreviews/page={page}/id={app_id}/sortby=mostrecent/xml?urlDesc=/customerreviews/id={app_id}/sortBy=mostRecent/xml
예를 들어, 알라미의 한국 리뷰 xml은 아래와 같다. (1페이지/10페이지)
https://itunes.apple.com/kr/rss/customerreviews/page=1/id=1163786766/sortby=mostrecent/xml?urlDesc=/customerreviews/id=1163786766/sortBy=mostRecent/xml
리뷰 xml 요소 분석
xml에서 각 리뷰는 아래와 같은 구조를 가지고 있다.
(개인이 특정 될 수 있는 내용은 가명화 함.)
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
<entry>
<id>###가명화:리뷰id(로 추정)###</id>
<title>###가명화:제목입니다.###</title>
<content type="text">###가명화:리뷰 내용이 포함됩니다.###</content>
<im:contentType term="Application" label="앱"/>
<im:voteSum>0</im:voteSum>
<im:voteCount>0</im:voteCount>
<im:rating>4</im:rating>
<updated>2023-01-27T19:56:37-07:00</updated>
<im:version>6.77.2</im:version>
<author>
<name>###가명화###</name>
<uri>https://itunes.apple.com/kr/reviews/id###가명화###</uri>
</author>
<link rel="related" href="https://itunes.apple.com/kr/review?id=1163786766&type=
Purple%20Software"/>
<content type="html"><table border="0" width="100%"> <tr> <td>
<table border="0" width="100%" cellspacing="0" cellpadding="0">
<tr valign="top" align="left"> <td width="100%"> <b>
<a href="https://apps.apple.com/kr/app/%EC%95%8C%EB%9D%BC%EB%AF%B8-
%EC%83%81%EC%BE%8C%ED%95%9C-
%EC%95%84%EC%B9%A8%EC%9D%84-%EC%9C%84%ED%95%9C-
%EC%95%8C%EB%9E%8C%EC%8B%9C%EA%B3%84-%EC%88%98%EB%A9%B4-
%EC%82%AC%EC%9A%B4%EB%93%9C/id1163786766?uo=2">
###가명화:제목입니다.###</a>
</b><br/> <font size="2" face="Helvetica,Arial,Geneva,Swiss,SunSans-Regular">
</font>
</td> </tr> </table> </td> </tr> <tr>
<td> <font size="2" face="Helvetica,Arial,Geneva,Swiss,SunSans-Regular"><br/>
###가명화:리뷰 내용이 포함됩니다.###</font><br/> </td>
</tr> </table> </content>
</entry>
각 리뷰는
(1) <entry>
태그로 둘러쌓여 있다.
(2) <title>
태그에 리뷰 제목이 포함되어있다.
(3) <content>
태그에 리뷰 내용이 포함되어있다.
(4) <im:rating>
태그에 별점이 포함되어있다.
(5) <updated>
태그에 업데이트일(작성일)이 포함되어있다.
(6) <im:version>
태그에 앱 버전이 포함되어있다.
(7) <name>
태그에 작성자 이름이 포함되어있다.
Elements 정리
하나. url에서 정의할 항목은 총 세 가지이다.
(1) country : 국가코드
(2) app_id : 해당 앱의 앱 코드
(3) page : 리뷰 페이지. 페이지당 50개의 리뷰가 포함됨.
총 10개의 페이지가 제공된다.
둘. xml에서 추출할 항목은 총 6가지이다.
<entry>
태그 내에서
(1) title 태그
(2) content 태그
(3) im:rating 태그
(4) updated 태그
(5) im:version 태그
(6) name 태그
참고
- 앱 코드는 앱스토어 주소창에서 확인 가능 (id 뒤의 숫자만)
- 국가코드는 아래 페이지에서 확인 가능 (영문 두글자)
https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2
Code
1
2
3
4
5
6
7
8
9
10
11
# 스크래핑 대상 및 최종 자료 파일 이름 정의
country = 'us' # 국가 코드
app_id = '1163786766' # 앱스토워 웹페이지에서 확인 가능
app_name = 'alarmy' # 아무거나 입력해도 됨
scrap_date = '20230129' # 스크래핑 일자 (달라도 상관 없음)
last_page = 10 # 현재 10페이지까지만 지원됨
file_name = f'scrap_apple_{app_name}_{country}_{scrap_date}.csv' # 저장할 파일 이름
# 국가코드 -- 한국 : kr / 미국 : us ...
# 그 외 국가코드는 https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2
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
# 스크랩 메서드 정의
def scrapping_alarmy_apple(page_num, app_id, country):
from bs4 import BeautifulSoup
import urllib.request
url_start = f'https://itunes.apple.com/{country}/rss/customerreviews/page='
url_end = f'/id={app_id}/sortby=mostrecent/xml?urlDesc=/customerreviews/id={app_id}/sortBy=mostRecent/xml'
html = urllib.request.urlopen(url_start + str(page_num) + url_end)
soup = BeautifulSoup(html, 'html.parser')
soups = soup.find_all('entry')
title = []
content = []
rating = []
date = []
version = []
name = []
for soup in soups:
try:
title.append(soup.find('title').string)
except:
title.append('None')
try:
content.append(soup.find('content', attrs={'type':'text'}).string)
except:
content.append('None')
try:
rating.append(soup.find('im:rating').string)
except:
rating.append('None')
try:
date.append(soup.find('updated').string)
except:
date.append('None')
try:
version.append(soup.find('im:version').string)
except:
version.append('None')
try:
name.append(soup.find('name').string)
except:
name.append('None')
return title, content, rating, date, version, name
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
# 스크랩 실행
ls_title = []
ls_content = []
ls_rating = []
ls_date = []
ls_version = []
ls_name = []
for i in range(1, last_page + 1):
title, content, rating, date, version, name = scrapping_alarmy_apple(i, app_id, country)
ls_title.append(title)
ls_content.append(content)
ls_rating.append(rating)
ls_date.append(date)
ls_version.append(version)
ls_name.append(name)
title = [ x.string for comps in ls_title for x in comps ]
content = [ x.string for comps in ls_content for x in comps ]
rating = [ x.string for comps in ls_rating for x in comps ]
date = [ x.string for comps in ls_date for x in comps ]
version = [ x.string for comps in ls_version for x in comps ]
name = [ x.string for comps in ls_name for x in comps ]
1
2
3
4
5
6
7
# csv 파일로 저장
import pandas as pd
df = pd.DataFrame([title, content, rating, date, version, name]).T
df.columns = ['title', 'content', 'rating', 'date', 'version', 'author']
df.to_csv(file_name)
Result
리뷰 제목, 내용, 별점, 일자, 앱 버전, 작성자를 불러올 수 있음.
Futhurmore Action
- 최근 500개 뿐만 아니라, 모든 리뷰를 수집하는 방법 연구
(참고)API를 이용해 정식으로 정보를 받으러면 Apple Developer Program에 가입해야 하는 듯 - 개발자의 답변을 스크랩 하는 방법 연구
- 구글 플레이스토어 리뷰 스크랩
- 다른 코드 연구
https://pypi.org/project/app-store-scraper/
https://python.plainenglish.io/scraping-app-store-reviews-with-python-90e4117ccdfb
Reference
- 리뷰xml 주소 : https://myinbox.tistory.com/161