brunch

You can make anything
by writing

C.S.Lewis

by CHAIBS Mar 19. 2018

크롤러 만들면서 어떤 삽질을 했나?

기록용


요약 


어뷰징을 방지하기 위해 네이버가 도입한 '클러스터링' 기술. 이를 악용해 기업의 이미지를 깎는 기사를 밀어내는 속칭 '클러스터링 밀어내기' 정황이 포착됨. 이것을 추적할 수 있는 크롤러를 기획했다.



우선 결과물인 코드는 ↑여기에 있다. 네이버는 여기에서 크롤링을 불허한다는 사실을 적어두고 있으니 참고. 다만 위의 크롤러는 클러스터링 밀어내기라는 여론 왜곡을 추적한다는 점에서 의미가 있고, 개인정보를 가져가는 종류는 아니며, 긁어가는 대상이 언론사의 기사(기사 내용 본문은 미포함)라는 점에서 괜찮지 않을까...? 싶긴 한데, 모르는 일이다. 예전에 회사에서 일했을 때 비슷한 작업을 한 적이 있는데, 그거는 딱히 문제 삼지 않았다. (정확히 말하면  긁는 거로 뭐라 하진 않았고, 내용으로만 이견을 제시함) 그때는 기자였고 지금은 아니니까 또 모를 일이지만??



긁어오려는 곳은 바로 여기. '클러스터'는 기사 한 덩어리를 의미한다. '클러스터링 밀어내기'는 뉴스 섹션 상단에 해당 기업에 대한 비판 기사가 있을 경우 우호적이거나 별 내용 없는 기사를 네이버에 송고해 상단의 비판적인 내용을 뉴스 섹션 상단에서 밀어내는 행위를 뜻한다. 이를 위해서 홍보를 담당하는 파트(혹은 대행사)에서는 돈 주고 기사 뭉텅이를 산다. 클러스터링도 언론사들의 어뷰징을 막아보고자 도입된 기술인데, 그 와중에 또 길을 찾아낸 거다. 이걸 뭐 대단하다고 해야 할지... 아무튼 검색 결과의 품질을 해치고, 여론 형성에도 왜곡으로 작용하는 짓임에는 분명하다. 그래서 트래커를 만들었다.


트래커의 원리는 이렇다.


네이버 접속

네이버 검색창에서 팔로업할 키워드 입력 (ex. 삼성)

검색 버튼 클릭

검색 결과에서 '뉴스 더 보기 클릭'

결과로 나온 첫 페이지 뉴스 데이터 수집(기사 타이틀, 링크, 송고한 언론사, 크롤링 시점, 크롤링 시점 기준 기사 송고 시간 - n 분 전 / n 시간 전 - , 클러스터 타이틀 / 관련기사 여부 표시)

데이터 파일(csv)로 익스포트

위의 과정을 지정한 시간 간격, 횟수로 실행


이렇게 하면 시간마다 캡처를 뜨거나 기록하지 않아도 자동으로 클러스터의 변동을 기록함으로써 문제가 되는 행위를 확인하고, 증거로 쓸 수 있다. 어느 언론사가 클러스터 밀어내기에 동조했는지, 그걸 위해 얼마나 쓰레기 같은 기사들을 네이버에 쏴 댔는지 알 수 있는 셈. 사실 네이버 뉴스 클러스터는 '검색 결과 자동고침'이라는 기능을 제공하기 때문에 검색창에서 '시작'버튼 눌러두고 화면 녹화하면 빼박 증거로 쓸 수 있다. 하지만 그건 데이터로 쓸 수가 없으니까 ~_~ 원래 목표는 이렇게 만들어진 데이터 파일을 바탕으로 클러스터 변동을 시각적으로 보여주는 그래프까지(더 나아가서 웹 서비스까지...?) 만드는 건데, 그거는 귀찮아서 아직 안 했다.


