94년생 스피노자

[코드 블록] 캡챠 우회해서 웹 스크래핑/ 크롤링하기 본문

철기시대 석공 벗어나기/코딩 조각

[코드 블록] 캡챠 우회해서 웹 스크래핑/ 크롤링하기

94년생 스피노자 2021. 5. 9. 12:48
728x90

오늘 크롤링을 하다가 캡챠로 인한 오류를 처음으로 경험했다.

 

 

0. 문제 상황

 

onlinelibrary.wiley.com/journal/10970266

 

Strategic Management Journal

Click on the title to browse this journal

onlinelibrary.wiley.com

위 논문 저널에서 경영학 논문의 키워드를 스크래핑하여 추세를 살펴보려고 했다.

그래서 아래와 같은 코드를 작성해서 돌렸다.

import requests
from bs4 import BeautifulSoup

b_url = "https://onlinelibrary.wiley.com/action/doSearch?SeriesKey=10970266&content=articlesChapters&countTerms=true&pageSize=2000&target=default&"

ay = "AfterYear="
by = "&BeforeYear="
a_year = 2021
b_year = 2021
period = ay + str(a_year) + by + str(b_year)

url = b_url + period
print(url)

# Soup 만들기
r = requests.get(url)
soup = BeautifulSoup(r.text, 'lxml')

# 태그 접근하기
link = soup.get("li")
print(link)

그랬더니 None값이 나오는 것이다.

페이지 소스에서 태그를 확인했기에 태그 명칭의 문제는 아니다.

그래서 크롤링을 위해 만들어 둔 soup을 확인했다.

<!DOCTYPE html>
<!--[if lt IE 7]> <html class="no-js ie6 oldie" lang="en-US"> <![endif]--><!--[if IE 7]>    <html class="no-js ie7 oldie" lang="en-US"> <![endif]--><!--[if IE 8]>    <html class="no-js ie8 oldie" lang="en-US"> <![endif]--><!--[if gt IE 8]><!--><html class="no-js" lang="en-US"> <!--<![endif]-->
<head>
<title>Attention Required! | Cloudflare</title>
<meta id="captcha-bypass" name="captcha-bypass"/>
<meta charset="utf-8"/>

확인해보니 페이지 소스와는 다른 내용들이 담겨 있었다.

위에 첨부한 부분은 상단의 일부분이다.

 

읽어보면 Cloudflare 관련 주의가 뜬 것을 알 수 있다.

좀 더 구체적인 문제는 captcha-bypass인 것 같다.

 

 

1. 문제 원인

 

이러한 문제는 사이트에서 스크래핑을 막기 때문이다.

스크래핑 자체를 막는 것은 아니다.

비정상적인 속도의 서버 접근을 막는 것이다.

 

이를 막지 않으면 서버는 쉽게 다운될 수 있다.

여러 컴퓨터에서 접근을 어마무지하게 요청하면 서버는 무너진다.

 

 

2. 문제 해결

 

cloudscraper 패키지를 설치하면 문제가 해결된다.

해당 패키지는 cloudflare의 캡챠를 우회하게 해준다.

 

Colab 혹은 Jupyter Notebook 코드블록에다가

pip install cloudscraper

위 한 줄을 치고 실행시키면 설치가 된다.

 

공식 사이트는 아래 링크를 타고 가면 된다.

pypi.org/project/cloudscraper/

 

cloudscraper

A Python module to bypass Cloudflare's anti-bot page.

pypi.org

이제 캡챠 에러 없이 스크래핑이 가능할 것이다.

 

 

3. 최종 코드

import requests
from bs4 import BeautifulSoup

!pip install cfscrape
import cfscrape

from google.colab import files
import json

b_url = "https://onlinelibrary.wiley.com/action/doSearch?SeriesKey=10970266&content=articlesChapters&countTerms=true&pageSize=2000&target=default&"

# 3년 간격
ay = "AfterYear="
by = "&BeforeYear="
b_year = 1982
a_year = b_year-2

period = ay+str(a_year)+by+str(b_year)
range = str(a_year)+"-"+str(b_year)
url = b_url+period

keywords_dict = {}
keywords_dict[range] = {}

# Soup 만들기
scraper = cfscrape.create_scraper()
r = scraper.get(url)
soup = BeautifulSoup(r.text, 'lxml')

# 태그 접근하기
link_class = soup.find_all(attrs={'class':'hlFld-Title'})

# Link 추출하기
link = []

for i in link_class:
  res = i.find("a")["href"]
  link.append(res)

# 논문 Keyword 따기
base_url = 'https://onlinelibrary.wiley.com'

keywords = []

for i in link:
  url = base_url+str(i)
  r = scraper.get(url)
  soup = BeautifulSoup(r.text, 'lxml')
  link_class = soup.find_all(attrs={'name':'citation_keywords'})
  for name in link_class:
    key_word = name["content"]
    keywords.append(key_word)
    
for word in keywords:
  year_dict = keywords_dict[range]
  try:
    year_dict[word] += 1
  except KeyError:
    year_dict[word] = 1
  keywords_dict[range].update(year_dict)

# Text 파일에 기록하고 저장
title = "논문 키워드 추출_"+str(a_year)+"_"+str(b_year)+".txt"
f = open(title, "w", newline='')
keywords_string = json.dumps(keywords_dict)

f.write(keywords_string)
f.close

files.download(title)

 

 

모두 행복하길

 

-끝-

728x90