์ผ | ์ | ํ | ์ | ๋ชฉ | ๊ธ | ํ |
---|---|---|---|---|---|---|
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 |
- KDT_TIL
- AQE
- Salting
- Kafka
- disk spill
- spark executor memory
- Spark Caching
- Airflow
- backfill
- colab
- mysql
- off heap memory
- CI/CD
- etl
- Spark Partitioning
- Spark SQL
- ๋ฐ์ดํฐ ํ์ดํ๋ผ์ธ
- Spark
- k8s
- aws
- Dag
- topic
- Speculative Execution
- ๋น ๋ฐ์ดํฐ
- Kubernetes
- Spark ์ค์ต
- DataFrame Hint
- redshift
- SQL
- Docker
- Today
- Total
JUST DO IT!
[TIL]KDT_20230419 ๋ณธ๋ฌธ
๐ KDT WEEK 3 DAY 3 TIL
- BeautifulSoup ํ์ฉํ HTML parsing
- ์ํ๋ ์์ ๊ฐ์ ธ์ค๊ธฐ
- ํ์ด์ง๋ค์ด์ (Pagination)
- ๋์ ์น ํ์ด์ง
๐ฅ BeautifulSoup4
HTML์์ ์ํ๋ ์์๋ฅผ ์ถ์ถํ๊ธฐ ์ํด ์ฌ์ฉํ HTML Parser
- soup = BeautifulSoup(res.text, "html.parser")
- requests๋ก ๊ฐ์ ธ์จ res์ text๋ฅผ ํ์ฑํ๋ค
- html์ ํ์ฑํ ๊ฒ์์ผ๋ก ๋ค์ ์ธ์์ "html.parser"๋ฅผ ์ ์ธํ๋ค.
- h1 = soup.find("h1")
- soup์์ ํน์ ํ๊ทธ ์์๋ฅผ ์ฐพ์ ์ ์๋ค.
- ์ด๋, ํ๊ทธ๊ฐ ๊ฐ์ ์ด๋ฆ์ ํ๊ทธ๊ฐ ์ฌ๋ฌ๊ฐ๋ผ๋ฉด ๊ฐ์ฅ ์ฒซ ๋ฒ์งธ๊ฒ์ ๊ฐ์ ธ์จ๋ค.
- ๋ชจ๋ ๊ฐ์ ์ด๋ฆ์ ํ๊ทธ๊ฐ ํ์ํ๋ค๋ฉด find_all("h1")์ ์ฌ์ฉํ์.
- h1.name, h1.text์ ํํ๋ก ํ๊ทธ์ ์ด๋ฆ์ด๋ ๋ด์ฉ์ ๊ฐ์ ธ์ฌ ์๋ ์๋ค
์ด๊ฑด ์ฌ์ฉ์์!
์ฌ๋ฌ๊ฐ์ง ์์๋ฅผ ๋ฃ์ด๋ดค๋ค.
์ค์ ์ฌ์ดํธ์์ ์ํ๋ ์์ ๊ฐ์ ธ์ค๊ธฐ
ํ์ฉํ ์ฌ์ดํธ : http://books.toscrape.com/catalogue/category/books/travel_2/index.html
๋จผ์ , ์ฌ์ดํธ์์ ํ์ํ ์ ๋ณด์ ์์น๋ฅผ ํฌ๋กฌ์ ๊ฐ๋ฐ์ ๋๊ตฌ๋ฅผ ํตํด ์์๋ธ๋ค.
- ํด๋น ์์์ ๋ง์ฐ์ค ์ค๋ฅธ์ชฝ ํด๋ฆญ โก ๊ฒ์ฌ ๋ฒํผ
- ์ง์ F12 ๋จ์ถํค๋ก ๊ฐ๋ฐ์ ๋๊ตฌ๋ฅผ ๋ถ๋ฌ์ ์ฐพ์๋ณด๊ธฐ
๋ค์์ผ๋ก BeautifulSoup๋ฅผ ํตํด ํ์ฑ
import requests
from bs4 import BeautifulSoup
# requests์ BeautifulSoup๋ฅผ ์ฌ์ฉํ์ฌ ํด๋น ์ฌ์ดํธ๋ฅผ html ํ์ฑ
res = requests.get("http://books.toscrape.com/catalogue/category/books/travel_2/index.html")
soup = BeautifulSoup(res.text, "html.parser")
# ์ฌ์ดํธ์์ h3 ํ๊ทธ์์ ์ ๋ชฉ์ด ์์์ ํ์ธํ์ผ๋ฏ๋ก h3 ์์๋ฅผ ์ฐพ์ ์ ์ฅํ๋ค.
h3_result = soup.find_all("h3")
# h3 > a ํ๊ทธ ์์ title ์์ฑ์ ์ ๋ชฉ์ด ์์ผ๋ฏ๋ก ๋ค์๊ณผ ๊ฐ์ด ์ ์ฅํ๊ณ ์ถ๋ ฅ
book_list = [x.a["title"] for x in h3_result]
print(book_list)
HTML์ Locator ํ์ฉํ๊ธฐ
- ํ๊ทธ์ ์ด๋ฆ์ผ๋ก ํ์ํ ๋ถ๋ถ์ ์ฐพ๋ ๊ฒ์ ์ข์ง ์์ ๋ฐฉ๋ฒ์ด๋ค.
- ๊ฐ์ ์ด๋ฆ์ ํ๊ทธ๊ฐ ์กด์ฌํ ๊ฐ๋ฅ์ฑ์ด ์์ฃผ ๋ค๋ถํ๊ธฐ ๋๋ฌธ!
- ๋ฐ๋ผ์ ํ๊ทธ๋ง๋ค ๊ฐ์ง ๊ณ ์ ์ id๋ class ์์ฑ์ ํตํด ์ฐพ๋ ๋ฐฉ๋ฒ์ด ์ข๋ค.
- BeautifulSoup์ find ๋ฉ์๋๋ฅผ ํ์ฉํ๋ฉด id์ class๋ฅผ ์ง์ ํด์ ์ฐพ์ ์๋ ์๋ค.
๋จผ์ , ์๊น์ฒ๋ผ ๋ด๊ฐ ์ฐพ์ผ๋ ค๋ ๊ฐ(์ฑ ์ ๊ฐ๊ฒฉ)์ ์์น๋ฅผ ์์๋ธ๋ค. (์๊น์ ๊ฐ์ ์ฌ์ดํธ)
๋ฐ๋ก ์ฝ๋๋ก ํ์ฑํด๋ณธ๋ค!
#์ฌ์ดํธ์์ html ํ์ฑ
import requests
from bs4 import BeautifulSoup
res = requests.get("http://books.toscrape.com/catalogue/category/books_1/index.html")
soup = BeautifulSoup(res.text, "html.parser")
#class๋ก ์ฐพ๋ ๊ฒฝ์ฐ ์ฐพ๋ ํ๊ทธ์ ์ด๋ฆ ๋ค ์ธ์์ class ์ด๋ฆ์ ๊ฐ์ด ์ ์ด์ค๋ค.
find_result = soup.find("div","product_price")
#id์ ๊ฒฝ์ฐ
#find_result = soup.find("ํ๊ทธ์ด๋ฆ", id = "id์ด๋ฆ")
#๋ด๊ฐ ์ฐพ๊ณ ์ ํ๋ ๊ฐ์ ์ถ๋ ฅํ๋ฉด ๋!
print(find_result.p.text)
ํ์ด์ง๋ค์ด์ (Pagination)
์ฌ์ฉ๋ ์ฌ์ดํธ : https://hashcode.co.kr/
ํญ์ ํ๋ ๊ฒ์ฒ๋ผ.. ๊ฐ์ฅ ๋จผ์ ์คํฌ๋ํํ ๋ด์ฉ์ ์ฐพ์๋ณธ๋ค!
์ด๋ฒ์, user_agent๋ฅผ dic ํํ๋ก ๋ฃ์ด ์์ฒญํ ๋ ๊ฐ์ด ์ ์กํด์ฃผ์๋ค.
import requests
from bs4 import BeautifulSoup
user_agent = {"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36"}
res = requests.get("https://hashcode.co.kr/", user_agent)
soup = BeautifulSoup(res.text, "html.parser")
# class๊ฐ 'question-list-item'์ ํด๋นํ๋ li ํ๊ทธ๋ฅผ ๋ชจ๋ ๊ธ์ด์๋ค
qList = soup.find_all("li", "question-list-item")
# ์ํ๋ ๋ด์ฉ(title)๋ง ์ ๋นผ์ ๋ฆฌ์คํธ ํํ๋ก ์ ์ฅํ๋ค
qTitleList = [x.find("div","question").find("div","top").h4.text for x in qList]
qTitleList
๋ ๋ง์ ๊ฒฐ๊ณผ, ๋ ๋ง์ ํ์ด์ง์์ ํ์์ ํ๋ ค๋ฉด ์ด๋ป๊ฒ ํด์ผํ ๊น?
โถ ํ์ด์ง๋ค์ด์ ์ ์ด์ฉํ๋ฉด ๋๋ค. (for ๋ฌธ)
์ฐ์ ์ฌ์ดํธ๊ฐ Query String์ ํตํด ํ์ด์ง๋ฅผ ๊ตฌ๋ถํ๋ค๋ ์ฌ์ค์ ๊ฐ์ํ๊ณ ์ฝ๋๋ฅผ ์์ฑํ๋ค.
Query String โก https://hashcode.co.kr/?page={i} # i์ ๊ฐ์ ๋ฐ๋ผ ํด๋น ํ์ด์ง๋ก ์ด๋ํ๋ค.
#์์ชฝ ์ฝ๋์ ์ด์ด์ง๋ค
import time
# 1~5ํ์ด์ง ํ์
for i in range(1,6):
res = requests.get("https://hashcode.co.kr/?page={}".format(i), user_agent)
soup = BeautifulSoup(res.text, "html.parser")
questionList = soup.find_all("li", "question-list-item")
qTitleList = [x.find("div","question").find("div","top").h4.text for x in questionList]
print(qTitleList)
#๊ณผ๋ํ ์์ฒญ์ ๋ฐฉ์งํ๊ธฐ ์ํด 0.5์ด ๊ฐ๊ฒฉ์ ๋์๋ค
time.sleep(0.5)
๐ฆ ๋์ ์น ํ์ด์ง
์ ์ (static) ์น ์ฌ์ดํธ : HTML ๋ด์ฉ์ด ๊ณ ์ ๋ ํํ
- ๊ฐ์ ์ฃผ์๋ก ์์ฒญ์ ๋ณด๋ด๋ฉด ๊ฐ์ ์๋ต์ ๋ฐ์ ์ ์์
- HTML ๋ฌธ์๊ฐ ์์ ํ๊ฒ ์๋ต๋จ
๋์ ์น ์ฌ์ดํธ : HTML ๋ด์ฉ์ด ๋ณํ๋ ํํ
- ์๋ก๊ณ ์นจ์ ํ ๋๋ง๋ค ๋ณด์ด๋ ๋ด์ฉ์ด ๋ฌ๋ผ์ง๋ ํํ
- ์๋ต ํ HTML์ด ๋ ๋๋ง์ด ๋ ๋๊น์ง์ ์ง์ฐ์๊ฐ์ด ์กด์ฌ
- ๋น๋๊ธฐ ์ฒ๋ฆฌ๋ฅผ ํ๋ฏ๋ก, ์๋ต์ ๋ฐ์์ ๋, ์ํฉ์ ๋ฐ๋ผ ๋ฐ์ดํฐ๊ฐ ์์ ํ์ง ์์ ์๋ ์์
๋์ ์น ์ฌ์ดํธ๋ ์๋ฐ์คํฌ๋ฆฝํธ ์ธ์ด๋ฅผ ์ฌ์ฉํ์ฌ ๋น๋๊ธฐ ์ฒ๋ฆฌ ๋ฐฉ์์ ์ฌ์ฉํ๋ฏ๋ก,
์ฐ๋ฆฌ๊ฐ ์๋ต๋ฐ๋ ์๊ฐ์ด ๋ฐ์ดํฐ ์ฒ๋ฆฌ๊ฐ ๋ชจ๋ ์๋ฃ๋ ์์ ์ด ์๋ ์๋ ์๋ค
๋ฐ๋ผ์, ์์๋ก ์๊ฐ์ ์ง์ฐํ๋ ๋ฐฉ์์ ์ทจํด์ผํ๋ค.
๋ํ, ์ฌ์ดํธ๋ฅผ ํค๋ณด๋๋ ๋ง์ฐ์ค๋ก ์กฐ์ํด์ผ ํ๋ ๊ฒฝ์ฐ๊ฐ ์๊ธฐ ๋๋ฌธ์
ํ์ด์ฌ Selenium ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ํตํด ์๊ฐ์ ์ง์ฐ์ํค๊ฑฐ๋ ์กฐ์ํ ์ ์๋ค.
๐ค ๊ณต๋ถํ๋ฉด์ ์ด๋ ค์ ๋ ๋ด์ฉ
๋ณธ๊ฒฉ์ ์ผ๋ก ์น ์ฌ์ดํธ์์ ๋ฐ์ดํฐ๋ฅผ ์คํฌ๋ํํ ์ ์๋ ์๊ฐ์ด์๋ค.
์ ์ ๊ตฌ๊ธ ์ด๋ฏธ์ง๋ฅผ ํฌ๋กค๋งํ๊ฑฐ๋ ํ๋ฌํฐ๋ก ์๋ง์กด ๊ด๋ จ ์ฑ์ ๋ง๋ค์ด ๋ณธ ์ ์ด ์์ด์ ๋ด์ฉ์ด ํฌ๊ฒ ์ด๋ ต์ง๋ ์์๋ค.
๊ฐ์ธ์ ์ผ๋ก ๋ชปํด๋ดค๋ ์คํฌ๋ํ ํ ์๊ฐํํด๋ณด๋ ์๊ฐ์ด ๊ธฐ๋๋๋ค...!
'TIL' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[TIL]KDT_20230421 (0) | 2023.04.21 |
---|---|
[TIL]KDT_20230420 (0) | 2023.04.20 |
[TIL]KDT_20230418 (1) | 2023.04.18 |
[TIL]KDT_20230417 (0) | 2023.04.17 |
[TIL] KDT_20230414 (0) | 2023.04.14 |