파이썬으로 만들었고, 크롤러에 많이 쓰이는 셀레늄을 사용했다. 셀레늄은 사람이 하는 것처럼 직접 요소를 선택하는 것 같은 액션을 주기 때문에 막혀있는 것도 긁을 수 있다는 장점이 있다. 단점은 직접 액션을 취해야 하기 때문에 느리다는 것? 잘 몰라서 장담은 못한다. 비슷하게는 리퀘스트를 쓸 수도 있다. 셀레늄과 리퀘스트를 조합할 수도 있고. 그 외에 HTML 등에서 원하는 데이터를 뽑아내는데 유용한 뷰티풀 수프를 썼고, 정규표현식(re), 타이머 설정(threading), 데이터 파일 익스포트(csv), 시간 처리(datetime)에 쓰이는 패키지를 사용했다.



가장 삽질한 부분


제작에 총 10일 남짓 들었다. 코드가 백 줄도 안 되는 단순 크롤러인데 열흘 넘게 든 건 순전히 내가 잘 모르기 때문이고, 아는 사람이라면 한두 시간에 짠다. 실제로 그 시간 안에 짜는 것도 세 번이나 봤고. 내가 오래 걸렸던 건 1. 요청한 결과물의 type을 전혀 생각하지 않아서 2. 웹문서의 구조 이해와 적용에 어려움을 겪어서다. 나머지는 수월하게 했다. 구글과 스택오버플로우 덕을 많이 봤다.


첫 번째 문제는 이런 거였다. 집합(편의상 집합이라고 표현)에서 부분집합을 만들어야 하는 문제다. 네이버 뉴스 클러스터는 기사 틀, 기사, 링크, 요약내용, 시간, 인링크, 아웃링크, 송고 매체, 이미지 등등으로 짜여있다. 기사 틀도 전체 기사 틀, 클러스터 기사 틀, 관련기사 틀 등이 있다. 다양한 집합으로 분류 가능한 요소들이 규칙적으로 섞여있다. 내가 말을 해놓고도 무슨 말인지 모르겠네... 아무튼 여기서 내가 원하는 요소를 뽑아내려면 이 규칙에 맞게 집합을 전체 집합에서 분리해 내야 한다. 그래야 내가 필요한 데이터를 규칙적으로 가지고 올 수 있다.


이를 위해서는 '집합'을 뽑아오는 명령을 내려야 한다. 그다음에 또 '하위 집합'을 뽑아오는 명령을 규칙적으로 넣고, 또 그 아래의 요소를 차례로 긁어오게 할 수 있다. 그런데 내가 불러온 요소가 집합이 아니었기 때문에 하위 집합을 규칙적으로 긁어낼 수가 없었다. 애초에 대상이 집합이 아니었기 때문에 부분집합을 만드는 명령이 먹힐 리가 없다. 왜 이런 문제가 생겼냐? 나 같은 애들이 보기에는 집합이든 아니든 눈으로 보기엔 비슷하게 보여서다. 둘 다 태그의 뭉치로 보였다. 나는 그게 다른 거라는 걸 체감하지 못해서, '비슷하게 생겼는데 왜 여기서는 추출이 안 되는 거지 ㅠㅠ' 생각하며 시간을 진짜 후루룩 말아먹었다.

보기엔 집합이든 아니든 이렇게 보이지만
실제로 확인해보면 타입이 다르다


그걸  만들 때 '집합'으로 만든 것에서는 부분 집합을 만들 수 있지만, 아닌데 집합을 만들어내라고 하면 컴퓨터는 '안 되는걸 왜 자꾸 시키냐' 되묻는다. 아 근데 쓰면서도 조심스럽다. 잘 모르는 내가 판단하기에 그랬다는 거고요. 아무튼. 눈으로 보면 비슷하니까 잘 모르는 나는 여기서 계속 삽질을 반복하며 시간을 썼다. 여기서 근본적인 잘못이 있다는 걸 깨달은 게 대략 9일째다. 그때에서야 타입이 다른 것에 기인한 문제가 아닌가 하는 생각이 들었다. 아는 분들이 본다면 기가 막히는 실수일 듯. 물론 그 사이에 시답잖은 몇 가지를 공부하긴 했지만. 예전에 수능 공부할 때 수학 4점짜리 모르겠는 걸 답지 안 보고 풀 때까지 그것만 쳐다보곤 했었는데, 그런 느낌이 들었다. 그때보단 좀 더 막막했다. 그때는 내가 수학을 모르는 게 아니었지만, 지금의 나는 파이썬을 잘 모르자너..


2번째는 웹문서의 구조에 대한 이해와 적용에서의 문제. 내가 원하는 정보를 얻기 위해서는 여러 가지 태그를 탐색하면서 내려가야 한다. 예컨대, OO고등학교에서 사물함에 든 교과서를 몽땅 가지고 온다고 가정하자. 학년을 돌고, 반을 돌고, 번호마다의 사물함을 몽땅 따서 사물함마다 몇 권이 들어있을지 모르는 책을 가지고 와야 한다. 그런데 아차! 학년마다 몇 반까지 있는지가 다 다르고, 반마다 몇 번까지 있는지도 다 다르며 사물함마다 든 책의 개수도 다 다르다.


'이게 뭐가 어렵냐 그냥 순서대로 다 까 보면 되지' 싶은데 나는 그렇게 코드를 짤 자신이 없어서 '우선 각 학년 1반의 세트를 만들고, 각 학년 1반의 1번 세트를 또 만들어야지' 생각했다. 그냥 봐도 이게 무슨 멍청한 짓인가 싶은데, 그게 더 쉽게 느껴졌다. 이것도 그 감각을 명확하게 설명하기 어렵네, 그니까 나는 운동장에서 '야 각 학년 1반 1번 사물함에서 책 다 들고 나와'라고 소리 지르는 방식을 택했다는 거다.


내가 해야 하는 건 교과서를 걷을 친구가 1학년 1반 1번부터 끝 번호까지 돌고, 그다음 반으로 넘어가고, 1학년 반을 다 돌면 2학년, 3학년으로 알아서 넘어가게 시키는 일이었다. 이걸 코드로 짜려면 대략 이렇게 짜야했다.


각 학년 별로 다 돌아

    각 학년마다 모든 반을 돌아

        각 반마다 1번부터 끝번까지 돌아


예시로 보니까 쉬운데, 짜려니까 영 어려웠다...ㅜㅜ for 루프나 if/else 구문을 쓸 줄 모르는 건 아닌데, 중복으로 적용해서 긁어오는 건 해 본 적이 없어서 손을 아예 못 댔달까? 어떻게 짠 거냐면... 대단한 깨달음이 있던 건 아니고, '괄호 안에 괄호를 차근차근 친다'는 굉장히 막연한 감각이었다. 이것도 뭐 설명을 못하겠네.... 글은 오지게 길게 쓰면서 제대로 설명하는 게 없다. 이걸 못 짜서 '어떻게 운동장에서 모두를 차례대로 불러낼 수 있을까'고민하면서 이거 써보고, 저거 써보고 몽땅 실패하고 그랬다. 트래커의 구조는 대충 이렇다.


클러스터 기사 데이터들을 가져오고

    관련기사가 달려있는지 확인하고

        달려있으면 관련기사 내용을 긁어오고

     관련기사가 없으면 다음 클러스터 가지고 와라


여기까지 짜면 한 페이지를 온전히 긁어올 수 있다. 뒤는 쉽다. 현재의 시간을 입력하는 기능을 넣고, 루프의 결과물은 csv파일을 열어 쓰는 작업을 추가했다. 마지막으로 전체를 함수로 만들고 지정한 시간 간격 - 지정한 횟수로 반복하게 만드는 기능을 더했다. 그렇게 끗.




 



매거진의 이전글 [D3.js] 투수TOP20 vs 타자TOP30

작품 선택

키워드 선택 0 / 3 0

댓글여부

afliean
브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari