AI/Python

[Python] Web Crawling - ์ •์  ์›น ํŽ˜์ด์ง€ ๐Ÿ†š ๋™์  ์›น ํŽ˜์ด์ง€

i-moo 2025. 10. 26. 16:27
๋ฐ˜์‘ํ˜•

๐Ÿ“Œ Crawling

์ผ๋‹จ ์ •์  ์›นํŽ˜์ด์ง€์™€ ๋™์  ์›นํŽ˜์ด์ง€๊ฐ€ ์กด์žฌํ•˜๋Š”๋ฐ ๊ทธ ์ฐจ์ด๋ฅผ ์•Œ์•„์•ผํ•œ๋‹ค.

์ •์  ์›นํŽ˜์ด์ง€๋Š” ์›€์ง์ด์ง€ ์•Š๊ณ  ํ˜„์žฌ ์ƒํƒœ ๊ทธ๋Œ€๋กœ html์„ ๊ฐ€์ ธ์™€ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์‚ฌ์ดํŠธ๋ฅผ ๋งํ•œ๋‹ค.
๊ฒ€์ƒ‰ํ–ˆ์„๋•Œ url ๋งํฌ๊ฐ€ ๊ฒ€์ƒ‰์–ด๊ฐ€ q = "hello" ํ˜•ํƒœ๋กœ ๋ถ™๋Š”๋‹ค๊ฑฐ๋‚˜
์ƒ์„ธ ํŽ˜์ด์ง€ url์„ ๊ฐ€์ง€๊ณ  ํ•ด๋‹น ์ƒํ’ˆ์˜ ์ƒ์„ธ ์ •๋ณด ๋‚ด์šฉ์„ ๋ชจ๋‘ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋Š” ํŽ˜์ด์ง€๋ฅผ ์ •์  ์›นํŽ˜์ด์ง€๋ผ๊ณ  ํ•œ๋‹ค.

๋™์  ์›นํŽ˜์ด์ง€๋Š” ๋™์ผํ•œ url์ธ๋ฐ ์‚ฌ์šฉ์ž์˜ ์ปจํŠธ๋กค์— ๋”ฐ๋ผ ํ™”๋ฉด์˜ ๊ฒฐ๊ณผ, html์ด ๋‹ฌ๋ผ์ง€๋Š” ์‚ฌ์ดํŠธ๋ฅผ ๋งํ•œ๋‹ค.
๋ฌดํ•œ ์Šคํฌ๋กค์ด ๊ฐ€๋Šฅํ•œ ํŽ˜์ด์ง€๋‚˜ tab ๋ฒ„ํŠผ์„ ๋ˆŒ๋ €๋Š”๋ฐ ํ˜„์žฌ ํŽ˜์ด์ง€์—์„œ ํ•˜๋‹จ ๊ฒฐ๊ณผ ๊ฐ’๋งŒ ๋‹ฌ๋ผ์ง€๊ฑฐ๋‚˜ ํ•œ๋‹ค.

๐Ÿ“Œ Crawling์—์„  ๋ญ๊ฐ€ ๋‹ค๋ฅธ๋ฐ??!!!

์ •์  ์›นํŽ˜์ด์ง€๋Š” requests ๋ชจ๋“ˆ์„ ์‚ฌ์šฉํ•˜์—ฌ url์˜ html์„ ๊ฐ€์ ธ์˜ค๋Š” ๋ฐฉ๋ฒ•์„ ๋ฐฐ์› ๊ณ ,
๋™์  ์›นํŽ˜์ด์ง€๋Š” selenium ๋ชจ๋“ˆ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ง์ ‘ ๋งˆ์šฐ์Šค๋ฅผ ์ œ์–ด(?)ํ•˜๋ฉฐ ํ•˜๋‚˜์˜ url์—์„œ ์›ํ•˜๋Š” ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๋ฐฉ๋ฒ•์„ ๋ฐฐ์› ๋‹ค.

๊ทธ๋ฆฌ๊ณ  html์„ ๊ฐ€์ ธ์™€์„œ ๋‚ด๊ฐ€ ์›ํ•˜๋Š” ๋ถ€๋ถ„์„ ์ฐพ์•„์˜ค๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ Beautifulsoup ์‚ฌ์šฉ๋ฒ•์„ ๋ฐฐ์› ๋‹ค.

๐Ÿ” ์ •์  ์›นํฌ๋กค๋ง

