iOS 업데이트 자동 확인: 웹 크롤링으로 이메일 알림 만들기
잦은 OS 업데이트로 매일매일 홈페이지에 들어가서 확인 하기가 번거로워서 웹 크롤링을 통해 이메일로 해당 업데이트 내용을 전달해주는 프로그램을 만들었다. 웹 크롤링 툴에는 크게 두가지
henniee.tistory.com
iOS 업데이트 여부를 확인하는 크롤링을 구현 했었다.
이번에는 안드로이드 를 확인 하는 크롤링을 해보려고 한다. \
[크롤링 대상 사이트 확인]
https://developer.android.com/about/versions/16/release-notes 는 공식 개발자 사이트로 각 버전별 릴리즈 노트가 정리되어 있다.
URL 링크를 살펴보면 규칙이 보인다.
- versions/16 -> 최신 버전번호가 들어감
- release-notes -> 릴리즈 노트 페이지
즉, 최신 버전 번호만 알 수 있으면 최종 릴리즈노트 링크를 만들 수 있다.
[최신 버전 번호 가져오기]
우선 vserions 까지의 주소에 접근 한 후 h3을 찾아 그 안의 img 태그의 alt 를 찾아준다.
그 후 alt의 끝부분 (숫자) 만 떼서 다시 versions/버전숫자/release-notes 라는 주소로 진입한다.

[릴리즈노트 페이지 진입]
최신 버전을 알았다면 릴리즈 노트 주소를 만들 수 있다.
하지만 이 릴리즈페이지는 앞전의 페이지와 다르게 내부의 탭들이 JavaScript 로 랜더링 되기 때문에 DOM이 모두 그려질 때까지 기다려야 한다. 그래서 이 부분에서는 Selenium을 사용하여 원하는 정보를 얻어낸다.

최종 코드
private List<AndroidVersionInfo> crawlAndroidWebsite() throws IOException {
List<AndroidVersionInfo> latestAndroidVersions = new ArrayList<>();
WebDriver driver = null;
try {
// 페이지 접속
Document doc = Jsoup.connect(Android_RELEASES_URL).get();
// h3 태그 중 img alt 속성이 "Android"로 시작하는 것 찾기
Elements h3s = doc.select("h3:has(img[alt^=Android])");
String latestVersionLink = null; // href="https://developer.android.com/about/versions/16?hl=ko"
String latestVersionNum = null; // 16
for (Element h3 : h3s) {
Element aTag = h3.selectFirst("a[href]");
if (aTag != null) {
latestVersionLink = aTag.attr("href");
Matcher m = Pattern.compile("/versions/(\\d+)").matcher(latestVersionLink);
if (m.find()) {
latestVersionNum = m.group(1); // "16"
}
break; // 첫 번째(최신)만 추출
}
}
if (latestVersionLink != null) {
String baseUrl = latestVersionLink + "/release-notes";
Document versionDoc = Jsoup.connect(baseUrl).get(); // 릴리즈노트 사이트로 들어가기
WebDriverManager.chromedriver().setup();
ChromeOptions options = new ChromeOptions();
options.addArguments("--headless=new");
options.addArguments("--disable-gpu");
// options.addArguments("--headless=new"); //창 없이 백그라운드 실행
// options.addArguments("--disable-gpu"); // GPU 가속 끄기
// options.addArguments("--no-sandbox");//샌드박스 비활성화 (서버 환경에서 필요)
// options.addArguments("--disable-dev-shm-usage"); //docker에서 크롬 크래시 방지
// options.addArguments("--window-size=1920,1080"); //창 크기 설정
driver = new ChromeDriver(options);
driver.get(baseUrl);
List<WebElement> tabs = driver.findElements(By.cssSelector("tab[role=tab] a"));
if (tabs.isEmpty()) { // 탭이 없을 경우 → 탭 정보 없이 저장
latestAndroidVersions.add(new AndroidVersionInfo(latestVersionNum, null, baseUrl));
System.out.println("탭없음");
} else {
String latestTab = null;
double maxVersion = 0.0;
for (WebElement tab : tabs) {
String text = tab.getText().trim(); // 예: "베타 4.1"
if (text.matches(".*\\d+(\\.\\d+)?")) {
double version = Double.parseDouble(text.replaceAll("[^\\d.]", ""));
if (version > maxVersion) {
maxVersion = version;
latestTab = latestVersionNum + " " + text;
}
}
}
if (latestTab != null) {
latestAndroidVersions.add(new AndroidVersionInfo(latestTab, null, baseUrl));
} else {
System.out.println("최신 업데이트 버전이 없음");
}
}
} else {
System.out.println("링크를 찾을 수 없습니다.");
}
} catch (IOException e) {
System.out.println("크롤링 오류: " + e.getMessage());
}
return latestAndroidVersions;
}'spring 스프링' 카테고리의 다른 글
| Spring Boot Gradle 프로젝트에서 SMTP 이메일 전송하기 (0) | 2025.08.28 |
|---|---|
| iOS 업데이트 자동 확인: 웹 크롤링으로 이메일 알림 만들기 (0) | 2025.08.21 |
| Spring CORS 설정: WebConfig 작성부터 wildcard '*', withCredentials 문제 해결까지 (1) | 2025.06.26 |
| Spring Data JPA 페이징 구현하기 (SpringBoot 적용) (0) | 2025.06.02 |
| The method builder() is undefined for the type 오류 (해결2) (0) | 2025.04.05 |