• ์๋ ํ์ธ์~ ์ด์ ์ ์ด์ํ๋ ๋ธ๋ก๊ทธ ๋ฐ GitHub, ๊ณต๋ถ ๋ด์ฉ์ ์ ๋ฆฌํ๋ Study-GitHub ๊ฐ ์์ต๋๋ค!
• ๐
๐ Jsoup์ ์ด์ฉํ ํฌ๋กค๋ง
์๋ ํ์ธ์! ์ด๋ฒ์ ์ ๋ฆฌํ ๋ด์ฉ์ Java์์ Jsoup์ ์ด์ฉํด ํฌ๋กค๋ง ํ๋ ๋ฐฉ๋ฒ์ ๋๋ค.
ํ์ฌ ์งํ์ค์ธ(?) ์ฌ์ด๋ ํ๋ก์ ํธ์์ ์ธํ๋ฐ ์ฌ์ดํธ์ ๊ฐ์ ๋ฐ์ดํฐ๋ค์ด ํ์ํด์ ํฌ๋กค๋ง์ ํด์ผ ํ๋๋ฐ์,
์์ ์ ํด๋ณธ Python์ผ๋ก ํฌ๋กค๋ง์ ํ ์ง, ์๋๋ฉด ์ต์ํ Java๋ก ํ ์ง ๊ณ ๋ฏผํ๋ค๊ฐ ๊ฒฐ๊ตญ์ Java๋ก ํ๊ฒ ๋์์ต๋๋ค.
์ฌ์ดํธ์ ์ ์ํ ๋ค ํ๊ทธ๋ฅผ ํตํด ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๋ ์ ์ฒด์ ์ธ ๋งฅ๋ฝ์ Python๊ณผ ๋น์ทํ๊ธฐ ๋๋ฌธ์ ํฐ ์ด๋ ค์์์ด ์งํํ ์ ์์๋๋ฐ์,
์ธํ๋ฐ ์ฌ์ดํธ์์ ํ์ํ ๋ฐ์ดํฐ๋ฅผ ๊ฐ๊ณต & ํฌ๋กค๋ง ํ๋ ๊ณผ์ ์ ์ ๋ฆฌํด๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค !
๐ ํ์ํ ๋ฐ์ดํฐ
์ ํํ์ง๋ ์์ง๋ง ํ๋ก์ ํธ์ ํ์ํ ๋ฐ์ดํฐ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
- ์ธ๋ค์ผ ๋งํฌ
- ๊ฐ์ ์ ๋ชฉ
- ๊ฐ๊ฒฉ(+ํ ์ธ ๊ฐ๊ฒฉ)
- ํ์
- ๊ฐ์์
- ๊ฐ์ ๋งํฌ
- ์๊ฐ์ ์
- ๊ฐ์ ์ธ์ ๊ฐ์
- ๊ฐ์ ๋ถ๊ฐ์ค๋ช
- ๊ฐ์ ์คํฌ & ์คํ
ํ์ํ ๋ฐ์ดํฐ๊ฐ ๊ฝค ๋ง์๋ฐ์... ๐ ์ด ๋๋ฌธ์ ๊ฝค ์ ๋จน๊ธฐ๋ ํ์ต๋๋ค... ๐๐
์ ๋ฐ์ดํฐ๋ค์ ๊ฐ์ ธ์ฌ ์ ์๋ ๋ฐฉ๋ฒ์ด ์ ๋ถ ๋์ผํ์ง๋ ์๊ธฐ ๋๋ฌธ์ ํ๋ํ๋ ํ์ธํด๊ฐ๋ฉฐ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์์ผ ํฉ๋๋ค.
ํน์ ๋ฐ์ดํฐ๋ ์๋ ์ฌ์ดํธ์์ ๋ฐ๋ก ๊ฐ์ ธ์ฌ ์ ์๋ ๋ฐ๋ฉด, ํน์ ๋ฐ์ดํฐ๋ ์ฌ์ดํธ๋ฅผ ํ๊ณ ๋ค์ด๊ฐ์ผ ๊ฐ์ ธ์ฌ ์ ์๋ ๋ฐ์ดํฐ๋ ์กด์ฌํฉ๋๋ค.
์ฝ๋๋ฅผ ํตํด ์ด๋ ํ ๋ฐฉ์์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ํฌ๋กค๋งํ๋์ง ์ดํด๋ณด๊ฒ ์ต๋๋ค.
๐ ์ฝ๋
๋จผ์ ์๋ฐ์์ ํฌ๋กค๋ง์ ํ๊ธฐ ์ํด Jsoup ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ํ์ํฉ๋๋ค.
์ ๋ Maven ๊ธฐ๋ฐ์ผ๋ก ๊ฐ๋ฐ์ ์งํํ๊ธฐ ๋๋ฌธ์ pom.xml ์ jsoup ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ถ๊ฐํฉ๋๋ค.
final String inflearnUrl = "https://www.inflearn.com/courses/it-programming
Connection conn = Jsoup.connect(inflearnUrl);
Document document = conn.get();
ํฌ๋กค๋ง์ ํ๊ธฐ ์ํด ํ์ํ URL ์ฃผ์ ๋ฐ Jsoup ๊ฐ์ฒด๋ค์ ์ ์ธํฉ๋๋ค.
๐ฏ ์ธ๋ค์ผ ๋งํฌ
์ด์ ์ธํ๋ฐ ์ฌ์ดํธ์์ ๊ฐ๋ฐ์ ๋๊ตฌ๋ฅผ ํตํด ํ์ํ ๋ฐ์ดํฐ์ ํ๊ทธ๋ฅผ ํ์ธํ ํ ๊ฐ์ ธ์๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
F12 ๋ฅผ ๋๋ฅธ ํ ์๋จ์ ๋ง์ฐ์ค ํ์๋ฅผ ํด๋ฆญํ ํ ๊ฐ์ ์ฌ์ง์ ํด๋ฆญํ๋ฉด ์ฐ์ธก๊ณผ ๊ฐ์ด ์์๋ค์ด ๋์ค๋๋ฐ์,
๊ทธ ์ค class="swiper-lazy" ์ ํ๊ทธ๋ฅผ ํตํด ์ธ๋ค์ผ ๋งํฌ๋ฅผ ๊ฐ์ ธ์ฌ ์ ์์ต๋๋ค.
โป ์์ ๊ฐ์ด class="swpier-lazy" ๋ก ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ฌ ๊ฒฝ์ฐ, ํด๋น ํ์ด์ง์ ๋ชจ๋ ์ธ๋ค์ผ ๋งํฌ๋ฅผ ์ ๋ถ ๊ฐ์ ธ์ต๋๋ค.
๊ทธ๋ผ ์ ํ๊ทธ๋ฅผ ํตํด ํ์ฌ ํ์ด์ง(www.inflearn.com/courses/it-programming) ์ ์ธ๋ค์ผ ๋งํฌ๋ฅผ ๋ชจ๋ ๊ฐ์ ธ์๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
import org.jsoup.Connection;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import java.io.IOException;
public class Crawling {
public static void main(String[] args) {
final String inflearnUrl = "https://www.inflearn.com/courses/it-programming";
Connection conn = Jsoup.connect(inflearnUrl);
try {
Document document = conn.get();
Elements imageUrlElements = document.getElementsByClass("swiper-lazy");
for (Element element : imageUrlElements) {
System.out.println(element);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
document์ getElementsByClass ๋ฉ์๋๋ฅผ ํตํด class๊ฐ "swiper-lazy" ์ธ ๋ฐ์ดํฐ๋ฅผ ๋ชจ๋ ๊ฐ์ ธ์ค๋ ์ฝ๋์ ๋๋ค.
๋ณต์์ ๋ฐ์ดํฐ์ด๊ธฐ ๋๋ฌธ์ Elements(๋ณต์ํ) ์์๋ก ๊ฐ์ ธ์จ ๋ค, ๊ฐ ์์์ ์ ๊ทผํ๊ธฐ ์ํด for๋ฌธ์ ๋ฐ๋ณตํ๋ฉฐ ์ถ๋ ฅํฉ๋๋ค.
์ ๋ญ๊ฐ ๋ชจ๋ ๊ฐ์ ธ์ค๊ธด ํ ๊ฒ ๊ฐ์๋ฐ.. ๋ถํ์ํ ์์๊ฐ ์ ๋ง ๋ง๋ค์~
๊ฐ์ฅ ์์ src ๋งํฌ๋ฅผ ํด๋ฆญํ๋ฉด ์์ ๊ฐ์ด ์ธ๋ค์ผ ๋งํฌ๊ฐ ์ถ๋ ฅ์ด ๋๋๋ฐ์, ํ์ง๋ง ์ ํฌ๊ฐ ํ์ํ๊ฑด ์์ ๊ฐ์ ์ ์ฒด html ํ๊ทธ๊ฐ ์๋
์ธ๋ค์ผ ๋งํฌ ๋ง ํ์ํฉ๋๋ค.
๋ฐ๋ผ์ ํด๋น ํ๊ทธ๋ฅผ ๊ฐ๊ณตํด์ค ํ์๊ฐ ์์ต๋๋ค.
for (Element element : imageUrlElements) {
System.out.println(element.attr("abs:src");
}
์์ ๊ฐ์ด element์ attr๋ฉ์๋๋ฅผ ํตํด ํ์ํ ๋ถ๋ถ(src:) ๋ง ๊ฐ์ ธ์ฌ ์ ์์ต๋๋ค.
์์ ๊ฐ์ด for๋ฌธ์ ์์ ํ๊ณ ๋ค์ ์ถ๋ ฅํด๋ณด๋ฉด ํ์ํ ๋ถ๋ถ๋ง ๊ฐ์ ธ์ฌ ์ ์์ต๋๋ค.
์ ์ด์ ํ์ํ ๋ฐ์ดํฐ ์ค ํ๋ ๊ฐ์ ธ์๋ค์.. ใ ใ
๊ฐ๊ธธ์ด ๋ฉ๊ธฐ ๋๋ฌธ์ ๋ค๋ฅธ ๋ฐ์ดํฐ๋ค๋ ๋น ๋ฅด๊ฒ ๊ฐ์ ธ์๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค !
๐ฏ ๊ฐ์ ์ ๋ชฉ
๊ฐ์๋ ์ธ๋ค์ผ๊ณผ ๋น์ทํ๋ฐ์, ๊ฐ์๋ฅผ ์ฐ์ด๋ณด๋ฉด ๋ค์๊ณผ ๊ฐ์ด 2๊ฐ์ class๋ก ๋ฌถ์ฌ์์ต๋๋ค.
<div class="card-content">
<div class="course_title">
์ ํ๊ทธ๋ "card-content" > "course_title" ์ ๊ฐ์ด ํ์๋ก ๋ฌถ์ฌ์๋ ํํ์ธ๋ฐ์, ์ด ๋ฐ์ดํฐ๋ ๊ฐ์์๋ ์กฐ๊ธ ๋ค๋ฅด๊ฒ select ๋ฉ์๋๋ฅผ ํตํด ๊ฐ์ ธ์๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
(์ ๊ทธ๋ ๊ฒ ๊ฐ์ ธ์๋์ง๋ ์ ๋ ์ ๋ชฐ๋ผ์ ใ
ใ
์๋ง ๋ค๋ฅธ ๋ฐฉ๋ฒ์ด ์๋์ด์ ์ ๋ ๊ฒ ๊ฐ์ ธ์๋ ๊ฒ ๊ฐ์ต๋๋ค __ )
์ฝ๋์ ์ ๋ถ๋ถ๊ณผ ์๋ซ ๋ถ๋ถ์ ์ธ๋ค์ผ ์ฝ๋์ ๋์ผํ๊ธฐ ๋๋ฌธ์ ์๋ตํ๊ฒ ์ต๋๋ค :)
Elements titleElements = document.select("div.card-content > div.course_title");
for (int j = 0; j < titleElements.size(); j++) {
final String title = titleElements.get(j).text();
System.out.println("๊ฐ์ ์ ๋ชฉ: " + title);
}
์์ ๊ฐ์ด document ์ select ๋ฉ์๋๋ฅผ ํตํด div.card-content ํ์(>) ์ div.course_title ๋ฅผ ๊ฐ์ ธ์ต๋๋ค.
๐์ข์ต๋๋ค. ํ์ฌ ์ฌ์ดํธ์ ์กด์ฌํ๋ ๊ฐ์ ์ ๋ชฉ๋ค์ ๋ชจ๋ ๊ฐ์ ธ์์ต๋๋ค.๐
๐ฏ ๊ฐ๊ฒฉ + ํ ์ธ ๊ฐ๊ฒฉ
์ธํ๋ฐ ์ฌ์ดํธ์์ ๊ฐ๊ฒฉ์ ๊ฒฝ์ฐ ์ผ๋ฐ ๊ฐ๊ฒฉ๊ณผ ํ ์ธ ๊ฐ๊ฒฉ ๋ ๊ฐ์ง์ ์ ํ์ด ์กด์ฌํ๋๋ฐ์, ์ฌ๊ธฐ์๋ ํธ๋ฆญ์ด ์กด์ฌํ๋ ์ ์ํด์ผ ํฉ๋๋ค.
๋จผ์ ์์ ๊ฐ์ด ํ ์ธ ๊ฐ๊ฒฉ์ด ์๋ ๊ฒฝ์ฐ๊ฐ ์กด์ฌํฉ๋๋ค.
๋ํ ๊ฐ๊ฒฉ์ด ์กด์ฌํ์ง ์๋ ๋ฌด๋ฃ ๋ผ๋ ๊ธ์จ๋ ์กด์ฌํฉ๋๋ค.
์ฆ, ๊ฐ๊ฒฉ์ ๊ฒฝ์ฐ ๋ค์๊ณผ ๊ฐ์ ์ธ ๊ฐ์ง์ ์ผ์ด์ค๊ฐ ์กด์ฌํฉ๋๋ค.
- ์ผ๋ฐ ๊ฐ๊ฒฉ๋ง ์กด์ฌํ๋ ๊ฒฝ์ฐ
- ์ผ๋ฐ ๊ฐ๊ฒฉ, ํ ์ธ ๊ฐ๊ฒฉ ๋ชจ๋ ์กด์ฌํ๋ ๊ฒฝ์ฐ
- ๊ฐ๊ฒฉ์ด ์๋ ๊ฒฝ์ฐ(๋ฌด๋ฃ)
๋ฐ๋ผ์ ์์ ๋ฐ์ดํฐ์ ์ ์ํด์ ํฌ๋กค๋ง์ ํด์ผํฉ๋๋ค.
(์ ๋ ๊ฐ๊ฒฉ์ด ์๋ ๊ฒฝ์ฐ๋ 0 ์ผ๋ก ํ์ํ๊ธฐ๋ก ์ฝ์์ ํ์ต๋๋ค.)
๊ฐ๊ฒฉ์ ๊ฐ์ ธ์ค๋ class์ ํ๊ทธ๋ "price" ์ ๋๋ค.
๋จผ์ ๊ฐ๊ฒฉ, ํ ์ธ ๊ฐ๊ฒฉ์ ๊ฐ์ ธ์ค๋ ์ ์ฒด ์ฝ๋๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
public static void main(String[] args) {
final String inflearnUrl = "https://www.inflearn.com/courses/it-programming";
Connection conn = Jsoup.connect(inflearnUrl);
try {
Document document = conn.get();
Elements priceElements = document.getElementsByClass("price");
for (int j = 0; j < priceElements.size(); j++) {
final String price = priceElements.get(j).text();
final String realPrice = getRealPrice(price);
final String salePrice = getSalePrice(price);
final int realIntPrice = toInt(removeNotNumeric(realPrice));
final int saleIntPrice = toInt(removeNotNumeric(salePrice));
System.out.println("๊ฐ๊ฒฉ: " + realIntPrice);
System.out.println("ํ ์ธ ๊ฐ๊ฒฉ: " + saleIntPrice);
}
} catch (IOException e) {
e.printStackTrace();
}
}
private static String getRealPrice(final String price) {
final String[] pricesArray = price.split(" ");
return pricesArray[0];
}
private static String getSalePrice(final String price) {
final String[] pricesArray = price.split(" ");
return (pricesArray.length == 1) ? price : pricesArray[1];
}
private static String removeNotNumeric(final String str) {
return str.replaceAll("\\W", "");
}
private static int toInt(final String str) {
return Integer.parseInt(str);
}
final String price = priceElements.get(j).text(); ์ ์ฝ๋๋ฅผ ํตํด ๊ฐ๊ฒฉ์ ๊ฐ์ ธ์ค๊ฒ ๋ฉ๋๋ค.
๋ง์ฝ ํ ์ธ ๊ฐ๊ฒฉ์ด ์กด์ฌํ๋ฉด, ๊ณต๋ฐฑ์ ๊ธฐ์ค์ผ๋ก ๋ ๊ฐ์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๊ณ , ๊ทธ๋ ์ง ์๋ค๋ฉด ํ ๊ฐ์ ๋ฐ์ดํฐ๋ง ๊ฐ์ ธ์ต๋๋ค.
๋ฐ๋ผ์ getRealPrice() ๋ฉ์๋์ getSalePrice() ๋ฉ์๋๋ฅผ ํตํด ์ผ๋ฐ ๊ฐ๊ฒฉ / ํ ์ธ ๊ฐ๊ฒฉ์ ๊ฐ์ ธ์ค๊ณ ,
removeNotNumeric() ๋ฉ์๋๋ฅผ ํตํด ์ซ์๊ฐ ์๋ ๋ฐ์ดํฐ๋ ์ ๊ฑฐํฉ๋๋ค.
์ ์ฝ๋๋ฅผ ์ถ๋ ฅํ๋ฉด ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
๐ฏ ๊ฐ์ ๋งํฌ
๋ค๋ฅธ ๋ฐ์ดํฐ๋ณด๋ค ๊ฐ์ ๋งํฌ์ ๋ฐ์ดํฐ๋ฅผ ๋จผ์ ๊ฐ์ ธ์์ผ ๊ฐ์ ๋งํฌ์์ ๋ฐ์ดํฐ๋ฅผ ์ป์ ์ ์์ต๋๋ค.
๋ฐ๋ผ์ ๊ฐ์ ๋งํฌ ๋ฐ์ดํฐ๋ฅผ ๋จผ์ ํฌ๋กค๋ง ํด๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
๊ฐ์ ๋งํฌ๋ aํ๊ทธ์ course_card_front ๊ฐ์ผ๋ก ๊ฐ์ ธ์ฌ ์ ์์ต๋๋ค.
Elements linkElements = document.select("a.course_card_front");
for (int j = 0; j < linkElements.size(); j++) {
final String url = linkElements.get(j).attr("abs:href");
}
๊ฐ์ ๋งํฌ ๋ํ ์ธ๋ค์ผ ๋งํฌ์ ๋น์ทํ๊ฒ html ํ๊ทธ๊ฐ ์ ๋ถ ํฌํจ๋์ด ์์ต๋๋ค.
๋ฐ๋ผ์ attr("abs:href") ๋ฅผ ํตํด ํ์ํ ๋ฐ์ดํฐ๋ง ๋ฝ์์ค๋๋ก ํฉ๋๋ค.
์ถ๋ ฅํด๋ณด๋ฉด ์์ ๊ฐ์ด ์ ์์ ์ผ๋ก ๋งํฌ ๋ฐ์ดํฐ๋ฅผ ๋ฝ์์ฌ ์ ์์ต๋๋ค.
๐ฏ ํ์
๋ค์์ผ๋ก ํ์ ์ ๋๋ค.
ํ์ ์ ํด๋น ๊ฐ์๋ฅผ ๋ค์ด๊ฐ์ผ ํ์ธํ ์ ์์ต๋๋ค.
๋ฐ๋ผ์ ํฌ๋กค๋ง์ ํ๋ฉฐ ์ธํ๋ฐ ์ฌ์ดํธ๋ฅผ ๋ฐฉ๋ฌธํ ๋, ํ ๋ฒ ๋ ๋ด๋ถ๋ก ๋ค์ด๊ฐ์ผ ํฉ๋๋ค.
์์์ ๋ฝ์ ๊ฐ์ ๋งํฌ ๋ฐ์ดํฐ๋ฅผ ํตํด ๊ฐ์ ๋ด๋ถ๋ก ๋ค์ด๊ฐ๋๋ค.
/* ๊ฐ์ ๋งํฌ ๋ด๋ถ */
Connection innerConn = Jsoup.connect(url);
Document innerDocument = innerConn.get();
์์ ๊ฐ์ด ๊ฐ์๋ฅผ ํด๋ฆญํด์ ๋ค์ด๊ฐ๋ฉด <div class="dashboard-star__num"> ์ ํ๊ทธ๋ก ํ์ ์ ๊ฐ์ ธ์ฌ ์ ์์ต๋๋ค.
ํ์ ์ ๊ฐ์ ธ์ค๋ ์ฝ๋๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
/* ํ์ */
Element ratingElement = innerDocument.selectFirst("div.dashboard-star__num");
final float rating = Objects.isNull(ratingElement)
? toFloat("0")
: toFloat(ratingElement.text());
System.out.println("ํ์ : " + rating);
private static float toFloat(final String str) {
return Float.parseFloat(str);
}
ํ์ ๋ํ ์ฝ๊ฐ์ ํธ๋ฆญ์ด ์กด์ฌํ๋๋ฐ์, ๋ชจ๋ ๊ฐ์๊ฐ ์์ ๊ฐ์ด ํ์ ์ด ์กด์ฌํ์ง๋ ์์ต๋๋ค.
๋ฐ๋ผ์ ํ์ ์ด ์๋ ๋ฐ์ดํฐ์ ๊ฒฝ์ฐ NullPointerException ์์ธ๊ฐ ๋ฐ์ํ๊ธฐ ๋๋ฌธ์, Objects.isNull() ๋ฉ์๋๋ฅผ ํตํด ํํฐ๋ง์ ์งํํฉ๋๋ค.
์ถ๋ ฅํด๋ณด๋ฉด ํ์ ์ด ์๋ ๊ฒฝ์ฐ 0.0 ์ผ๋ก ์ถ๋ ฅ์ด ๋๊ณ , ๊ทธ ์ธ์ ๋ฐ์ดํฐ๋ ๋ชจ๋ ํ์ ์ด ์ถ๋ ฅ๋ฉ๋๋ค.
๐ฏ ๊ฐ์์, ๊ฐ์ ๋ถ๊ฐ์ค๋ช , ๊ธฐ์ ์คํ
๊ฐ์์, ๋ถ๊ฐ์ค๋ช , ๊ธฐ์ ์คํ์ ๋ชจ๋ ์ธํ๋ฐ ์ฒซ ์ฌ์ดํธ์์ ๋ฐ์ดํฐ๋ฅผ ๋ฝ์๋ผ ์ ์์ผ๋ฏ๋ก ๊ฐ์ด ์ ๋ฆฌ๋ฅผ ์งํํ๊ฒ ์ต๋๋ค.
๊ฐ์์, ๋ถ๊ฐ์ค๋ช ์ ๊ธฐ์กด๊ณผ ๋์ผํ๊ฒ ํ๊ทธ๋ฅผ ํฌ๋กค๋งํ๋ฉด ๋๋ฏ๋ก ๋์ด๊ฐ๊ณ ๊ธฐ์ ์คํ์ ํ๊ทธ๋ง ๊ฐ๋จํ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
๊ธฐ์ ์คํ์ div ํ๊ทธ์ course_skills > span ํ๊ทธ์ ์กด์ฌํฉ๋๋ค.
์ฝ๋๋ฅผ ๋ณด๋ฉด ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
public static void main(String[] args) {
final String inflearnUrl = "https://www.inflearn.com/courses/it-programming";
Connection conn = Jsoup.connect(inflearnUrl);
try {
Document document = conn.get();
Elements instructorElements = document.getElementsByClass("instructor");
Elements descriptionElements = document.select("p.course_description");
Elements skillElements = document.select("div.course_skills > span");
for (int j = 0; j < instructorElements.size(); j++) {
final String instructor = instructorElements.get(j).text();
final String description = descriptionElements.get(j).text();
final String skills = removeWhiteSpace(skillElements.get(j).text());
System.out.println("๊ฐ์์: " + instructor);
System.out.println("๊ฐ์ ๋ถ๊ฐ์ค๋ช
: " + description);
System.out.println("๊ธฐ์ ์คํ: " + skills);
}
} catch (IOException e) {
e.printStackTrace();
}
}
private static String removeWhiteSpace(final String str) {
return str.replaceAll("\\s", "");
}
๐ฏ ์ ์ฒด ์ฝ๋
์๊ฐ์ ์, ๊ฐ์ ์ธ์ ๊ฐ์ ๋ฑ์ ๋ฐ์ดํฐ๋ ์์ ๊ฐ์ ๋ฐฉ๋ฒ์ผ๋ก ์งํํ๋ฉด ๋๋ฏ๋ก ์๋ตํ๊ณ ์ ์ฒด ์ฝ๋์ ๋ํ๋ด๋ณด๊ฒ ์ต๋๋ค!
package com.github.oneline.onelinecourse.util;
import org.jsoup.Connection;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.safety.Whitelist;
import org.jsoup.select.Elements;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Objects;
public class InflearnCrawling {
private static final Logger log = LoggerFactory.getLogger(InflearnCrawling.class);
private static final int FIRST_PAGE_INDEX = 1;
private static final int LAST_PAGE_INDEX = 32;
private static final String PLATFORM = "Inflearn";
public static void main(String[] args) {
try {
// ๊ฐ๋ฐ ๊ฐ์ ๋ชจ๋ ํ์ด์ง ์ํ
for (int i = FIRST_PAGE_INDEX; i <= LAST_PAGE_INDEX; i++) {
final String inflearnUrl = "https://www.inflearn.com/courses/it-programming?order=seq&page=" + i;
Connection conn = Jsoup.connect(inflearnUrl);
Document document = conn.get();
// ํฌ๋กค๋ง ํญ๋ชฉ ํ์ ๋ฆฌ์คํธ
// - ์ธ๋ค์ผ ๋งํฌ, ๊ฐ์ ์ ๋ชฉ, ๊ฐ๊ฒฉ(ํ ์ธ๊ฐ๊ฒฉ), ํ์ , ๊ฐ์์, ๊ฐ์ ๋งํฌ, ์๊ฐ์ ์, ํ๋ซํผ, ๊ฐ์ ์ธ์
๊ฐ์ + ์๊ฐ
Elements imageUrlElements = document.getElementsByClass("swiper-lazy");
Elements titleElements = document.select("div.card-content > div.course_title");
Elements priceElements = document.getElementsByClass("price");
Elements instructorElements = document.getElementsByClass("instructor");
Elements linkElements = document.select("a.course_card_front");
Elements descriptionElements = document.select("p.course_description");
Elements skillElements = document.select("div.course_skills > span");
String[] imageUrls = new String[imageUrlElements.size()];
int setIndex = 0;
int getIndex = 0;
for (Element e : imageUrlElements) {
imageUrls[setIndex++] = e.attr("abs:src");
}
for (int j = 0; j < titleElements.size(); j++) {
final String title = titleElements.get(j).text();
final String price = priceElements.get(j).text();
final String realPrice = getRealPrice(price);
final String salePrice = getSalePrice(price);
final int realIntPrice = toInt(removeNotNumeric(realPrice));
final int saleIntPrice = toInt(removeNotNumeric(salePrice));
final String currency = String.valueOf(price.charAt(0));
final String instructor = instructorElements.get(j).text();
final String url = linkElements.get(j).attr("abs:href");
final String description = descriptionElements.get(j).text();
final String skills = removeWhiteSpace(skillElements.get(j).text());
System.out.println("์ธ๋ค์ผ: " + imageUrls[j]);
System.out.println("๊ฐ์ ์ ๋ชฉ: " + title);
System.out.println("๊ฐ๊ฒฉ: " + realIntPrice);
System.out.println("ํ ์ธ ๊ฐ๊ฒฉ: " + saleIntPrice);
System.out.println("์ํ: " + currency);
System.out.println("๊ฐ์์: " + instructor);
System.out.println("๊ฐ์ ๋งํฌ: " + url);
System.out.println("๊ฐ์ ์ค๋ช
: " + description);
System.out.println("๊ธฐ์ ์คํ: " + skills);
/* ๊ฐ์ ๋งํฌ ๋ด๋ถ */
Connection innerConn = Jsoup.connect(url);
Document innerDocument = innerConn.get();
/* ํ์ */
Element ratingElement = innerDocument.selectFirst("div.dashboard-star__num");
final float rating = Objects.isNull(ratingElement)
? toFloat("0")
: toFloat(ratingElement.text());
System.out.println("ํ์ : " + rating);
/* ์๊ฐ์ ์ */
Element listenerElement = innerDocument.selectFirst("div.cd-header__info-cover");
final String listener = Objects.isNull(listenerElement)
? innerDocument.selectFirst("span > strong").text()
: innerDocument.select("div.cd-header__info-cover > span > strong").get(1).text();
System.out.println("์๊ฐ์ ์: " + removeNotNumeric(listener));
final int viewCount = Integer.parseInt(removeNotNumeric(listener));
/* ๊ฐ์ ์ธ์
๊ฐ์ */
final String course = innerDocument.selectFirst("span.cd-curriculum__sub-title").text();
System.out.println("๊ฐ์ ์ธ์
๊ฐ์: " + getSessionCount(course));
final int sessionCount = Integer.parseInt(getSessionCount(course));
System.out.println();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
private static String getRealPrice(final String price) {
final String[] pricesArray = price.split(" ");
return pricesArray[0];
}
private static String getSalePrice(final String price) {
final String[] pricesArray = price.split(" ");
return (pricesArray.length == 1) ? price : pricesArray[1];
}
// html ํ๊ทธ ์ ๊ฑฐ
private static String stripHtml(final String html) {
return Jsoup.clean(html, Whitelist.none());
}
// ๋งจ ์, ๋งจ ๋ค ์๊ดํธ ์ ๊ฑฐ
private static String removeBracket(final String str) {
return str.replaceAll("^[(]|[)]$", "");
}
private static String getSessionCount(final String course) {
return removeNotNumeric(course.substring(0, course.indexOf("๊ฐ")));
}
private static String removeNotNumeric(final String str) {
return str.replaceAll("\\W", "");
}
private static String removeWhiteSpace(final String str) {
return str.replaceAll("\\s", "");
}
private static int toInt(final String str) {
return Integer.parseInt(str);
}
private static float toFloat(final String str) {
return Float.parseFloat(str);
}
}
final String inflearnUrl = "https://www.inflearn.com/courses/it-programming?order=seq&page=" + i;
์ ์ฝ๋์์ url์ ๋ค์๊ณผ ๊ฐ์ด ๋์ด์๋๋ฐ์, ์ด๋ ์ธํ๋ฐ ์ฌ์ดํธ์์ ์ ์ฒด ๊ฐ์๋ฅผ ํฌ๋กค๋ง ํด์ผ ํ๊ธฐ ๋๋ฌธ์ ์ ์ฒด ํ์ด์ง๋ฅผ ์ํํ๋๋ก ์ค์ ํ์ต๋๋ค.
/* ์๊ฐ์ ์ */
Element listenerElement = innerDocument.selectFirst("div.cd-header__info-cover");
final String listener = Objects.isNull(listenerElement)
? innerDocument.selectFirst("span > strong").text()
: innerDocument.select("div.cd-header__info-cover > span > strong").get(1).text();
System.out.println("์๊ฐ์ ์: " + removeNotNumeric(listener));
final int viewCount = Integer.parseInt(removeNotNumeric(listener));
์๊ฐ์ ์ ๋ํ ๋ฐ์ดํฐ๊ฐ ์กด์ฌํ์ง ์๊ฑฐ๋, ๋์ผํ ํ๊ทธ๊ฐ ์ค๋ณต๋์ด ์๊ฑฐ๋ ๋ฑ์ ํธ๋ฆญ์ด ์กด์ฌํด์ ์กฐ๊ฑด ์ฒ๋ฆฌ๋ฅผ ํด์ฃผ์์ต๋๋ค.
for (Element e : imageUrlElements) {
imageUrls[setIndex++] = e.attr("abs:src");
}
๋ํ ์ธ๋ค์ผ ๋งํฌ์ ๊ฒฝ์ฐ, ๋ค๋ฅธ ๋ฐ์ดํฐ์๋ ๋ค๋ฅด๊ฒ ํฌ๋กค๋ง ํ ๋ ์ด์๊ฐ ์์๊ธฐ ๋๋ฌธ์, ๋ฐ๋ก ๋ฐ์ดํฐ๋ฅผ ์ถ๊ฐํด์ฃผ์์ต๋๋ค.
'Java' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Java] - ๊น์ ๋ณต์ฌ(Deep Copy) vs ์์ ๋ณต์ฌ(Shallow Copy) (1) | 2021.07.30 |
---|---|
[Java] - Project Lombok(๋กฌ๋ณต) (0) | 2021.06.20 |
[Java] - ์์ธ(Exception), ์์ธ ์ฒ๋ฆฌ(Exception Handling) (2) | 2021.05.08 |
[Java] - ์๋ฐ ์ ๊ท ํํ์(Regular Expression) + 2021 ์นด์นด์ค ์ฝํ (์ ๊ท ์์ด๋ ์ถ์ฒ) (0) | 2021.03.28 |
[Java] - @FunctionalInterface ํจ์ํ ์ธํฐํ์ด์ค (0) | 2021.02.11 |
๋๊ธ