Guzzle + domCrawler 을 이용한 심플 php 웹파싱(스크래핑)

들어가기 전에

파싱과 스크랩핑, 크롤링은 의미가 좀 다르지만, 한국에서는 보통 파싱이라는 단어로 통용된다.

파싱을 위해선 정규식을 쓰는게 일반적이지만, 웹의 데이타를 추출할때는 어려운점이 있다.

웹의 데이타를 파싱하기 위해 가장 보편적이고, 심플한 방법은 DOM 에서 데이타를 추출하는 형태이다. 웹페이지를 설계할때 css를 이용하여  계층적으로  만들기 때문에, 데이타를 추출하기 위해서도 계층적 구조로 접근이 가능한것이 유리하다.

Dom 파싱을  위해 각 언어별로 적당한 모듈이 있는데, 자바에서는 jsoup, 파이썬에선 BeautifulSoup 이 있고, nodejs 는 JSDOM, cheerio 가 있다.

문제는 PHP인데, 언어의 인지도에 비해 크롤링(파싱)부분이 취약하다.  그나마 정규식을 통해 파싱처리를 하는데, 조금 복잡한 웹페이지를 파싱할려면, 계층별로 split처리와 여러 정규식을 써야한다.  정규식 자체도 복잡하게되어 직관성이 매우 떨어지게 된다.(그러나 일단 데이타가 파싱만 되면, db처리나 활용이 편리한 이점이 있다.)

최근 php 로 데이타 파싱을 해야 할 일이 있어(정규식으로 해볼려다가 암걸리는줄 알았다.), 보던중에  php dom 파싱이 가능한 라이브러리가 있어 정리를 해본다. (물론 전통적인  php dom 파서가 있다. 타 언어에 비해 느리고, 잘 정의된 문서가 아닌 경우 오류가 심하고, dom 에 접근하는 방식이 직관적이지 못하다.)

웹 스크래핑(파싱) 라이브러리는 쉬운 사용법과, 직관적인 selector 사용이 가능해야 하며, 태그 일부가 유실되어 깨진 문서라고 하더라도 오류없이 파싱되어야 한다. 속도도 어느정도 되어야 한다.

설치

설치는 composer 를 통해서 설치할수 있다 

 

Guzzle + Dom crawler + css selector 라이브러리를 사용했는데, 굳이 따로 쓸필요없이, Goutte 라이브러리만 써도 된다. 아래 예제에서 Sir class는 위의 방식대로 작업한것이고, 아래 Sir2 클래스 파일은 Goutte를 사용한 방식이다. 내부에서 쓰는 라이브러리가 동일함으로 그냥 Goutte 를 쓰는걸 추천한다. 

예제코드중 Sir1 클래스는 sir.co.kr 자유게시판 목록을 스크래핑(파싱) 하는 코드이며, Sir2 클래스는 로그인 인증처리후 쪽지함 목록을 스크래핑(파싱)하는 코드이다. 본인이 테스트한 서버는 https 접속시 ssl 인증서 오류가 발생하여, 옵션 코드를 추가하였다.  

아래코드는 예제입니다. 테스트로만 사용하세요. 지나치게 많은 request를 sir.co.kr 로 보내면 아이피가 차단될수 있습니다.

예제코드

 

구현 코드를 보면, php에서 정규식을 사용하는것보다 심플하고 직관적으로 웹페이지 파싱이 가능하다는걸 알수 있습니다. php 에서 웹페이지에 대한 파싱이 필요한 경우 guzzle + dom crawler 는 좋은 선택이 될수 있습니다. 라이브러리 에 대한 자세한 사용법은 공식홈페이지와 아래 링크를 참고바랍니다. 

참고 정보

Scraping products from Walmart with PHP, Guzzle, Crawler and Doctrine

PHP Simple HTML DOM Parser vs FriendsOfPHP Goutte

PHP 로 API 서비스 개발 with slim3

앱과 통신하는데 필요한 api 서비스 개발중인데.. 

기존 사이트가 php라서 빠르고 심플하면서, 확장성 높은 설계를 위해 php 를 쓰기로 함.

적당한 라이브러리를 찾아보고 있었는데,, 라라벨은 너무 덩치가 큰것 같아서 패스하고,

slim3 가 적당해보여서 개발을하고 있은데,, 전체적인 구조는 라라벨과 유사(라이브러리도 가져다 씀) 하면서도 심플하니 좋네요.

한번 만들면 비슷한 php 로 api 작업하는 경우는 금방금방 끝날것 같습니다.

국내에서는 자료가 별로 없고, 유투브나 웨비나 사이트에 강좌는 많네요. 유튜브보고 사용법 배움.

코딩 위주로 설명을 해주니, 영알못도 대충 이해됨.

모던 php 배우시는 분이라면, 라라벨도 좋지만, slim3 로 가볍게 시작해보세요.

이름처럼 슬림합니다..(그렇지만 유연하고 확장성 높음)

PHP용 redis query cache (쿼리 캐시) class

시간이 오래걸리는 쿼리의 결과 데이타를 캐시 처리하도록 만들어진 클래스입니다.

 

SQL_INJECTION(SQL 인젝션)은 어떻게 막아야 하나요?

SQL_INJECTION(SQL 인젝션)은 어떻게 막아야 하나요?

1. pdo의 bind parameter,  pdo의 quota 함수,  mysql_real_eacape_string 함수 등을 이용 
– pdo  bind 를 쓰는게 가장 바람직합니다. 그냥 bind는 의미 없구요. order by 구문은 bind가 안되는 부분임으로
코드에서 order by value 를 꼭 확인해야 합니다. url 에 온 파라메타 그대로 order by에 쓰면 안돼요!!

2. url 파라메타에 select, update, union, and, or 구문 사용금지(그외 웹용 특수문자 입력금지) 
– 게시판은 이게 좀 곤란하죠… 게시판의 제목과, 본문, 코멘트는 그누보드 필터 함수를 꼭 쓰셔야 해요.(그누보드 함수 좋아요)

3. 웹서버에 웹방화벽 모듈 설치 mod_security or webknight, naxsi, dot depeder 등등.. 
– sql injection 공격이 한번 들어온곳은 계속 들어옴으로, 웹방화벽에서 추가를 해야 해요.. 개인적으로 nginx 모듈인 naxsi 를 추천합니다. 이건 다시한번 정리해서 올릴 예정입니다.

4. 웹방화벽 기능이 있는 cdn 서비스 이용 (클라우드 플레어 등) 
– 클라우드 플레어의 프로 플랜 이상이면 사용이 가능합니다. 정상적인걸 막는 경우도 있음으로 룰셋을 잘 관리해야 합니다.
(그런데 클라우드플레어 국내에선 너무 느려서…. 공격들어올때 잠깐 켰다가 끄는 방법을 추천)

5.웹소스로 된 방화벽 솔루션이나 코드 추가

– kisa 캐슬.. 성능은 예전에 안 좋았는데, 요즘은 어떤지 모르겠음.). github 에도 좀 있을듯.
– 경험삼아 한번씩 설치해보세요. 접속자가 많지 않은곳은 성능 이슈가 없어서 괜찮습니다.

 

지금 사이트와 개발자 상황에 맞춰서 5가지중에 가능한걸 적용하시면 됩니다.(2개 이상 적용하면 더 좋습니다.)

아래 예제는 php에서 sql injection 을 체크하기 위한 코드입니다. 간단해보이지만 효과적입니다.