기본 콘텐츠로 건너뛰기

spiderable package를 살펴보았다.

동적페이지를 만들면 웹크롤러들이 찌르러 왔다가 빈손으로 돌아가곤 한다.
이래서야 안될일.

발번역부터 시작해보자.
// list of bot user agents that we want to serve statically, but do
// not obey the _escaped_fragment_ protocol. The page is served
// statically to any client whos user agent matches any of these
// regexps. Users may modify this array.
//
// An original goal with the spiderable package was to avoid doing
// user-agent based tests. But the reality is not enough bots support
// the _escaped_fragment_ protocol, so we need to hardcode a list
// here. I shed a silent tear.
우리가 정적으로 제공하고 싶지만 _escaped_fragment_ 프로토콜을 따르지 않는 봇 사용자 에이전트의 목록입니다.
페이지는 사용자 에이전트가 이러한 정규식 중 하나와 일치하는 모든 클라이언트에 정적으로 제공합니다. 사용자는 이 배열을 변경할 수 있습니다.
spiderable 패키지와 원래 목표는 사용자 에이전트 기반의 테스트를 실시하는 것을 피하기 위해서였다.
하지만 현실은 봇들은 _escaped_fragment_ 프로토콜을 지원하지 않기 때문에, 여기에서는 목록을 하드 코딩해야합니다. 나는 조용히 눈물을 흘렸다.
Spiderable.userAgentRegExps = [
    /^facebookexternalhit/i, /^linkedinbot/i, /^twitterbot/i];

요놈들! 말을 듣지 않는 나쁜 아이들이 니 놈들이렸다! 이 오라질 것들!
아래와 같이 javascript 코드를 생성하여 phantom.js에 밀어 넣는다. 파일로에서 넣지 않고 바로 생성하기 위해 /dev/stdin 을 사용하여 밀어넣는다. 아마 이것 때문에 윈도우에선 애로사항이 꽃필 것이다. 방법이야 있지만 패스.

    var phantomScript = "var url = " + JSON.stringify(url) + ";" +
          "var page = require('webpage').create();" +
          "page.open(url);" +
          "setInterval(function() {" +
          "  var ready = page.evaluate(function () {" +
          "    if (typeof Meteor !== 'undefined' " +
          "        && typeof(Meteor.status) !== 'undefined' " +
          "        && Meteor.status().connected) {" +
          "      Deps.flush();" +
          "      return DDP._allSubscriptionsReady();" +
          "    }" +
          "    return false;" +
          "  });" +
          "  if (ready) {" +
          "    var out = page.content;" +
          "    out = out.replace(/<script[^>]+>(.|\\n|\\r)*?<\\/script\\s*>/ig, '');" +
          "    out = out.replace('<meta name=\"fragment\" content=\"!\">', '');" +
          "    console.log(out);" +
          "    phantom.exit();" +
          "  }" +
          "}, 100);\n";

소스 코드의 주 내용은 별게 없다. url을 인자로 받은 페이지를 만들어 반환하되 페이지 렌더링이 끝나는 시간을 가정하여 0.1초마다 계속 Meteor 어플리케이션의 존재를 확인하면 Deps를 flush하고 모든 subscription 들을 완료하였는지를 ready로 넘겨준다. 마지막으로 ready가 참이면 page.content를 넘겨주면서 끝난다.

단, <script>덩어리들을 홀랑 날리고 <meta name="fragment" content="!"> 도 홀랑홀랑 날린 다음에 stdout으로 보내주는 것이다. 평범한 html 문서 조각이 되는 것이다.

자. 큰덩어리로 돌아가는 구조를 말로 한번 풀어보자면 이런 것이다.

WebApp.connectHandlers 를 통해 들어온 놈들 중
request url이 _escaped_fragment_= 를 포함하거나  user-agent 이름이 facebookexternalhit, linkedinbot, twitterbot 같은 걸로 들어올 때
phantomJS를 가동해서 page.content를 얻은 다음 페이지로딩이 완료된 다음에 <script>와 <meta name="fragment" content="!"> 을 제거해서 돌려준다...
google 같은 경우 <meta name="fragment" content="!">가 있는 경우 _escaped_fragment_=를 붙여서 요청하는데 이때 phantomJS로 렌더링한 페이지 본문을 넘겨준다.

...라는 아름다운 이야기가 되겠다.

이래도 뭔소린지 모르겠다면 진리의 evetedmind 동영상을 보자.
https://www.eventedmind.com/posts/meteor-the-spiderable-package

재밌는 건 이 링크도 역시 spiderable 적용이다.
curl https://www.eventedmind.com/posts/meteor-the-spiderable-package
한 결과랑

curl https://www.eventedmind.com/posts/meteor-the-spiderable-package?_escaped_fragment_=
한 결과를 비교해보면 한눈에 알 수 있다.

마찬가지로 다른 bot들을 적용해보려면 user-agent를 주면 된다.

curl -s -A "facebookexternalhit" https://www.eventedmind.com/posts/meteor-the-spiderable-package

훌륭하지 않은가?

댓글

이 블로그의 인기 게시물

세상 간단한 https(+secured websocket): Caddy

nginx, apache2 같은 걸로 매번 certbot 연동을 통해 https 하는게 지겨워서 알아보니 Caddy라는게 있더라. 설치법은 강하게 크기 위해 알아서 해본다. # cat /etc/caddy/Caddyfile your.shitty.site:8123 {   proxy / localhost:9123 {     websocket     transparent   } } 이건 외부에서 8123으로 들어오는 걸 내부적으로 9123로 맞춰서 https 맞춰주는 reverse proxy. 만일 port를 생략하면 # cat /etc/caddy/Caddyfile your.shitty.site {   proxy / localhost:9123 {     websocket     transparent   } } 기본포트인 443으로 되어 https://your.shitty.site 로 접속이 된다. 요새 말썽이던 cloudflare 버리고 netlify domain이랑 caddy를 쓰니까 앓던 이가 빠진 느낌. 이 조합은 당분간 계속 써야겠다 싶다.

저지연 오디오 생성 LLVC 사용기

https://github.com/KoeAI/LLVC 써봄 CUDA 11.8 버전 쓰고 있어 pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118 VC 없어서 설치 https://wikidocs.net/168848 참조 FAIRSEQ 관련 오류 https://github.com/facebookresearch/fairseq/issues/2908 pip install editdistance  설치 No CUDA runtime is found, using CUDA_HOME='C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.8' 오류 멀쩡하게 있는데 안됨. pip install torch==2.1.0+cu118 torchvision==0.16.0+cu118 torchaudio==2.1.0+cu118 --extra-index-url https://download.pytorch.org/whl/cu118 다시 설치 set DISTUTILS_USE_SDK=1 이게 문젠가 설정하고 재도전 Using cached ruamel.yaml.clib-0.2.8-cp311-cp311-win_amd64.whl (118 kB) Building wheels for collected packages: fairseq   Building wheel for fairseq (pyproject.toml) ... error   error: subprocess-exited-with-error   × Building wheel for fairseq (pyproject.toml) did not run successfully.   │ exit code: 1   ╰─> [1829 lines of output]       No CUDA runtime is found, usi...