https://finance.naver.com/research/company_list.naver
import requests
import pandas as pd
from bs4 import BeautifulSoup
# 1. URL
url='https://finance.naver.com/research/company_list.naver?&page=1'
# 2. request(URL) > response(HTML)
response = requests.get(url) #예시 페이지는 get방식으로 가져옴
response
HTML > BeautifulSoup > css-selector > DataFrame
4-1) HTML -> BeautifulSoup
# 첫번째 인자: response의 body를 텍스트로 전달
# 두번째 인자: "html"로 분석한다는 것을 명시
dom = BeautifulSoup(response.content,'html.parser')
type(dom) # select(), select_one()
4-2) BeautifulSoup -> css-selector
주의 : 개발자 도구의 copy - html selector을 너무 믿지 말자..(실제 소스와 개발자 도구 html의 코드가 다를 수 있다)
# html selector 오류 코드
# selector = '#contentarea_left > div.box_type_m > table.type_1 > tbody > tr:nth-child(3)'
selector = 'table.type_1 > tr'
elements = dom.select(selector)
len(elements)
필요 태그 (tr 아래의 6개의 td 선택)
element = elements[2]
tag = element.select('td')
len(tag), tag
필요 엘리먼트 수집
data = {}
data['stock_name'] = tag[0].select_one('a').text #0번째 td태그 중 'a' 태그 선택
data['stock_link'] = tag[0].select_one('a').get('href') #해당 속성값 가져옴
data['title'] = tag[1].select_one('a').text
data['titme_link'] =tag[1].select_one('a').get('href')
data['writer'] = tag[2].text
data['pdf_link'] = tag[3].select_one('a').get('href')
data['date'] = tag[4].text
data['pv'] = tag[5].text
data
반복문을 이용하여 데이터 수집
tag != 6 이면 필요하지 않은 태그이기 때문에 제외한다.
# enumerate
rows = []
for idx, element in enumerate(elements):
tag = element.select('td')
print(idx, len(tag))
if len(tag) == 6:
data = {}
data['stock_name'] = tag[0].select_one('a').text #0번째 td태그 중 'a' 태그 선택
data['stock_link'] = tag[0].select_one('a').get('href') #해당 속성값 가져옴
data['title'] = tag[1].select_one('a').text
data['titme_link'] =tag[1].select_one('a').get('href')
data['writer'] = tag[2].text
data['pdf_link'] = tag[3].select_one('a').get('href')
data['date'] = tag[4].text
data['pv'] = tag[5].text
rows.append(data)
4-3) css-selector > DataFrame
df = pd.DataFrame(rows)
df.tail(2)
https://www.selenium.dev
Selenium 4버전 이상에서는 크롬 드라이버를 따로 설치하지 않아도 된다
#!pip install selenium
#!pip install webdriver_manager
import pandas as pd
from selenium import webdriver
from selenium.webdriver.common.by import By
# 직접 드라이버를 다운 받아서 설정
driver = webdriver.Chrome()
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
# 자동으로 본인 환경에 맞는 드라이버를 다운 받아서 설정
service = Service(ChromeDriverManager().install())
driver = webdriver.Chrome(service=service)
# 페이지 이동
driver.get('https://daum.net')
# 브라우져 사이즈 조절
driver.set_window_size(200, 600)
# 자바스크립트 코드 실행
driver.execute_script('alert("hello selenium!");')
# alert 종료
alert = driver.switch_to.alert
alert.accept()
# 검색어 입력
driver.find_element(By.CSS_SELECTOR, '#q').send_keys('selenium')
By.CSS_SELECTOR
# 검색버튼 클릭
driver.find_element(By.CSS_SELECTOR, '.btn_ksearch').click()
# 브라우져 종료 : 자원(RAM)반환
driver.quit()
!pip install scrapy
import scrapy
import requests
from scrapy.http import TextResponse
//*[@id="container"]/div[2]/ul/li[1]
//
: 최상위 엘리먼트*
: 모든 하위 엘리먼트 : css selector의 한칸띄우기와 같다.[@id="value"]
: 속성값 선택/
: 한단계 하위 엘리먼트 : css selector의 >와 같다.[n]
: nth-child(n)# !pip install scrapy
import scrapy, requests
from scrapy.http import TextResponse
!scrapy startproject news
!tree news
scrapy structure
- items : 데이터의 모양 정의
- middewares : 수집할때 header 정보와 같은 내용을 설정
- pipelines : 데이터를 수집한 후에 코드를 실행
- settings : robots.txt 규칙, 크롤링 시간 텀등을 설정
- spiders : 크롤링 절차를 정의
import scrapy, requests
from scrapy.http import TextResponse
url='https://news.daum.net/'
response = requests.get(url)
response = TextResponse(response.url, body=response.text, encoding='utf-8')
response
selector = '/html/body/div[2]/main/section/div/div[1]/div[1]/ul/li/div/div/strong/a/@href'
links = response.xpath(selector).extract()
len(links), links[:3]
link=links[0]
response = requests.get(link)
response = TextResponse(response.url, body=response.text, encoding='utf-8')
response
4-2) 기사 제목 가져오기
# 기사 제목 가져오기
title = response.xpath('//*[@id="mArticle"]/div[1]/h3/text()')[0].extract()
title
xpath
- html element 선택하는 방법
- scrapy 에서는 기본적으로 xpath를 사용
- syntax
- // : 최상위 엘리먼트
- * : 모든 하위 엘리먼트 : css selector의 한칸띄우기와 같다.
- [@id="value"] : 속성값 선택
- / : 한단계 하위 엘리먼트 : css selector의 >와 같다.
- [n] : nth-child(n)
# %load news/news/items.py
# Define here the models for your scraped items
#
# See documentation in:
# https://docs.scrapy.org/en/latest/topics/items.html
import scrapy
class NewsItem(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
pass
오버라이딩
%%writefile news/news/items.py
import scrapy
class NewsItem(scrapy.Item):
title = scrapy.Field()
link = scrapy.Field()
%%writefile news/news/spiders/spider.py
# 모듈 임포트
import scrapy
from news.items import NewsItem
#스파이더 클래스 정의
class NewsSpider(scrapy.Spider):
name = 'news' #스파이더의 이름
allow_domain = ['daum.net'] #크롤링을 허용할 도메인
start_urls = ['https://news.daum.net'] #크롤링을 시작할 URL을 정의
# 초기 응답을 처리 메서드
def parse(self, response):
#Path 표현식으로, 뉴스 기사 링크를 선택
selector = '/html/body/div[2]/main/section/div/div[1]/div[1]/ul/li/div/div/strong/a/@href'
#선택된 링크들을 추출
links = response.xpath(selector).extract()
#각 링크에 대해 scrapy.Request를 생성하고, parse_content 콜백 메서드를 호출
for link in links:
yield scrapy.Request(link, callback=self.parse_content)
#각 뉴스 기사 페이지의 내용을 처리
def parse_content(self, response):
item = NewsItem()
item['link'] = response.url
item['title'] = response.xpath('//*[@id="mArticle"]/div[1]/h3/text()')[0].extract()
yield item #item 객체를 반환
def generator_example():
yield 1
yield 2
yield 3
gen = generator_example()
print(next(gen)) # 1
print(next(gen)) # 2
print(next(gen)) # 3