Web Crawling - kamchur/note GitHub Wiki
[์ฐธ์กฐ ๋งํฌ]
server status
-
crawling : ํ์ด์ง์ ํน์ ๋ฐ์ดํฐ๋ฅผ ์์งํ๊ณ ๋ถ๋ฅํ๋ ์์
-
scraping : ๋ฐ์ดํฐ๋ฅผ ์์งํ๋ ์์
-
bot : ํ์ด์ง ์ ๋ณด๋ฅผ DB์ ์ ์ฅํด๋์, ์ ์ ๊ฐ ์์ฒญ์ DB์์ ์ถ์ถํ์ฌ ์ ๋ฌํ๋ฏ๋ก ๊ฒ์์๋๊ฐ ๋น ๋ฆ
-
POST๋ฐฉ์์ payload์ ๋ง์ด ๋ด์ ์ ์๊ณ
-
GET๋ฐฉ์์ URL์์ ๋ด๊ธฐ์ ๋ง์ด ๋ด์ ์ ์์(๋ธ๋ผ์ฐ์ ์ ๋ฐ๋ผ ์ ํ๋ ๊ธ์ ์)
-
array(JSON)์ 'list'๋ผ๊ณ ๋ณด๋ฉด ๋จ
-
JSON์ 'dictionary'๋ผ๊ณ ๋ณด๋ฉด ๋จ
-
html์ 10000์๋ฅผ ๋ณด๋ด๋ฉด ์ฌ์ฉํ ์ ์๋ ๊ธ์๊ฐ 1000์์ธ๋ฐ
json์ 2000์ ์ค์ 1000์์ฌ์ฉ, json์ ์ ๋ณด๋ฅผ ์ ๋ฌํ๋ ์๋ ์์ฐจ๊ณ ์ ์ด์ ์๋๊ฐ ๋น ๋ฆ
crawling์ ์ฑ
url = */robots.txt
User-agent : ํด๋ผ์ด์ธํธ๊ฐ ์ด๋ค ์ ๋ณด๋ฅผ ๊ฐ์ง๊ณ ์๋์ง ์ ์ํด๋์๊ฒ
์๋ฒ์ชฝ์์ ์ด๋ค ํด๋ผ์ด์ธํธ๊ฐ ์์ฒญํ๋์ง? OS๋ ๋ฌด์์ธ์ง
๋ธ๋ผ์ฐ์ ๋ ๋ฌด์์ธ์ง ๋ฒ์ ์ ๋ฌด์์ธ์ง ํด๋ผ์ด์ธํธ์๋ํ ์ ๋ณด๋ฅผ
User Agent๋ผ๋ ์ด๋ฆ์ผ๋ก requestํ ๋ ์๋ฒ์ ๋ณด๋
์๋ฒ์ชฝ์์ web application ๊ฐ๋ฐํ๋ ์ฌ๋์ด ์ ์ ์์
User-agent: * # ๋ชจ๋ ์ ์ ๋ค์ด ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ๊ฐ๋ ๋๋ค๋ ๋ป
Baiduspider ์ค๊ตญ์ ๊ตฌ๊ธ
ํฌ๋กค๋ง์ ๋ํ ๋ฒ์ ์ ์ฌx
๊ณผ๋ํ ํฌ๋กค๋ง์ผ๋ก ์๋น์ค์ ์ํฅ์ ์ฃผ์์ ๋ ๋ฌธ์ ๊ฐ ๋ ์ ์์:์์
๋ฐฉํด
ํ์ฌ ๊ณ ์ ์์ฐ์๋ํ ์นจํด๋ ์ง์ ์ฌ์ฐ๊ถ ์นจํด๋ฅผ ์ค
ํฌ๋กค๋ง์ ํ ๋๋ ๋๋๋ก API๋ฅผ ์ฌ์ฉํ๋๊ฒ์ด ์ข์
- 1. requests : json : ์นํ์ด์ง API ํธ๋ํฝ์ ๋ถ์ํด์ ๋ฐ์ดํฐ ์์ง : naver stock
- 2. requests : json : ๊ณต์์ ์ผ๋ก ์ ๊ณตํ๋ API๋ฅผ application key ๋ฐ์์ ๋ฐ์ดํฐ ์์ง : naver api(papago, trend)
- 3. requests : html, BeautifulSoup(css selector) : ์นํ์ด์ง์ html ์ฝ๋ ๋ฐ์์ ๋ฐ์ดํฐ ์์ง : gmarket
- 4. selenium : browser - python : ๋ธ๋ผ์ฐ์ ธ๋ฅผ ํ์ด์ฌ ์ฝ๋๋ก ์ปจํธ๋กคํด์ ๋ฐ์ดํฐ์์ง : ted
- ํฌ๋กค๋งํ ๋ ์ข์ ์์ : 2 > 1 > 3 > 4
html๊ณผ cssํ๊ธฐ
ํ๋ ์ด์ ๋? ๋ธ๋ผ์ฐ์ ์์ ์ฌ์ฉ๋๋ ์ธ์ด๋ ์ธ๊ฐ์ง ์ธ์ด๊ฐ ์๋ค
HTML, CSS, JS(Javascript)
> HTML์ด ํ๋ ์ญํ
ํ
์คํธ ์ ๋ณด, ๋ ์ด์์์ ์์น๋ฅผ HTML์ด ์ ์ํด์ค
ํด๋ฆญํ๋ฉด ์ด๋๋๋ ๋งํฌ๋ฅผ ์ ํด์ฃผ๋ ๋์๋
> CSSํ๋ ์ญํ
ํ
์คํธ์ ์ฌ์ด์ฆ, ๋ฒํผ์ด ์์๋ ๋ฒํผ์ ์์, ํฌ๊ธฐ, ์คํ์ผ
> JS ์ญํ
EVENT๋ด๋น, ๋ฒํผ์ ํด๋ฆญํ์๋ ์ด๋ค ๋์์ ํ ๊ฒ์ธ์ง
html์ ์์น๋ฅผ ์์์ผ
๋ฐ์ดํฐ๋ฅผ ํด๋ฆญํด์ ๋ฐ๊ฟ์ฃผ๊ธฐ ์ํด์์์ผํจ
CSS Selector ๋ผ๊ณ ํจ
ํด๋น ๋ฐฉ๋ฒ์ ์์์
Client๊ฐ Server์์ ๋ฐ์ดํฐ(html)๋ฅผ ๋ฐ์์ฌ๋
ํน์ ์์น์ ๋ฐ์ดํฐ๋ฅผ CSS Selector๋ฅผ ์ด์ฉํด์
ํน์ ๋ฐ์ดํฐ๋ฅผ ์์งํ ๊ฒ
์๊ด๊ด๊ณ๋ถ์์ด๋?
- ๋ ๋ฐ์ดํฐ ์งํฉ ์ฌ์ด์ ์ด๋ค ๊ด๊ณ๊ฐ ์๋์ง ํ์ธํ๋ ๋ถ์ ๋ฐฉ๋ฒ
- '์๊ด๊ณ์'๋ก ํ์ธ์ ํ๋ฉฐ 'object'ํ์
์ด ์๋ '์ซ์'ํํ์ฌ์ผ ํ์ธ ๊ฐ๋ฅ
์๊ด๊ด๊ณ
`1`๊ณผ ๊ฐ๊น์ธ์๋ก ๊ฐํ ์์ ์๊ด๊ด๊ณ
`-1`๊ณผ ๊ฐ๊น์ธ์๋ก ๊ฐํ ์์ ์๊ด๊ด๊ณ
`0`๊ณผ ๊ฐ๊น์ธ์๋ก ์๋ก ๊ด๊ณ์์
URL๋ถ์
https:// - Protocol
naver.com - Domain
news - sub Domain
80 - port
/main/ - path
read.nhn - page
?mode=LSD&mid.... - query
#da_727145 - fragment > velog์์ ###ํ๊ณ ํ๊ทธ๋ ์ด๋ฆ์ ๋๋ฅด๋ฉด ํด๋น ํ์ด์ง๋ก ์ด๋ ์ํค๋๊ฒ๊ณผ ๋์ผํ ์ญํ
url ํ์ธ
๋ฐ์ดํฐ ์์ฒญ
๋ฐ์ดํฐ ํ์ฑ
import pandas as pd
import requests
# ํตํฉ ๊ฒ์ ํธ๋ ๋
url = "https://openapi.naver.com/v1/datalab/search"
params = {
"startDate": "2018-01-01",
"endDate": "2022-01-31",
"timeUnit": "month",
"keywordGroups": [
{"groupName": "ํธ์ํฐ", "keywords": ["ํธ์ํฐ", "ํธ์"]},
{"groupName": "ํ์ด์ค๋ถ", "keywords": ["ํ์ด์ค๋ถ", "ํ๋ถ"]},
{"groupName": "์ธ์คํ๊ทธ๋จ", "keywords": ["์ธ์คํ๊ทธ๋จ", "์ธ์คํ"]},
]
}
# application key value
headers = {
'Content-Type':'application/json',
'X-Naver-Client-id':CLIENT_ID,
'X-Naver-Client-Secret':CLIENT_SECRET,
}
# ์๋ฒ์ ๋ฐ์ดํฐ ์์ฒญ : `json_dumps()` : ํ๊ธ ์ธ์ฝ๋ฉ ์ฉ๋
response = requests.post(url, json.dumps(params), headers=headers) # <Response [200]>
# ๋ฐ์ ๋ฐ์ดํฐ ํ์ฑ(๋ฐ์ดํฐ ํํ ๋ณ๊ฒฝ)
data = response.json()["results"]
# DataFrame ๋ณํ
dfs = []
for data in datas:
df = pd.DataFrame(data["data"])
df["title"] = data["title"] # ํธ์ํฐ, ํ์ด์ค๋ถ, ์ธ์คํ๊ทธ๋จ
dfs.append(df)
# Processing
df = pd.DataFrame({
'date': [period['period'] for period in data[0]['data']],
'twitter': [ratio['ratio'] for ratio in data[0]['data']],
'instagram': [ratio['ratio'] for ratio in data[1]['data']],
'facebook': [ratio['ratio'] for ratio in data[2]['data']],
})
# show chart
df.plot(figsize=(20,5))
import pandas as pd
import requests
url = "https://finance.daum.net/api/exchanges/summaries"
headers = {
"user-agent": "user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36",
"referer": "https://finance.daum.net/exchanges",
}
response = requests.get(url, headers=headers)
datas = response.json()["data"]
df = pd.DataFrame(datas)
columns = ["date", "currencyCode", "currencyName", "country", "name", "basePrice"]
df[columns].head()
import requests
import pandas as pd
import geohash2
addr = "๋ง์๋"
url = f"https://apis.zigbang.com/v2/search?leaseYn=N&q={addr}&serviceType=์๋ฃธ"
response = requests.get(url)
data = response.json()["items"][0]
lat, lng = data["lat"], data["lng"]
# geohash๋ก ์๋, ๊ฒฝ๋ ์์๋ด๊ธฐ, !pip install geohash2
geohash = geohash2.encode(lat, lng, precision=5)
# geohash๋ก ๋งค๋ฌผ ์์ด๋ ์์๋ด๊ธฐ
url = f"https://apis.zigbang.com/v2/items?deposit_gteq=0&domain=zigbang\
&geohash={geohash}&needHasNoFiltered=true&rent_gteq=0&sales_type_in=์ ์ธ|์์ธ\
&service_type_eq=์๋ฃธ"
response = requests.get(url)
datas = response.json()["items"]
# len(datas), datas[0]
ids = [data["item_id"] for data in datas]
# ๋งค๋ฌผ์์ด๋๋ก ๋งค๋ฌผ์ ๋ณด ๊ฐ์ ธ์ค๊ธฐ
url = "https://apis.zigbang.com/v2/items/list"
params = {
"domain": "zigbang",
"withCoalition": "true",
"item_ids": ids
}
response = requests.post(url, params)
# parsing
datas = response.json()["items"]
df = pd.DataFrame(datas)
columns = ["item_id", "sales_type", "deposit", "rent", "size_m2", "floor", "building_floor",
"address1", "manage_cost"]
filtered_column_df = df[columns]
# ์ฃผ์์ ๋ง์๋์ด ์๋ ๋ฐ์ดํฐ๋ง ํํฐ๋ง
result_df = filtered_column_df[filtered_column_df["address1"].str.contains("๋ง์๋")]
result_df = result_df.reset_index(drop=True)
result_df.tail(2)
def usa_data(pagesize, page, code):
url = f'https://api.stock.naver.com/marketindex/exchange/{code}/prices?page={page}&pageSize={pagesize}'
response = requests.get(url)
data = response.json()
return pd.DataFrame(data)
# 60ํ์ด์ง๋ฅผ ๊ฐ์ ธ์ค๊ธฐ
usd = usa_data(60, 1, 'FX_EURKRW')
# ๋ฐ์ดํฐ ์ ์ฒ๋ฆฌ
df = kospi.copy() # ์ ์นดํผ๋ฅผ ์ผ๋์ง๋ ๋ง์ง๋ง์ ์ค๋ช
์ ํ๋๋ก ํจ
df['kosdaq'] = kosdaq['closePrice']
df['usd'] = usd['closePrice']
df = df.rename(columns={'closePrice':'kospi'})
# ์ปฌ๋ผ์ ๋ฐ์ดํฐ ํ์
๋ณ๊ฒฝ : str > float
# df[column].apply() : ๋ชจ๋ ๋ฐ์ดํฐ๋ฅผ ํจ์์ ๋์
ํ ๊ฒฐ๊ณผ๋ฅผ ์ถ๋ ฅ
df['kospi'] = df['kospi'].apply(lambda data:float(data.replace(',', '')))
df['kosdaq'] = df['kosdaq'].apply(lambda data:float(data.replace(',', '')))
df['usd'] = df['usd'].apply(lambda data:float(data.replace(',', '')))
df[['kospi', 'kosdaq', 'usd']].corr()
# kospi - kosdaq : 0.984 : 1๊ณผ ๊ฐ๊น์ฐ๋ฉด ๊ฐํ ์์ ์๊ด๊ด๊ณ
# kospi - usd : -0.878 : -1๊ณผ ๊ฐ๊น์ฐ๋ฉด ๊ฐํ ์์ ์๊ด๊ด๊ณ
css-selector์ฌ์ฉํ ์ ์๋๋ก ๋์์ฃผ๋๊ฒ์ด BeautifulSoup
# ์๋ฆฌ๋จผํธ ํ๋ ์ ํ : select_one()
# tag์ด๋ฆ : span
# id : #kt
# class : .kt
# attr : [value='kt']
# ์ฌ๋ฌ๊ฐ์ ์๋ฆฌ๋จผํธ ์ ํ : select()
# .not(.kt1)
# :nth-child(n)
# .wrap > p : ํ ๋จ๊ณ ํ์ ์๋ฆฌ๋จผํธ์์ ์ ํ
# .wrap p : ๋ชจ๋ ํ์ ์๋ฆฌ๋จผํธ์์ ์ ํ
# .kt1, .kt2 : ์ ํํ๋ ๋ชจ๋ ์๋ฆฌ๋จผํธ ์ ํ
n๋ฒ์งธ element์ ํํ๋ ๋ฐฉ๋ฒ
: .py:nth-child(2)
โป์ฃผ์์ฌํญ, .py element์ค์ 2๋ฒ์งธ๊ฐ ์๋
2๋ฒ์งธ ์๋ฆฌ๋จผํธ์ค์ ํด๋์ค๊ฐ .py์ธ ์๋ฆฌ๋จผํธ๋ฅผ ์ ํํ๋๊ฒ
๊ณ์ธต์ element์ ํ(3๊ฐ์ง ๋ฐฉ๋ฒ)
1. ๋ชจ๋ ํ์ ์๋ฆฌ๋จผํธ ์ ํ, ( ) ๊ทธ๋ฅ ๊ณต๋ฐฑ ์ฌ์ฉ
(.wrap p) # .wrap์์ p์๋ฆฌ๋จผํธ
2. ํ๋จ๊ณ ํ์ ์๋ฆฌ๋จผํธ (.wrap > p)
3. ์ฌ๋ฌ๊ฐ ์ ํ (.no1, .no2) # ๋๊ฐ์ ํด๋์ค๋ฅผ ๋ชจ๋ ์ ํ
import pandas as pd
import requests
from bs4 import BeautifulSoup
# URL
keyword = 'kt'
url = f'https://search.naver.com/search.naver?where=nexearch&sm=top_hty&fbm=1&ie=utf8&query={keyword}'
# ์ ์ ํ์ด์ง๋ 'JSON'์ด ์๋ 'HTML'์ด ์ค๊ธฐ์ ๋ณํ์ด ํ์
response = requests.get(url)
dom = BeautifulSoup(response.text, 'html.parser')
# select() : ์๋ฆฌ๋จผํธ ์ฌ๋ฌ๊ฐ ์ ํ
# select_one() : ์๋ฆฌ๋จผํธ ํ๊ฐ ์ ํ
elements = dom.select('.lst_related_srch > .item') # BeautifulSoap ๊ฐ์ฒด๋ฅผ ๋ง๋ค์ด์ฃผ๋ ์ด์ CSS_Selector๋ฅผ ๋ง๋ค์ด์ฃผ๊ธฐ ์ํด
# ์ด 10๊ฐ์ ํ
์คํธ๋ฅผ ๊ฐ์ ธ์๋ณด์
# keywords = [element.select_one('.tit').text for element in elements]
keywords = []
for element in elements:
keyword = element.select_one('.tit').text
keywords.append(keyword)
['์ผ์ฑ์ ์', 'kt ๊ณ ๊ฐ์ผํฐ', 'kt ์ธํฐ๋ท', 'ky', 'ํ์จ', 'kr', '๋ ์จ', 'kt ๋๋ฆฌ์ ', 'SKT', 'kt ๊ณ ๊ฐ์ผํฐ ์ ํ๋ฒํธ']
import pandas as pd
import requests
from bs4 import BeautifulSoup
# ๊ฐ๋ฐ์๋๊ตฌ > Networkํญ๋๋ฅด๊ณ > ์๋ก๊ณ ์นจ > BestSellersํด๋ฆญ >
url = 'http://corners.gmarket.co.kr/Bestsellers'
response = requests.get(url)
# HTML(str) > BeautifulSoup Object
dom = BeautifulSoup(response.text, 'html.parser')
type(dom) # bs4.BeautifulSoup
# 200๊ฐ์ ์ํ ์๋ฆฌ๋จผํธ ์ ํ
# Elements > ํด๋ฆญ >
elements = dom.select('#gBestWrap > div > div:nth-child(5) > div > ul > li') # ๋ชจ๋ li๋ฅผ ์ ํํ๋ ค๋ฉด nth์ญ์
len(elements) # 200
# element์ ๋ด์ฉ์ DataFrame์ผ๋ก ๋ง๋ฆ
element = elements[0]
# dictionary format์ผ๋ก ๋ง๋ค์ด์ค
# ์ด๋ฏธ์ง๋ img ํ๊ทธ ์๋์ data_origin
items = []
for element in elements:
data = {
'title':element.select_one('.itemname').text,
'o_price':element.select_one('.o-price').text,
's_price':element.select_one('.s-price > strong').text,
'img':'http:' + element.select_one('img').get('data-original'),
}
items.append(data)
df = pd.DataFrame(items)
df.tail(2)
import pandas as pd
import requests, os
# os๋ filesystem์ ๋ค๋ฃจ๋ ์์คํ
, ํ์ผ ์ญ์ , ๋ณต์ฌ, ์ด๋ํ๋ ํจํค์ง
# ๋๋ ํ ๋ฆฌ ์์ฑ
path = 'data'
if not os.path.exists(path):
os.makedirs(path) # data์ด๋ฆ์ folder์์ฑ
# csvํ์ผ์ ๋ก๋(csvํ์ผ ๋ด์ URL๊ฒฝ๋ก๊ฐ ์์์)
df = pd.read_csv('gmarket.csv')
# ๊ฐ์ฅ ์์ ์๋ ์ด๋ฏธ์งURL ๋ถ๋ฌ์ค๊ธฐ http://gdimg.gmarket.co.kr/2266434001/still/30...
img_link = df.loc[0, 'img'] # loc[ํ์กฐ๊ฑด, ์ด์ด๋ฆ]
# image download : requests๋ฅผ ์ด์ฉํด์ ์ด๋ฏธ์ง ๋ค์ด๋ก๋๋ฅผ ๋ฐ์ ๊ฒ
response = requests.get(img_link)
# ์ด๋ฏธ์ง ์ ์ฅ
with open(f'{path}/test.png', 'wb') as file: # ์ ์ฅ์:wb(write binary), ์ฝ์์:rb
file.write(response.content) # ํ
์คํธ ๋ฐ์ดํฐ๊ฐ ์๋๊ธฐ๋๋ฌธ์ 'content' ์ฌ์ฉ
# img ์ถ๋ ฅ
from PIL import Image as pil
pil.open(f'{path}/test.png')
# ํ์ผ์ด๋ฆ ์ง์ ์ฌ๋ฌ๊ฐ
for idx, data in df[:3].iterrows():
# filename = '0' * (3 - len(str(idx))) + str(idx) + '.png'
filename = '%03d.png' % (idx)
print(idx,filename, data['img'])
response = requests.get(data['img'])
with open(f'{path}/{filename}', 'wb') as file:
file.write(response.content)
pil.open(f'{path}/001.png')
๋ธ๋ผ์ฐ์ ๋ฅผ ์ด์ฉํด ๋ฐ์ดํฐ ์์ง
QAํ, ๊ฒ์ํ๋ ๊ณผ์ ์ ์๋ํํ๋ ํจํค์ง
๋ธ๋ผ์ฐ์ ๋ฅผ python์ธ์ด๋ก ์ปจํธ๋กคํ์ฌ ๋ฐ์ดํฐ๋ฅผ ์์งํ๋๊ฒ
ํ๊ฒฝ์ค์
๊ฒ์ > chrome driver
chrome browser ๋ฒ์ ํ์ธ
์ค๋ฅธ์ชฝ ์๋จ ์ฉ์ฉ์ฉ ํด๋ฆญ
๋์๋ง > ํฌ๋กฌ์ ๋ณด
104.0.5112.79(๋งจ ์์ ์ธ๊ธ์๋ง ํ์ธ)
chromedriver.win32.zip ๋ค์ด๋ก๋
chromedriver๋ฅผ ์ฌ์ฉํ๋ ์ด์ ๋
์๋์ selenium์ `webdriver`๋ก `Chrome()`ํจ์๋ฅผ ์ฌ์ฉํ์์
`Chrome`๋ธ๋ผ์ฐ์ ์ฐฝ์ ๋์ฐ๊ธฐ ์ํด์์ด๋ค
# find_element() == BeautifulSoup.select_one() , find_elements() = BeautifulSoupselect()
# pandas, numpy๋ python๋ง ์ง์ํ๋๋ฐ selenium์ ๋ค์ํ ์ธ์ด, ๋ธ๋ผ์ฐ์ ์ ์ง์์ด ๊ฐ๋ฅ
# !pip install selenium
from selenium import webdriver
from selenium.webdriver.common.by import By
# ๋ธ๋ผ์ฐ์ ๋์ฐ๊ธฐ
driver = webdriver.Chrome()
# ํ์ด์ง์ด๋
driver.get('url')
# ๋ธ๋ผ์ฐ์ ์ฌ์ด์ฆ ์กฐ์
driver.set_window_size(200, 600)
# ๋ธ๋ผ์ฐ์ ์คํฌ๋กค ์กฐ์ (html css javascript) > javascript code ์คํ
driver.execute_script('window.scrollTo(200, 300)')
# ๋ธ๋ผ์ฐ์ ์คํฌ๋กค ์์ ๋ณต๊ท
driver.execute_script('window.scrollTo(0, 0)')
# alert ๋ค๋ฃจ๊ธฐ, ์นํผ์ด์ง ์ธ๋ ์กฐ๊ทธ๋ง ํ์ด์ง๊ฐ ๋จ๋๋ฐ ํด๋น ์ฐฝ์ด ์๋ ์ผ ํฌ๋กค๋ง๊ฐ๋ฅ
#alert์ฐฝ ๋์ฐ๊ธฐ
driver.execute_script("alert('hello selenium!');")
# alert์ฐฝ ๋ซ๊ธฐ
alert = driver.switch_to.alert
alert.accept()
# inpuut ์ฐฝ์ ๋ฌธ์์ด ์
๋ ฅ, ๋ฐ๋ก ํด๋น ์ฌ์ดํธ๋ฅผ ์ด์ด๋๊ณ
# ๊ฐ๋ฐ์๋๊ตฌ๋ฅผ ์ฌ์ฉํ์ฌ selector๋ฅผ ์ฌ์ฉํด htmlํ์ธ
driver.find_element(By.CSS_SELECTOR, '#q').send_keys('ํ์ด์ฌ') # q์ด์ ๋ element๋ก css selector๋ก ํ์ธํ์๋ id='q'์๋ค
# ๊ฒ์ ๋ฒํผ ํด๋ฆญ, `.`๋ถ์ฌ์ฃผ๋ฉด ๋๋ค์ ํ
driver.find_element(By.CSS_SELECTOR, '.inner_search > .ico_pctop.btn_search').click()
# ๋ธ๋ผ์ฐ์ ์ข
๋ฃ
driver.quit()
from selenium import webdriver
from selenium.webdriver.common.by import By
# ๋ธ๋ผ์ฐ์ ์ด๊ธฐ
driver = webdriver.Chrome()
# ํ์ด์ง ์ด๋
driver.get('https://ted.com/talks')
# ์ ๋ชฉ ๋ฐ์ดํฐ ํ
์คํธ ์์ง
# css-selector : #bannersecondary
sub_title = driver.find_element(By.CSS_SELECTOR, '#banner-secondary').text #.text๋ฅผ ํด์ฃผ์ด์ผ ์ ๋ชฉ๊ฐ์ ธ์ด
# select box์์ ํ๊ตญ์ด ํด๋ฆญ
# languages > optgroup > [lang='ko'] ๋๋ languages [lang='ko'] `ํ ์นธ ๋์ด์ค์ผ๋ก์จ ๋ชจ๋ ๊ฒ์ํ๋ ๋ฐฉ๋ฒ
driver.find_element(By.CSS_SELECTOR, '#languages [lang-'ko']').click()
# ํ๊ตญ์ด ๋ฉ๋ด๊ฐ ๋์ค๋ฉด, ์ ์ฒด ๋ฐ์ดํฐ์ ์ ๋ชฉ๊ณผ ๋งํฌ ๋ฐ์ดํฐ๋ฅผ ์์ง
elements = driver.find_elements(By.CSS_SELECTOR, '#browse-results > .row > div')
len(elements) # 36
# ga-link ์ฒซ๋ฒ์งธ ๋ชฉ๋ก๋ฐ์ดํฐ
element = elements[0]
# ga-link๊ฐ ๋๋ฌด ๋ง๊ธฐ ๋๋ฌธ์ ์ ํํ ๊ฐ์ด ๋์ค์ง ์์
# h4๋ class ์์ attr
title = element.find_element(By.CSS_SELECTOR, 'h4 > .ga-link').text
link = element.find_element(By.CSS_SELECTOR, 'h4 > .ga-link').get_attribute('href') # element์ ์์ฑ๊ฐ ๊ฐ์ ธ์ค๊ธฐ
# ๋ฐ์ดํฐ ํ๋ ์์ผ๋ก ๋ง๋ค๊ธฐ
data = []
for element in elements:
data.append({
'title' : element.find_element(By.CSS_SELECTOR, 'h4 > .ga-link').text,
'link' : element.find_element(By.CSS_SELECTOR, 'h4 > .ga-link').get_attribute('href'),
})
df = pd.DataFrame(data)
๋ธ๋ผ์ฐ์ ธ๋ฅผ ํ๋ฉด์ ๋์ฐ์ง ์๊ณ ๋ฉ๋ชจ๋ฆฌ ์์์๋ง ๋ธ๋ผ์ฐ์ ๋ฅผ ์คํํ์ฌ ํฌ๋กค๋ง ํ๋ ๋ฐฉ๋ฒ
window๊ฐ ์ง์๋์ง ์๋ ํ๊ฒฝ์์ selenium์ฌ์ฉ ๊ฐ๋ฅ
ํฌ๋กฌ ๋ฒ์ : 60 ์ด์๋ถํฐ ์ง์ ๊ฐ๋ฅ
์ ๋ ๋์ headless ๋ชจ๋๋ ํ๋ฉด์ ํ์๋๋ ๋ธ๋ผ์ฐ์ ๊ฐ ์๋ ๋ชจ๋์ง๋ง ๋ด๋ถ์ ์ผ๋ก๋ ํ๋ฉด์ ๊ฐ์ง๊ณ ,
๋ ๋๋ง๋๋ ํ์ด์ง๋ฅผ ๊ณ์ฐํฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ , headless ๋ชจ๋๋ ํ๋ฉด์ฌ์ด์ฆ๊ฐ 800x600
# ํฌ๋กฌ ๋ฒ์ ํ์ธ
driver = webdriver.Chrome()
version = driver.capabilities['browserVersion']
driver.quit()
version
# ๋ธ๋ผ์ฐ์ ๋ฅผ ๋์ฐ๋ ์๋์ฐ๋ ์๋๋ ํฌ๊ฒ ์ฐจ์ด ์์
options = webdriver.ChromeOptions() # tag less?
options.add_argument('headless') # argument๋ ์๋์ฐ์ ์ฌ์ด์ฆ๋ฅผ ์กฐ์ ?
# options๋ฅผ ์ค์ ํด์ฃผ๋ฉด browser ํ๋ฉด์ด ๋จ์ง ์์์ฑ ๋ฐ์ดํฐ๋ฅผ ์์งํ ์ ์์
driver = webdriver.Chrome(options=options)
driver.get('https://ted.com/talks')
sub_title = driver.find_element(By.CSS_SELECTOR, '#banner-secondary').text
driver.quit()
sub_title
# iframe์ ์นํ์ด์ง๋ฅผ ์๋ก์ด ํ์ด์ง ์บ๋ ๋ฐฉ์
# ํฌ๋กค๋ง์ผ๋ก ์ ๋ช
ํ๊ฒ์ด ๋ฑ
ํฌ์๋ฌ๋ ์ฑ์ด ์๋ค
from selenium import webdriver
from selenium.webdriver.common.by import By
# ์น๋ธ๋ผ์ฐ์ ์ด๊ธฐ ๋ฐ ํ์ด์ง ์ด๋
driver = webdriver.Chrome()
driver.get(url)
# rendering ๋๋ ๋์ ๋ชป์ฐพ์์๋ ์๋ค. ๋ฐ์ดํฐ๋ฅผ ๋ถ๋ฌ์ค๋ ์๊ฐ์ ์ฃผ๋ฉด ์ข๋ค
import time
time.sleep(3) # 3์ด
# 2. ๊ฒ์์ฐฝ์ '๋งฅ๋ถ'์
๋ ฅํ๊ณ ๊ฒ์ ๋ฒํผ ํด๋ฆญ
# + selenium์ ์นํ์ด์ง๋ฅผ ํ
์คํธํ๊ธฐ ์ํด ๋ง๋ค์ด์ง ๊ฒ์ธ๋ฐ ์นํ์ด์ง ๋ด์ ๋ณด์ด์ง ์๋ ์์ญ์ ํด๋ฆญํ๊ฒ ๋๋ฉด
# ์๋ฌ๊ฐ ๋ฐ์ํ ์ ์๋ค ๊ทธ๋์ ์คํฌ๋กค์ ํ์ฌ ์ํ๋ ๋ ์ด์์์ด ๋ณด์ผ ์ ์๋๋ก scrollํด์ฃผ์ด์ผํจ
# send_keys๋ก ๊ฒ์์ด์ ํ
์คํธ ์
๋ ฅํ๋ ๋ฐฉ๋ฒ
# ๊ฒ์์ฐฝ ID : topLayerQueryInput
keyword = '๋งฅ๋ถ'
driver.find_element(By.CSS_SELECTOR, '#topLayerQueryInput').send_keys(keyword)
# ๊ฒ์๋ฒํผ ํด๋ฆญํ๋ ์ฝ๋
# searchBoard();return false; javascript onClick ๋ฒํผ ์
๋ ฅ : ์๋๋ ํจ์ฌ ๋น ๋ฆ
driver.execute_script('searchBoard();')
# ๊ฒ์๊ธ ๋ชฉ๋ก ๋ฐ์ดํฐ ์์ง (๋งค์ฐ์ค์ํ ๋ถ๋ถโ
) : iframe
selector = '.article-board' # table tbody tr
elements = driver.find_elements(By.CSS_SELECTOR, '.article-board > table > tbody > tr')
len(elements) # 0 ์ด ๋์๋ค๋๊ฒ์ ์ ๊ทผํ ์ ์๋ค๋๊ฒ
# ์ ์ ํ์ ๋ชปํ๋๋ฉด ์ ์ฒด ๊ฒ์๊ธ๋ถ๋ถ์์ ์ญ ์ฌ๋ผ๊ฐ๋ณด๋ฉด iframe์ผ๋ก ๋จ, ํ์ด์ง์์ ํ์ด์ง๊ฐ ์๋๊ฒ
# iframe์์ ์๋ ๋ฐ์ดํฐ์ ์ ๊ทผํ ์ ์๋ค.
# ์๋๋ก์ด๋ Acitvity์ windowpopup์ ํฌ์ปค์ฑ ๋ฌธ์ ์ ๋น์ทํ ๋ฌธ์ ๋ก ๋ณด์ฌ์ง
# iframe์ผ๋ก driver ์ด๋, id = 'cafe_main'
iframe = driver.find_element(By.CSS_SELECTOR, "#cafe_main") # iframe ๊ฐ์ฒด๋ฅผ ์ ํํด์ค๊ฒ
iframe
# ์์ ์๋ frame ์ ํ
driver.switch_to.frame(iframe)
### ์๋ default frame์ผ๋ก ์ด๋
driver.switch_to.default_content()
# iframe์ผ๋ก driver์ ์ด๋ํ ๋ค์ ๋ฐ์ดํฐ๋ฅผ ์ ํํ๋ ๋ฐ์ดํฐ๊ฐ ์ ํ์ด ๋์๋ค
selector = '.article-board'
elements = driver.find_elements(By.CSS_SELECTOR, '.article-board > table > tbody > tr')
len(elements) # 15
# ์ ๋ชฉ ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ
data = []
for element in elements:
data.append({
'title':element.find_element(By.CSS_SELECTOR, ".article").text,
'writer':element.find_element(By.CSS_SELECTOR, '.p-nick').text,
})
df = pd.DataFrame(data)
df.tail(2)
# ๋ธ๋ผ์ฐ์ ์ข
๋ฃ
driver.quit() # ๋ฉ๋ชจ๋ฆฌ๊ฐ ๋ฐ๋ฉ๋์ด ์ปดํจํฐ๊ฐ ๋ค๋ฅธ ์ผ์ ํ๋๋ฐ ์ฌ์ฉํ ์ ์๋๋ก...
premierleague.csv ๋ฐ๋์ง ๊ฐ์ฌ๋ ์ฐธ์กฐ ํ์ผ ์ฌ์ฉ
df = pd.read_csv('premierleague.csv')
feature = df[['gf', 'ga']] # ๋์ , ์ค์
target = df[['points]]
# !pip install sklearn
from sklearn.linear_model import LinearRegression
import numpy as np
# ์ธ๊ณต์ง๋ฅ ๊ฐ์ฒด
model = LinearRegression().fit(feature, target)
# RAM์ ์ฅ์ฐฉ๋จ, ์ค์ ๋ก๋ ํ๋๋์คํฌ์ ์ ์ฅํด์ ์ฌ์ฉํด์ผํจ
# ๋ฐ์ดํฐ ์์ธก, ๋์ 80 ์ค์ 36์ด๋ฉด ์น์ ์?
model.predict([[80, 36]]) # array([[78.90247916]])
np.round(model.predict([80, 36]])) # array([[79.]])
# ์ปดํจํฐ๋ฅผ ๋๊ฒ๋๋ฉด RAN์ ์๋ MODEL์ด ์ฃฝ๊ธฐ ๋๋ฌธ์ ๋ชจ๋ธ์ ํ๋๋์คํฌ์ ์ ์ฅํด์ค
# model > SSD or HDD ์ ์ฅ
# ๋ชจ๋ธ ๊ฐ์ฒด ์ ์ฅํ๋ ๋ฐฉ๋ฒ (๋ฉ๋ชจ๋ฆฌ > ์ ์ฅ์ฅ์น)
import pickle
# ram > ssd
with open('model.pkl', 'wb') as file:
pickle.dump(model, file) # model์ ์์ ์น์ ์์ธกํ๋ ์ธ๊ณต์ง๋ฅ ๋ชจ๋ธ
# ssd > ram
with open('model.pkl', 'rb') as file:
load_model = pickle.load(file)
np.round(load_model.predict([[80, 36]])) # array([[79.]])