

tags = soup.select("#_per") # #은 id를 사용한다는 의미
print(tags) # 배열형태. 결과가 괄호로 되어있음을 확인 [<em>11</em> , <em>12</em>]
tag = tags[0] # tags의 첫번째 값을 받는다.
print(tag.text) # 태그의 값
#은 id를 사용한다는 뜻이다.
크롬에서 원하는 곳 검사

import requests
from bs4 import BeautifulSoup
url = "https://finance.naver.com/item/main.naver?code=000660"
html = requests.get(url).text
soup = BeautifulSoup(html, "html5lib")
# 직접 만든 CSS 셀렉터
tags = soup.select(".lwidth tbody .strong td em") # .은 class를 불러온다. select함수 차례대로 분석해보면, lwidth클래스 안에 tbody 안에 strong클래스 안에 td 안에 em으로 강조된 데이터
# 크롬 브라우저가 지원하는 CSS 셀렉터
# tags = soup.select("#tab_con1 > div:nth-of-type(2) > table > tbody > tr.strong > td > em")
# 그대로 따라가면 된다.
tag = tags[0] # 원하는 값만을 파싱했기 때문에 0번만 인덱싱
print(tag.text) # 50.24%


전체 제목 가져오기
import requests
from bs4 import BeautifulSoup as bs
page = requests.get("https://library.gabia.com/") # scrap
# requests.get() : 함수를 통해 url의 html가져옴(페이지 가져옴)
soup = bs(page.text, "html.parser") # scrap conversion
# page 에서 데이터를 유니코드형태로 받음 (text)
# html에 특정되어 있는 parser을 사용해 스크랩
# 응답 받은 내용을 유니코드 형태로 변환하여 soup(변수)에 할당
# soup # 실행하면 html이 쭉 들어와 있음
elements = soup.select('div.esg-entry-content a > span') # parsing
# 페이지에서 확인한 결과 div.esg-entry-content는 여러개가 있다
# 여러 div.esg-entry-content 중 a 를 찾을 수 있다.
# a안에서 span은 여러개 있다. 따라서 원하는 요소를 딱 집어서 가져옴
# 검색해보면 요소들이 모두 배열(array)형태이다.
elements

-> span에 해당하는 데이터를 모두가져왔다.
살펴보면 우리가 필요한 것은 텍스트 데이터이므로 .text 활용
for index, element in enumerate(elements, 1): # enumerate 배열의 인덱스와 값을 가져옴
print("{} 번째 게시글의 제목: {}".format(index, element.text))
# 원하는 인덱스(몇번째)와 제목을 모두 가져오는 결과

-> enumerate 를 이용하여 인덱스 1부터 끝까지 넣어주고 해당하는 인덱스와 elements요소 매칭
*참고 : enumerate(데이터, 인덱스 시작값)
import requests
from bs4 import BeautifulSoup as bs
page = requests.get("https://library.gabia.com/")
soup = bs(page.text, "html.parser")
elements = soup.select('div.esg-entry-content a.eg-grant-element-0')
# div.esg-entry-content에서 a태그의eg-grant-element-0를 배열형태로 불러옴
elements

-> 속성을 살펴보면, class, href, target이 있다. 여기서 href에 링크가 적혀있는 것을 볼 수 있다. 따라서 이를 고려하면 아래와 같다.
for index, element in enumerate(elements, 1):
print("{} 번째 게시글: {}, {}".format(
index, element.text, element.attrs['href']))
# a anchor 태그이 있는 attribute(속성은 추가 정보를 제공하는 역할) 중 herf 값을 가져온다.

-> 1부터 시작한 인덱스, 텍스트, 링크가 나온것을 알 수 있다
웹 스크래핑은 아주 쉬워서 더 배울 필요는 없어 보인다.

import requests
from bs4 import BeautifulSoup as bs
import pandas as pd
page = requests.get("https://library.gabia.com/")
soup = bs(page.text, "html.parser")
elements = soup.select('div.esg-entry-content a.eg-grant-element-0')
# elements
titles = [] # 열로 지정할 빈 리스트 생성
links = [] # 열로 지정할 빈 리스트 생성
for index, element in enumerate(elements, 1):
titles.append(element.text)
links.append(element.attrs['href'])
# 판다스 데이터 프레임으로 Excel로 저장하는 방법
df = pd.DataFrame()
df['titles'] = titles
df['links'] = links
df.to_excel('./library_gabia.xlsx', sheet_name='Sheet1')
-> 엑셀 파일 생성 완료
다 아는거라 매우 쉽다

-> version은 노드

흠.. 보통 필요한 경로를 복사해서 붙여넣는 정도니깐 딱히 암기할 필요 없는 듯하다.
아님 GPT에 물어보면 그때 그때 쉽게 알 수 있는듯?
혹시 코딩 테스트에 나올지도 모르니깐 코태연습할때 잘 봐두자
!apt install chromium-chromedriver # 크롬을 사용하므로 설치
!cp /usr/lib/chromium-browser/chromedriver /usr/bin # 구글 드라이버를 사용하고 있기에 드라이버에 설치된 패키지를 user bin으로 복사하는 작업
!pip install selenium
apt: APT(어드밴스트 패키징 툴,Advanced Packaging Tool)은 우분투(Ubuntu)를 포함안 데비안(Debian)계열의 리눅스에서 쓰이는 팩키지 관리 명령어 도구
cp:복사하기 명령어
pip: 파이썬으로 작성된 패키지 소프트웨어를 설치하거나 관리하는 패키지 관리 시스템
from selenium import webdriver #웹드라이버 불러오기(import). 셀레니움에서 가장 많이 사용하는 패키지
options = webdriver.ChromeOptions() # 크롬옵션 객체 생성
options.add_argument('-headless') # virtual randering
options.add_argument('-no-sandbox') # Bypass OS security model
options.add_argument('-disable-dev-shm-usage') # overcome limited resource problems
from selenium.webdriver.common.by import By
크롬 옵션 설명
- 브라우저(크롬 등)는 기본적으로 창을 사용. 그 후 HTML과 CSS를 사용해 GUI(Graphic User Interface)를 화면에 표시
- headless란?
'창이 없는'과 같다고 해석
'화면' 자체가 존재하지 않는 경우, 예: 우분투(Ubuntu) 서버, 일반적인 방식으로는 크롬 사용이 불가능
이때, headless 모드를 사용
'창'으로 띄우지 않고 대신 화면을 그려주는 작업(렌더링)을 가상으로 진행- sandbox란?
외부로부터 들어온 프로그램이 보호된 영역에서 동작해 시스템이 부정하게 조작되는 것을 막는 보안 형태- -no-sandbox: 이 보안을 해재시키는 옵션
- disable-dev-shm-usage란?
한정된 자원의 셋팅을 해재시키는 옵션- selenium.webdriver.common.by의 By란
'class name', 'id' 혹은 'name'등 어떤 종류의 로케이터(locator)를 사용할 것인지 지정
실습에서는 XPATH를 사용
wd = webdriver.Chrome(options=options)
wd.get("https://www.amazon.com/Dyson-V10-Allergy-Cordless-Cleaner/dp/B095LD5SWQ/")
get('페이지')함수를 사용하여 원하는 페이지를 가져옴
find_element(by=방법, value=값) 함수
- 제공된 로케이터와 일치하는 HTML 코드의 첫 번째 요소에 대한 참조를 가지고 옴.
하이퍼 텍스트 마크업 언어(영어: Hyper Text Markup Language, HTML, 문화어: 초본문표식달기언어, 하이퍼본문표식달기언어)는 웹 페이지 표시를 위해 개발된 마크업 언어
웹 브라우저와 같은 HTML 처리 장치의 행동에 영향을 주는 자바스크립트, 본문과 그 밖의 항목의 외관과 배치를 정의하는 CSS 같은 스크립트를 포함
웹을 생성하고 관리하는 마크업 언어
보통 형태는 아래와 같다.
<html>
<head>
<title>Hello HTML</title>
</head>
<body>
<p>Hello World!</p>
</body>
</html>
import requests
from bs4 import BeautifulSoup as bs
page = requests.get("http://movie.naver.com/movie/sdb/rank/rmovie.nhn")
soup = bs(page.text, "html.parser")
pkg_list = soup.findAll("div", "tit3") # css class가 tit3인 모든 div
print(pkg_list)
-> 결과로 나온 것 중 하나는 다음과 같다.

