We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
最近接了一个seo优化的需求,运用到了phantomjs,它可以说是一个没有ui的webkit浏览器,所以它可以抓取由ajax返回的数据所生成的dom,这是爬虫所需要的。总体优化的思路便是:配置nginx,判断如果是爬虫,则将请求转发到自己配置的web server服务器上,使用phantomjs抓取完整的html并且返回给爬虫。下面一步一步实现这个功能。
不多说,直接上代码。
./spider.js
'use strict' // 单个资源等待时间,避免资源加载后还需要加载其他资源 var resourceWait = 500 var resourceWaitTimer // 最大等待时间 var maxWait = 5000 var maxWaitTimer // 资源计数 var resourceCount = 0 // phantomjs webpage模块 var page = require('webpage').create() // nodejs系统模块 var system = require('system') // 从cli中获取第二个参数为目标url var url = system.args[1] // 设置phantomjs视窗大小 page.viewportSize = { width: 1280, height: 1014 } var capture = function (errCode) { // 外部通过stdout获取页面内容 console.log(page.content) // 清除定定时器 clearTimeout(maxWaitTimer) // 任务完成,正常退出 phantom.exit(errCode) } // 资源请求并计数 page.onResourceRequested = function (req) { resourceCount++ clearTimeout(resourceWaitTimer) } // 资源加载完毕 page.onResourceReceived = function (res) { // chunk模式的http回包,会多次触发resourceReceived事件,需要判断资源是否已经end if (res.stage !== 'end') { return } resourceCount-- if (resourceCount === 0) { // 当页面中全部资源加载完毕后,截取当前渲染出来的html // 由于onResourceReceived在资源加载完毕就立即被调用了,我们需要给一些时间让js跑解析任务 resourceWaitTimer = setTimeout(capture, resourceWait) } } // 资源加载超时 page.onResourceTimout = function (req) { resourceCount-- } // 资源加载失败 page.onResourceError = function (err) { resourceCount-- } // 打开页面 page.open(url, function (status) { if (status !== 'success') { phantom.exit(1) } else { // 当改页面的初始html返回成功后,开启定时器 // 当到达最大时间(默认5秒)的时候,截取渲染出来的html maxWaitTimer = setTimeout(function () { capture(2) }, maxWait) } })
每次都要使用terminal,输入命令并指定url,这样显然不够通用,需要配置一个web server,动态抓取html。
./app.js
var express = require('express') var app = express() // 引入nodejs的子进程模块 var child_process = require('child_process') app.get('*', function (req, res) { // 完整url var url = req.protocol + '://' + req.hostname + req.originalUrl // 预渲染后的页面字符串容器 var content = '' // 开启一个phantomjs子进程 var phantom = child_process.spawn('phantomjs', ['spider.js', url]) // 设置stdout字符编码 phantom.stdout.setEncoding('utf8') // 监听phantom的stdout, 并拼接起来 phantom.stdout.on('data', function (data) { content += data.toString() }) // 监听子进程退出事件 phantom.on('exit', function (code) { switch (code) { case 1: console.log('加载失败') res.send('加载失败') break case 2: console.log('加载超时:' + url) res.send(content) break default: res.send(content) break } }) }) app.listen(3000, function () { console.log('Spider app listening on port 3000!'); })
新建一个phantom.conf文件
# 定义一个Nginx的upstream为spider_server upstream spider_server { server localhost:3000; } server { listen 80; server_name yuedu.163.com; # 指定一个范围,默认 / 表示全部请求 location / { proxy_set_header Host $host:$proxy_port; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 当UA里面含有Baiduspider的时候,流量Nginx以反向代理的形式,将流量传递给spider_server if ($http_user_agent ~* "Baiduspider|twitterbot|facebookexternalhit|rogerbot|linkedinbot|embedly|quora link preview|showyoubot|outbrain|pinterest|slackbot|vkShare|W3C_Validator|bingbot|Sosospider|Sogou Pic Spider|Googlebot|360Spider") { proxy_pass http://spider_server; } } }
./ nginx.conf
include phantom.conf
The text was updated successfully, but these errors were encountered:
No branches or pull requests
目录
1.前言
最近接了一个seo优化的需求,运用到了phantomjs,它可以说是一个没有ui的webkit浏览器,所以它可以抓取由ajax返回的数据所生成的dom,这是爬虫所需要的。总体优化的思路便是:配置nginx,判断如果是爬虫,则将请求转发到自己配置的web server服务器上,使用phantomjs抓取完整的html并且返回给爬虫。下面一步一步实现这个功能。
2.初试phantomjs
不多说,直接上代码。
./spider.js
每次都要使用terminal,输入命令并指定url,这样显然不够通用,需要配置一个web server,动态抓取html。
3.使用express
./app.js
4.配置nginx
新建一个phantom.conf文件
./ nginx.conf
The text was updated successfully, but these errors were encountered: