beautiful Soup, PhantomJS 사용한 javacript web scraping
환경 : windows 8 64bit, python 2.7.5 64bit, pycharm 3.4
참고 사이트 :
http://stackoverflow.com/questions/814757/headless-internet-browser
http://coreapython.hosting.paran.com/etc/beautifulsoup4.html --> beautiful Soup 4 한글문서
http://www.crummy.com/software/BeautifulSoup/bs4/doc/# --> beautiful Soup 4 영어문서
http://phantomjs.org/quick-start.html ---> PhantomJS quick start!
<< 미션 >>
Pubmed 사이트에서 검색한 논문의 인용횟수 구하기...
< 분석 >
1. chrome 으로 pubmed 에서 찾고자 하는 논문을 검색한다.
ex) http://www.ncbi.nlm.nih.gov/pubmed/17708774
---> 화면 우측 하단에 있는 Cited by 62 PubMed Central articles 부분의 정보를 가져오면 됨!
2. 찾은 논문 페이지에서 F12 눌러서 '개발자 도구' 열어서, html 소스 분석하기.
---> id 는 유일하므로 <div id="disc_col"> 을 먼저 찾고,
-> class 는 여러개 가능하므로 <div class="portlet_title"> 를 모두 찾아서,
-> 하위의 <h3> , 또 그 하위의 <span> 까지 찾아들어간후,
-> 'Cited by' 문자가 있으면 정규식으로 62 추출하자!!!
* 준비 : beautiful Soup 4 설치하기
< 1차 시도 >
# -*- coding: utf-8 -*-
from bs4 import BeautifulSoup
import urllib
urlstr = 'http://www.ncbi.nlm.nih.gov/pubmed/23256168'
f = urllib.urlopen(urlstr)
tt = f.read()
pp = BeautifulSoup(tt)
# pp 내용중에서, div tag 이면서 id = 'disc_col' 인 element를 list 로 가져온다
tmp = pp.find_all('div', attrs={'id':'disc_col'})[0]
print tmp.prettify()
url2 = tmp.a.get('href')
url2 = 'http://www.ncbi.nlm.nih.gov/' + url2
print '------------------------------------------- \n'
print url2
f2 = urllib.urlopen(url2)
tt2 = f2.read()
pp = BeautifulSoup(tt2)
print '------------------------------------------- \n'
print pp.prettify()
-- 출력 결과 --
*** 예상과는 다른 결과 나옴!
개발자 도구에서 <div id="disc_col"> 을 찾으면 다음을 쉽게 진행할수 있으리라 생각했으나,
href 에 새로운 url 이 나오고, 새로운 url 을 추적하였으나, javascript 에 연결되어 있고 원하는 결과 안보임 !!!
====> 새로운 해결책 필요!!!
javascript를 실행해서 우리가 원하는 결과를 가져올수 있는 뭔가가 필요하다....
그래서.. PhantomJS 찾음. (다른 도구 사용하고 싶으면 참고사이트를 참고하시라!)
<< PhantomJS 사용법 >>
1. http://phantomjs.org/download.html 에서 zip 파일 다운로드함.
2. zip 파일 압축풀면. phantomjs.exe 단독 실행 파일 존재함. (추가 설치 작업 필요없다.)
3. javascript 를 포함하고있는 목표 url 을, 분석하여 html로 변환하여, 로컬에 저장한다.
-> 이를 위해 js 파일을 만든다. (test.js)
-> phantomjs.exe 로 위에서 만든 js 파일(test.js)을 실행시킴.
-> javascript 로 된 url 구문이 html 구문으로 변환되고, 이를 로컬에 저장한다.
-> 이후에 저장된 html 파일을 분석하여 원하는 결과 가져오면됨.
* 메모장으로 test.js 라는 이름으로 텍스트파일을 만들어 아래 내용 입력(복사) 한다. (phantomjs 에서 사용하기 위함)
var page = require('webpage').create();
system = require('system');
var fs = require('fs');// File System Module
var args = system.args;
var url = args[1]; // 대상 webpage url
var output = args[2]; // 저장할 파일이름, path for saving the local file
page.open( url, function() { // open the file
fs.write(output,page.content,'w'); // Write the page to the local file using page.content
phantom.exit(); // exit PhantomJs
});
* python 에서 편하게 사용하기위해, phantomjs.exe 파일만 python 설치한 폴더로 복사함.
** phantomjs 실행 화면
---> javascript 를 포함한 http://www.ncbi.nlm.nih.gov/pubmed/17708774 를 html 로 변환하여 test.html 로 저장하라.
*** 최종 코드 ***
# -*- coding: utf-8 -*-
from bs4 import BeautifulSoup
import re
html_file = 'test.html' # phantomJS 로 만든 대상 web page의 html 파일
f = open(html_file)
tt = f.read()
pp = BeautifulSoup(tt)
# pp 내용중에서, div tag 이면서 id = 'disc_col' 인 element를 list 로 가져온다
data = pp.find_all('div', attrs={'id': 'disc_col'})[0]
# print data.prettify()
# data 내용중에서, div tag 이면서 class = 'portlet_title' 인 element들을 list 로 가져온다
d2 = data.find_all('div', attrs={'class': 'portlet_title'})
# print len(d2)
citation = '0'
for x in d2:
tmp = x.h3.span.contents # x -> h3 tag -> span tag contents
if tmp and u'Cited by' in tmp[0]:
# print tmp[0]
citation = re.search('\d+', tmp[0]).group() # string
print u'인용횟수 = ' , citation
성공 !!!
** 추가로.. 예외처리, 기타 자동화는 개인적으로 수정해서 사용하세요!!!!
--- 모든 경우를 확인 한것 아니므로 , 에러 발생시 chrome 개발자도구로 html 분석해서 알고리즘 추가하세요!
'python' 카테고리의 다른 글
| django 설치, 버전 확인 (0) | 2014.10.14 |
|---|---|
| python -- ffmpeg 이용한 video, audio capture (1) | 2014.09.30 |
| python debugging -- exception 발생한 file name, line number 찾기 (0) | 2014.09.19 |
| bioinfomatics -- vienna format 으로 RNA 그리기 (0) | 2014.09.02 |
| python -- self, 클래스멤버(변수) , 인스턴스멤버(변수), 생성자, 소멸자 (0) | 2014.08.27 |