1๏ธโƒฃ ์ •์  ์›นํŽ˜์ด์ง€ requests ๋ชจ๋“ˆ ์‚ฌ์šฉํ•˜์—ฌ html ๊ฐ€์ ธ์˜ค๊ธฐ.
2๏ธโƒฃ ๊ฐ€์ ธ์˜จ html์„ lxml ํŒŒ์„œ๋ฅผ ์„ ํƒํ•ด์„œ html์„ ํ•ด์„ํ•œ๋‹ค.
3๏ธโƒฃ ํ•ด์„๋œ html = soup, soup์—์„œ ์›ํ•˜๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์ถ”์ถœํ•ด๋‚ธ๋‹ค.

res = requests.get(url, headers={"user-agent":user_agent})
res.encoding = "utf-8"

if res.status_code == 200:
    soup = BeautifulSoup(res.text, "lxml")
    
    a_tag_list = soup.select(a_selector)
    
    for a_tag in a_tag_list:
        print(a_tag.get("href"))
        print(a_tag.attrs["href"])
else:
    raise Exception(f"์š”์ฒญ ์‹คํŒจ. ์‘๋‹ต์ฝ”๋“œ: {res.status_code}")

 

โœ… BeautifulSoup Parser(ํŒŒ์„œ) ์ข…๋ฅ˜๋Š” "lxml", "html.parser", "html5lib" ์ค‘ ํ•˜๋‚˜๋ฅผ ์„ ํƒํ•œ๋‹ค.
html.parser๋Š” ํŒŒ์ด์ฌ ๋‚ด์žฅ์œผ๋กœ ์„ค์น˜๊ฐ€ ๋ถˆํ•„์š”ํ•˜์ง€๋งŒ ์†๋„๊ฐ€ ๋А๋ฆฐํŽธ์ด๋ฉฐ,
html5lib์€ HTML5 ํ‘œ์ค€์— ๋งž๊ฒŒ ์—„๊ฒฉํ•˜๊ฒŒ ํ•ด์„ํ•˜๋Š” ํŒŒ์„œ๋ผ์„œ ๋” ์†๋„๊ฐ€ ๋А๋ฆฌ๋‹ค.
์œ„์—์„œ ์‚ฌ์šฉํ•œ lxml์€ C์–ธ์–ด ๊ธฐ๋ฐ˜์ด๋ผ ์†๋„๊ฐ€ ์ œ์ผ ๋น ๋ฅด๊ณ  ์•ˆ์ •์„ฑ์ด ์ข‹์•„ lxml๋กœ ๋Œ€๋ถ€๋ถ„ ์‚ฌ์šฉํ•œ๋‹ค.

โœ… a_tag๋ฅผ ๊ทธ๋Œ€๋กœ printํ•ด๋ณด๋ฉด select๋กœ ๊ฐ€์ ธ์˜ค๊ฒŒ ๋œ html ๊ทธ๋Œ€๋กœ๊ฐ€ ํ‘œ์‹œ๋œ๋‹ค.
ํ•ด๋‹น html์—์„œ ๋‚ด๊ฐ€ ์›ํ•˜๋Š” ์ •๋ณด๋ฅผ ์ถ”์ถœํ•˜๋ ค๋ฉด a_tag์—์„œ๋„ select๋ฅผ ํ•ด์„œ ๋” ์ƒ์„ธํ•˜๊ฒŒ ๋“ค์–ด๊ฐˆ ์ˆ˜ ๋„ ์žˆ๊ณ ,
๋ฐ”๋กœ get์ด๋‚˜ attrs๋ฅผ ๊ฐ€์ง€๊ณ  ๋‚ด๊ฐ€ ์›ํ•˜๋Š” ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋‹ค.

๐Ÿ” ๋™์  ์›นํฌ๋กค๋ง

๋™์  ์›นํฌ๋กค๋ง์€ Selenium์ด ๋Œ€ํ‘œ์ ์ด๊ณ  ์š”์ฆ˜์—” Playwright๋„ ๋งŽ์ด ์‚ฌ์šฉํ•œ๋‹ค๊ณ  ํ•œ๋‹ค. ์ˆ˜์—…์‹œ๊ฐ„์—” Selenium์—๋Œ€ํ•ด์„œ ๋ฐฐ์› ๋‹ค.

option = webdriver.ChromeOptions()
option.add_argument("--headless")

driver_path = ChromeDriverManager().install()
service = Service(executable_path=driver_path)

browser = webdriver.Chrome(service=service, options = option)

๋™์  ์›นํฌ๋กค๋ง์€ ์ปดํ“จํ„ฐ์— ์กด์žฌํ•˜๋Š” chromedriver.exe ํŒŒ์ผ์„ ๊ฐ€์ง€๊ณ  ํฌ๋กค๋ง์„ ํ•˜๊ธฐ๋•Œ๋ฌธ์— 
browser ๊ฐ์ฒด๋ฅผ ํ†ตํ•ด ์›น ์‚ฌ์ดํŠธ์˜ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅผ ์ˆ˜๋„ ์žˆ๊ณ , ์Šคํฌ๋ฆฐ์ƒท์„ ํ•  ์ˆ˜๋„ ์žˆ๊ณ  ์Šคํฌ๋กค๋ฅผ ๋‚ด๋ฆฌ๊ฒŒ ํ•  ์ˆ˜ ๋„ ์žˆ๋‹ค.

execute_script("js code")๋ฅผ ํ†ตํ•ด์„œ ์›น์‚ฌ์ดํŠธ์—์„œ js์ฝ”๋“œ๋ฅผ ์‹คํ–‰์‹œํ‚ฌ ์ˆ˜ ๋„ ์žˆ๋‹ค.

โœ… ์›น ํฌ๋กค๋ง์„ ์‹œ์ž‘ํ•˜๋ฉด ๊ธฐ๋ณธ์œผ๋กœ ์›น์ด ์‹ค์ œ๋กœ ๋œจ๋ฉด์„œ ์ž‘๋™์ด ๋˜๋Š” ํ˜•ํƒœ์ธ๋ฐ,,,
๋ธŒ๋ผ์šฐ์ € ์ฐฝ์€ ๋„์šฐ์ง€ ์•Š๊ณ  ํฌ๋กค๋ง ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” option์— headless๋ฅผ ์„ค์ • ํ•ด์ค˜์•ผํ•œ๋‹ค.

โœ… ํŽ˜์ด์ง€ ์ด๋™์ด๋‚˜ ๋ฌดํ•œ์Šคํฌ๋กค์—์„œ ์Šคํฌ๋กค์„ ์ง„ํ–‰ํ•  ๋•Œ,
ํฌ๋กค๋ง์„ ๋ฐ”๋กœ ํ•˜๋ฉด ํ™”๋ฉด ๊ตฌ์„ฑ์ด ์™„๋ฃŒ๋˜์ง€ ์•Š์€ ์ƒํƒœ์˜ html์„ ๊ฐ€์ ธ์˜ค๊ฒŒ ๋œ๋‹ค.
์ด๋ฅผ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด์„œ ์‚ฌ์šฉํ•˜๋Š”๊ฒŒ time.sleep(์ดˆ), WebDriverWait.until(ํ™”๋ฉด์ด ๋œจ๋Š” ์กฐ๊ฑด), ImplicitWait๊ฐ€ ์žˆ๋‹ค.

time.sleep(n) : ๋ฌด์กฐ๊ฑด n์ดˆ๋งŒํผ ๊ธฐ๋‹ค๋ฆฌ๊ธฐ
WebDriverWait.until : ํ™”๋ฉด์˜ ๋œจ๋Š” ์กฐ๊ฑด์ด ๋งŒ์กฑ๋˜๋ฉด n์ดˆ๊ฐ€ ๋˜์ง€ ์•Š์•„๋„ ๋‹ค์Œ์œผ๋กœ ๋„˜์–ด๊ฐ„๋‹ค.
ImplicitWait : ์ „์ฒด ํŽ˜์ด์ง€ ๋กœ๋”ฉ์ด ๋๋‚ ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ ธ๋‹ค๊ฐ€ n์ดˆ๊ฐ€ ๋˜์ง€ ์•Š์•„๋„ ๋‹ค์Œ์œผ๋กœ ๋„˜์–ด๊ฐ„๋‹ค.

https://selenium-python.readthedocs.io/waits.html

1๏ธโƒฃ ๋ฌดํ•œ ์Šคํฌ๋กค ๊ฐ€๋Šฅํ•œ ๋™์  ์›นํŽ˜์ด์ง€ ์—ด์–ด์ฃผ๊ธฐ
2๏ธโƒฃ ์ œ์ผ ํ•˜๋‹จ๊นŒ์ง€ ๋ฌดํ•œ ์Šคํฌ๋กค ์ง„ํ–‰
3๏ธโƒฃ html ๊ฐ€์ ธ์˜ค๊ณ  ์›ํ•˜๋Š” ์ •๋ณด ๊ฐ€์ ธ์˜ค๊ธฐ

Selenium ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ ์ •์ ์ด๋“  ๋™์ ์ด๋“  ์ž๋™์œผ๋กœ ์›น ํฌ๋กค๋ง ํ•˜๊ฒŒ ๋งŒ๋“ค๊ธฐ๋„ ํ•˜๊ณ , ๋งคํฌ๋กœ๋ฅผ ๋งŒ๋“ค์–ด ์‚ฌ์šฉํ•˜๊ธฐ๋„ ํ•œ๋‹ค.

๋ฐ˜์‘ํ˜•