네이버 크롤링은 매우 간단하다.

이 글에서는 영화를 검색했을 경우, 네티즌의 리뷰 갯수가 몇개나 등록되어 있는지를 크롤링하는 코드를 포스팅한다.

# 현재 내가 가지고 있는 영화의 타이틀을 저장함
full_title =np.array([train_and_test['title'].apply(lambda x : x.split(' '))]).reshape(-1, )

# requests, bs4가 없다면 설치해야 한다.
import requests
from bs4 import BeautifulSoup

# 네이버에서 영화를 검색할 시 공통적으로 생성되는 쿼리문은 아래와 같다
# 따라서 영화 이름과 url을 붙여준 리스트를 한번 더 생성해보자
full_url = list()
for title in full_title:
    url = 'https://search.naver.com/search.naver?sm=top_hty&fbm=1&ie=utf8&query=영화'
    for word in title:
        url += '+'
        url += word
    
    full_url.append(url)

# 이제 영화 리뷰 수, 즉 별점을 몇명이나 주었는지에 대한 정보를 담을 dataframe을 생성한다.
star_num_df = pd.DataFrame(columns=['title', 'star_num'])

# headers
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows; U; MSIE 9.0; WIndows NT 9.0; ko-KR))',
}

# 네이버에서는 우리가 찾을 값을 cont_p로 정의해두었다. 그에 맞춰 이름을 정의하자.
cont_p_list = list()

# main code
for i, (url, title) in enumerate(zip(full_url, train_and_test['title'])):
    print(i)
    response = requests.get(url, headers = headers)
    html = response.text
    
    soup = BeautifulSoup(html, 'lxml')
    
    # cont_p를 찾아준다.
    em = soup.find('em', {'class':'cont_p'})
    
    if(em is None):
        num_df.loc[i, 'title'] = title
        num_df.loc[i, 'star_num'] = 0
    else:
    	# 자신이 찾고 싶은 데이터에 맞게 찾아오면된다. 자세한건 soup.find를 검색해보자
        for em in soup.find('em', {'class':'cont_p'}):
            num_df.loc[i, 'title'] = title
            num_df.loc[i, 'star_num'] = em

지금 글부터는 자바스크립트 형태로 되어 있어 위의 코드로 찾을 수 없는 데이터를 찾으려고 한다.

어떻게 알 수 있냐면, 분명히 페이지 소스에서는 존재하는 데이터가 soup.find로 찾으려고 할때 None값이 리턴되는 경우가 생긴다면 의심해 볼 필요가 있다.

위의 코드는 해당 데이터가 자바스크립트 형태로 되어 있을 시, soup.find를 통하여 클래스를 찾을 수가 없다. 따라서 아래와 같이 코드를 변경해주어야 한다.

이번 예제는 네이버에서 영화를 검색했을 때, 영화의 하트 갯수를 찾을 것이다. (검색하면 쉽게 찾아볼 수 있음)

# 영화의 제목을 저장하자
full_title =np.array([train_and_test['title'].apply(lambda x : x.split(' '))]).reshape(-1, )

# 이부분까지도 위와 같다.
import requests
from bs4 import BeautifulSoup

full_url = list()
for title in full_title:
    url = 'https://search.naver.com/search.naver?sm=top_hty&fbm=1&ie=utf8&query='
    for word in title:
        url += '+'
        url += word
        
    url += '+영화'
    full_url.append(url)
    
# 우리가 원하는 데이터는 하트 갯수이다. 이를 저장할 dataframe을 생성하자
heart_num_df = pd.DataFrame(columns=['title', 'heart_num'])

# main code
# 여러가지 방법이 있겠지만 이 글에서는 크롬을 이용한다
from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager
import time

chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument('headless') # headless 모드를 했을 때 실행이 안된다. 일단 생략.

# driver = webdriver.Chrome(ChromeDriverManager().install())
driver = webdriver.Chrome(executable_path='/Users/johwiyong/.wdm/chromedriver/74.0.3729.6/mac64/chromedriver')

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows; U; MSIE 9.0; WIndows NT 9.0; ko-KR))',
}

# 네이버에서는 우리가 찾을 데이터를 u_cnt로 정의해두었다. 
u_cnt_list = list()

for i, (url, title) in enumerate(zip(full_url, train_and_test['title'])):
    print(i)
#     response = requests.get(url, headers = headers)
    driver.get(url)
    driver.implicitly_wait(10) # 작동하지 않는 것 같다.
    # 이만큼의 시간을 기다려주는 이유는 데이터가 불려오기 전에 다음 페이지로 넘어갈 경우
    # None을 return하는 경우가 발생하는 점을 방지
    time.sleep(3) 
    html = driver.page_source
    driver.implicitly_wait(10)
    
    # 여기서부터는 위와 비슷하다
    soup = BeautifulSoup(html, 'lxml')
    
#     print(soup.find_all('em'))
    u_cnt_list = soup.find_all('em', 'u_cnt _cnt')

    if(len(u_cnt_list) == 0):
        print(title)
        heart_num_df.loc[i, 'title'] = title
        heart_num_df.loc[i, 'heart_num'] = 0
    else:
        heart_num_df.loc[i, 'title'] = title
        em = soup.find_all('em', 'u_cnt _cnt')[0].get_text()
        heart_num_df.loc[i, 'heart_num'] = em
        
    print(i, em)