find(name, attrs, recursive, string, *kwargs)
- name: 찾고자 하는 태그 이름입니다.
- attrs: 속성과 해당 값으로 요소를 필터링할 수 있습니다.
- recursive: 기본적으로 True로 설정되며, 하위 요소까지 재귀적으로 검색합니다
- string: 태그의 텍스트를 기반으로 요소를 찾습니다.
findAll(name, attrs, recursive, string, limit, **kwargs)

# crawler.py에 저장
import logging
from urllib.parse import urljoin
import requests
from bs4 import BeautifulSoup
logging.basicConfig(
format='%(asctime)s %(levelname)s:%(message)s',
level=logging.INFO) # 로그(로깅) 메세지를 표시
class Crawler:
def __init__(self, urls=[]):
self.visited_urls = [] #이미 처리한(visited) URL 리스트
self.urls_to_visit = urls #처리해야할 URL 리스트
def download_url(self, url):
return requests.get(url).text
def get_linked_urls(self, url, html):
soup = BeautifulSoup(html, 'html.parser')
for link in soup.find_all('a'): # a 태크를 모두 찾는다
path = link.get('href') # href를 골라낸다
if path and path.startswith('/'):
path = urljoin(url, path)
yield path
def add_url_to_visit(self, url): # url를 add한다
if url not in self.visited_urls and url not in self.urls_to_visit:
self.urls_to_visit.append(url)
def crawl(self, url): # page의 모든 링크를 리스트에 저장한다
html = self.download_url(url)
for url in self.get_linked_urls(url, html):
self.add_url_to_visit(url)
def run(self): # 크롤링 시작
while self.urls_to_visit:
url = self.urls_to_visit.pop(0)
logging.info(f'Crawling: {url}')
try:
self.crawl(url)
except Exception:
logging.exception(f'Failed to crawl: {url}')
finally:
self.visited_urls.append(url)
if __name__ == '__main__':
Crawler(urls=['http://movie.naver.com/movie/sdb/rank/rmovie.nhn']).run()
-> 코드를 파이썬 파일로 저장 후 실행해줘야한다.
!python crawler.py
!pip install Scrapy # 인스톨 scrapy
!scrapy startproject tutorial
scrapy 설치 후 폴더 생성(tutorial 임의로 파일명 정할 수 있다)

import scrapy
class QuotesSpider(scrapy.Spider):
name = "quotes" # 실행할때 사용하는 이름
def start_requests(self):
urls = [
'https://quotes.toscrape.com/page/1/',
'https://quotes.toscrape.com/page/2/'
]
for url in urls:
yield scrapy.Request(url=url, callback=self.parse)
def parse(self, response): # 파일로 만들어내는 기능
page = response.url.split("/")[-2]
filename = f'quotes-{page}.html'
with open(filename, 'wb') as f:
f.write(response.body)
self.log(f'Saved file {filename}')
-> 여기서 https://quotes.toscrape.com/page/1/는 임의로 만들어진사이트
import os
# working 디렉토리(directory)로 이동(change)
os.chdir('/content/tutorial/tutorial/spiders')
!scrapy crawl quotes
-> 현재의 폴더 말고 다른 공간에서 파일을 실행시키려면 os 가 필요하다.
os의 체인지디렉토리 함수(chdir())를 이용하여 실행한다.