1. tensorflow api 다운로드

https://github.com/tensorflow/models

 

tensorflow/models

Models and examples built with TensorFlow. Contribute to tensorflow/models development by creating an account on GitHub.

github.com


2. 본인이 사용하기 편한 경로로 이동시키기


3. protoc이 안깔렸으면 설치가 되어 있어야 합니다. --> protoc을 통한 .py 파일 생성하기

models/research에서 다음을 입력합니다.

protoc object_detection/protos/*.proto --python_out=.

proto파일에 _pb2.py로 끝나는 여러 파일이 생성되었다면 성공입니다.


4.

models/research

에서 다음의 명령어를 실행합니다. 

python setup.py build

python setup.py install

5. 환경변수 설정

다음의 명령어를 실행합니다.

export PYTHONPATH=$PYTHONPATH:[path]:[path]/slim

(여기서 [path]는 models/research 경로를 넣어주면 됩니다.)

예를 들면, /Users/.../models/research

후에 source ~/.bash_profile 을 실행합니다.


6. 설치 확인하기

models/research에서 다음의 명령어를 실행하여 설치를 확인합니다.

python object_detection/builders/mode_builder_test.py

다음 이미지의 결과를 보았다면 성공.


7. .ipynb로 튜토리얼 실행해보기

object_detection경로에 들어가보면 있습니다.

protobuf 사용을 위한 설치


맥에는 apt-get이 없으므로, brew를 사용한다.(brew가 없다면 설치하고 와야함.)

1. https://github.com/google/protobuf/releases

 

protocolbuffers/protobuf

Protocol Buffers - Google's data interchange format - protocolbuffers/protobuf

github.com

위 사이트에서 mac 버전 protobuf파일을 깔고, 원하는 디렉토리에 압축을 푼다.

2. shell에서 해당 경로로 이동한 다음

./autogen.sh && ./configure && make   

를 실행한다.

3. 만약 2번이 되지 않는다면 

brew install autoconf && brew install automake

를 실행하여 필요한 모듈을 설치해주어야 한다.(경우에 따라 오래걸릴 수 있음)

4. 마지막으로 shell 에서 다음 4가지를 실행하여 설치를 확인한다.

--> make check
--> sudo make install
--> which protoc
--> protoc --version

 

protobuf 사용하기


1. .txt 파일에 다음 이미지와 같이 예제를 입력하고 person.proto로 확장자를 변경하여 저장한다.

 

2. 다시 shell로 돌아가서 해당경로로 이동한 다음, 

protoc -I=./ --python_out=./ ./person.proto

를 입력하면 경로에 .py파일이 생성된 것을 확인할 수 있다.

 

import하여 사용하면 끝.

 

이 방법을 사용하면 가벼운 맥북으로도 무거운 서버의 gpu를 사용할 수 있습니다.(gpu관련글은 아님.)--


1. config 파일 만들기

cmd에서 jupyter notebook --generate-config

를 사용하면 jupyter_notebook_config.py가 만들어집니다. 


2. key 획득하기

위의 sha~ 부분을 다음과 같이 붙여줍니다. c.Notebook이런건 찾으시면 다 있으니 cmd(ctrl)+f기능을 활용하세요


3. jupyter_config 에서 몇 가지 더 수정하기

위에서 했던 것처럼 전부 찾아서 아래와 같이 바꿔주시면 됩니다.

c.NotebookApp.ip = '*'

c.NotebookApp.password_required = True

c.NotebookApp.port = 원하는 포트번호(5554)

c.NotebookApp.open_browser = False


4. 포트 등록하기

iptables를 사용하여 포트를 등록하면 됩니다. 혹시 permission 에러가 뜬다면 sudo!

cmd에 

(sudo) iptables -I(i입니다) Input 1 -p tcp --dport 5554 -j ACCEPT

이렇게 해주면 등록이 끝났습니다.


5. 사용하기

먼저 쥬피터 노트북을 no-browser모드로 실행시켜놓아야 합니다. 

jupyter notebook --ip=server_ip --no-browser

로 켜놓고 맥북에서

server_ip:port로 실행시켜주면 성공!

 

 

가끔 이미지 픽셀에 대해 분석하고 싶을때가 있습니다.


그럴땐 히스토그램만 생각하면 됩니다.

matplotlib의 hist()함수와 cv2.calcHist()함수가 대표적입니다.

둘의 인자는 거의 비슷합니다. 


https://matplotlib.org/api/_as_gen/matplotlib.pyplot.hist.html

https://opencv-python.readthedocs.io/en/latest/doc/19.imageHistograms/imageHistograms.html

인자는 각 API를 참조하는게 좋습니다.


다음은 예제 코드입니다.

range는 어느 픽셀까지 보여줄지를 뜻하고,

bin은 특정 범위를 뜻합니다.

예를 들어 bin이 16이면 총 16개의 범위로 나눠져서 보여주게 됩니다.