Showing
6 changed files
with
267 additions
and
17 deletions
@@ -6,7 +6,7 @@ const yohoLib = require('yoho-node-lib'); | @@ -6,7 +6,7 @@ const yohoLib = require('yoho-node-lib'); | ||
6 | 6 | ||
7 | // 全局注册library | 7 | // 全局注册library |
8 | yohoLib.global(config); | 8 | yohoLib.global(config); |
9 | - | 9 | +global.yoho.redis = require('./libs/redis'); |
10 | const logger = global.yoho.logger; | 10 | const logger = global.yoho.logger; |
11 | const app = express(); | 11 | const app = express(); |
12 | const seo = require('./apps/seo'); | 12 | const seo = require('./apps/seo'); |
@@ -14,10 +14,10 @@ const seo = require('./apps/seo'); | @@ -14,10 +14,10 @@ const seo = require('./apps/seo'); | ||
14 | // 定时任务 主动推送和生成xml | 14 | // 定时任务 主动推送和生成xml |
15 | seo.start(); | 15 | seo.start(); |
16 | 16 | ||
17 | -// 提供sitemap给搜索百度访问 | ||
18 | -app.use(express.static(config.sitemapPath)); | 17 | +app.get('/synchronousKeywords', seo.synchronousKeywords); |
18 | +app.get('/sendKeywordsUrls', seo.sendKeywordsUrls); | ||
19 | 19 | ||
20 | app.listen(config.port, function() { | 20 | app.listen(config.port, function() { |
21 | - logger.info('yoho seo start'); | 21 | + logger.info(`yoho seo start : ${config.port}`); |
22 | }); | 22 | }); |
23 | 23 |
@@ -11,6 +11,8 @@ const helper = global.yoho.helpers; | @@ -11,6 +11,8 @@ const helper = global.yoho.helpers; | ||
11 | const config = require('../config/config'); | 11 | const config = require('../config/config'); |
12 | const schedule = require('node-schedule'); | 12 | const schedule = require('node-schedule'); |
13 | const qs = require('querystring'); | 13 | const qs = require('querystring'); |
14 | +const seoModel = require('./seoModel'); | ||
15 | + | ||
14 | const baiduUrls = { | 16 | const baiduUrls = { |
15 | urls: 'http://data.zz.baidu.com/urls', | 17 | urls: 'http://data.zz.baidu.com/urls', |
16 | update: 'http://data.zz.baidu.com/update', | 18 | update: 'http://data.zz.baidu.com/update', |
@@ -120,6 +122,22 @@ const sendUrls = () => { | @@ -120,6 +122,22 @@ const sendUrls = () => { | ||
120 | })(); | 122 | })(); |
121 | }; | 123 | }; |
122 | 124 | ||
125 | +// 同步建议词(把接口拓展的建议词同步到灰度redis) | ||
126 | +const synchronousKeywords = (req, res) => { | ||
127 | + seoModel.synchronousKeywords(); | ||
128 | + res.end(); | ||
129 | +}; | ||
130 | + | ||
131 | +// 定时缓慢爬取关键词页面生成缓存,防止蜘蛛爬取 | ||
132 | + | ||
133 | + | ||
134 | +// 向百度推送页面新的页面 | ||
135 | +const sendKeywordsUrls = (req, res) => { | ||
136 | + seoModel.sendKeywordsUrls(); | ||
137 | + res.end(); | ||
138 | + | ||
139 | +}; | ||
140 | + | ||
123 | /** | 141 | /** |
124 | * 定时每天1点推送最新商品和文章,更新站点sitemap | 142 | * 定时每天1点推送最新商品和文章,更新站点sitemap |
125 | */ | 143 | */ |
@@ -130,5 +148,7 @@ const start = () => { | @@ -130,5 +148,7 @@ const start = () => { | ||
130 | }; | 148 | }; |
131 | 149 | ||
132 | module.exports = { | 150 | module.exports = { |
133 | - start | 151 | + start, |
152 | + synchronousKeywords, | ||
153 | + sendKeywordsUrls | ||
134 | }; | 154 | }; |
apps/seoModel.js
0 → 100644
1 | +'use strict'; | ||
2 | +const api = global.yoho.API; | ||
3 | +const redis = global.yoho.redis; | ||
4 | +const _ = require('lodash'); | ||
5 | + | ||
6 | +/** | ||
7 | + * redis multi command | ||
8 | + */ | ||
9 | +const multiAsync = (multi)=>{ | ||
10 | + return multi.execAsync().then(function(res) { | ||
11 | + return res; | ||
12 | + }); | ||
13 | +}; | ||
14 | + | ||
15 | +/** | ||
16 | + * 将链接推送到百度站长 | ||
17 | + * @param site string 站点 | ||
18 | + * @param urls object {site: 'https://www.yohobuy.com', type: 'mip'} 默认不需要type | ||
19 | + */ | ||
20 | +// const sendUrlsToBaidu = (params, urls) => { | ||
21 | +// let paramsDef = { | ||
22 | +// token: config.baiduToken | ||
23 | +// }; | ||
24 | +// | ||
25 | +// // 过滤无效的参数 | ||
26 | +// _.forEach(params, (val, key) => { | ||
27 | +// if (!val) { | ||
28 | +// delete params[key]; | ||
29 | +// } | ||
30 | +// }); | ||
31 | +// | ||
32 | +// qs.escape = (str) => { | ||
33 | +// return str; | ||
34 | +// }; | ||
35 | +// | ||
36 | +// let options = { | ||
37 | +// url: `${baiduUrls.urls}?${qs.stringify(Object.assign(paramsDef, params), null, null, {})}`, | ||
38 | +// headers: { | ||
39 | +// 'Content-Type': 'text/plain' | ||
40 | +// }, | ||
41 | +// method: 'post', | ||
42 | +// form: urls.join('\n'), | ||
43 | +// json: true, | ||
44 | +// timeout: 10000, | ||
45 | +// gzip: true | ||
46 | +// }; | ||
47 | +// | ||
48 | +// return rp(options).then(result => { | ||
49 | +// logger.info(result); | ||
50 | +// }); | ||
51 | +// }; | ||
52 | + | ||
53 | +const getKeywordsApi = (page, limit) => { | ||
54 | + let params = { | ||
55 | + page: page || 1, | ||
56 | + limit: limit || 1000, | ||
57 | + method: 'web.search.suggestList' | ||
58 | + }; | ||
59 | + | ||
60 | + return api.get('', params); | ||
61 | +}; | ||
62 | + | ||
63 | +/** | ||
64 | + * 关键词同步到redis | ||
65 | + */ | ||
66 | +const synchronousKeywords = () => { | ||
67 | + | ||
68 | + return getKeywordsApi(1, 1).then(res => { | ||
69 | + let start = 0, | ||
70 | + page = 1, | ||
71 | + limit = 1000, // 每次请求接口关键词数量 | ||
72 | + total = _.get(res, 'data.total', 0); | ||
73 | + | ||
74 | + // 接口调用失败 | ||
75 | + if (total <= 0) { | ||
76 | + console.log('no data'); | ||
77 | + return; | ||
78 | + } | ||
79 | + | ||
80 | + // 循环遍历接口关键词写入redis | ||
81 | + let interval = setInterval(() => { | ||
82 | + if (start > total) { | ||
83 | + clearInterval(interval); | ||
84 | + } | ||
85 | + | ||
86 | + getKeywordsApi(page, limit).then(result => { | ||
87 | + let multi = redis.multi(); | ||
88 | + | ||
89 | + start += limit; | ||
90 | + page++; | ||
91 | + console.log(page); | ||
92 | + _.forEach(_.get(result, 'data.suggest_list', []), value => { | ||
93 | + let key = `keywords_mana:${value.keyword}`; | ||
94 | + | ||
95 | + multi.set(key, value.keyword); | ||
96 | + multi.lrem('keywords_mana_list', 1, key).lpush('keywords_mana_list', key); | ||
97 | + }); | ||
98 | + | ||
99 | + multiAsync(multi); | ||
100 | + | ||
101 | + }).catch(()=>{ | ||
102 | + clearInterval(interval); | ||
103 | + }); | ||
104 | + | ||
105 | + }, 1000); | ||
106 | + | ||
107 | + }); | ||
108 | +}; | ||
109 | + | ||
110 | +/** | ||
111 | + * 查询 redis中 关键词 | ||
112 | + * @type {{getKeyWordsUrl}} | ||
113 | + */ | ||
114 | + | ||
115 | +const getRedisKeywords = (start, end) => { | ||
116 | + return redis.lrangeAsync('keywords_mana_list', start, end).then(res => { | ||
117 | + let urls = []; | ||
118 | + | ||
119 | + _.forEach(res, keyword => { | ||
120 | + let buff = new Buffer(keyword).toString('hex').toUpperCase(); | ||
121 | + | ||
122 | + urls.push(`https://www.yohobuy.com/so/${buff}.html`); | ||
123 | + }); | ||
124 | + | ||
125 | + return urls; | ||
126 | + }); | ||
127 | +}; | ||
128 | + | ||
129 | +/** | ||
130 | + * 推送url | ||
131 | + */ | ||
132 | +const sendKeywordsUrls = () => { | ||
133 | + return redis.llenAsync('keywords_mana_list').then(total => { | ||
134 | + console.log(total); | ||
135 | + if (total <= 0) { | ||
136 | + return; | ||
137 | + } | ||
138 | + | ||
139 | + let start = 0, | ||
140 | + count = 1000; | ||
141 | + | ||
142 | + let interval = setInterval(() => { | ||
143 | + if (start >= total) { | ||
144 | + clearInterval(interval); | ||
145 | + } | ||
146 | + | ||
147 | + console.log(start); | ||
148 | + getRedisKeywords(start, start + count).then(urls => { | ||
149 | + console.log(urls); | ||
150 | + | ||
151 | + // 发送到百度 | ||
152 | + // sendUrlsToBaidu({site: 'https://www.yohobuy.com'}, urls); | ||
153 | + }).catch(() => { | ||
154 | + clearInterval(interval); | ||
155 | + }); | ||
156 | + | ||
157 | + start += count; | ||
158 | + | ||
159 | + }, 1000); | ||
160 | + | ||
161 | + return []; | ||
162 | + | ||
163 | + }); | ||
164 | +}; | ||
165 | + | ||
166 | +module.exports = { | ||
167 | + synchronousKeywords, | ||
168 | + sendKeywordsUrls | ||
169 | +}; |
@@ -17,18 +17,18 @@ module.exports = { | @@ -17,18 +17,18 @@ module.exports = { | ||
17 | cookieDomain: '.yohobuy.com', | 17 | cookieDomain: '.yohobuy.com', |
18 | domains: { | 18 | domains: { |
19 | // test3 | 19 | // test3 |
20 | - // singleApi: 'http://api-test3.yohops.com:9999/', | ||
21 | - // api: 'http://api-test3.yohops.com:9999/', | ||
22 | - // service: 'http://service-test3.yohops.com:9999/', | ||
23 | - // serviceNotify: 'http://service-test3.yohops.com:9999/', | ||
24 | - // global: 'http://global-test-soa.yohops.com:9999/', | 20 | + singleApi: 'http://api-test3.yohops.com:9999/', |
21 | + api: 'http://api-test3.yohops.com:9999/', | ||
22 | + service: 'http://service-test3.yohops.com:9999/', | ||
23 | + serviceNotify: 'http://service-test3.yohops.com:9999/', | ||
24 | + global: 'http://global-test-soa.yohops.com:9999/', | ||
25 | 25 | ||
26 | // prod | 26 | // prod |
27 | - singleApi: 'http://single.yoho.cn/', | ||
28 | - api: 'http://api.yoho.cn/', | ||
29 | - service: 'http://service.yoho.cn/', | ||
30 | - serviceNotify: 'http://service.yoho.cn/', | ||
31 | - global: 'http://api-global.yohobuy.com/', | 27 | + // singleApi: 'http://single.yoho.cn/', |
28 | + // api: 'http://api.yoho.cn/', | ||
29 | + // service: 'http://service.yoho.cn/', | ||
30 | + // serviceNotify: 'http://service.yoho.cn/', | ||
31 | + // global: 'http://api-global.yohobuy.com/', | ||
32 | 32 | ||
33 | // gray | 33 | // gray |
34 | // singleApi: 'http://single.gray.yohops.com/', | 34 | // singleApi: 'http://single.gray.yohops.com/', |
@@ -133,7 +133,25 @@ module.exports = { | @@ -133,7 +133,25 @@ module.exports = { | ||
133 | maxQps: 1200, | 133 | maxQps: 1200, |
134 | sessionMemcachedPrefix: 'yohobuy_session:', | 134 | sessionMemcachedPrefix: 'yohobuy_session:', |
135 | baiduToken: '0lSAO4ZxEKsYopMG', // 百度站长推送的token | 135 | baiduToken: '0lSAO4ZxEKsYopMG', // 百度站长推送的token |
136 | - sitemapPath: './files' | 136 | + redis: { |
137 | + connect: { | ||
138 | + host: '127.0.0.1', | ||
139 | + port: '6379', | ||
140 | + retry_strategy(options) { | ||
141 | + if (options.error && options.error.code === 'ECONNREFUSED') { | ||
142 | + console.log('redis连接不成功'); | ||
143 | + } | ||
144 | + if (options.total_retry_time > 1000 * 60 * 60 * 6) { | ||
145 | + console.log('redis连接超时'); | ||
146 | + return; | ||
147 | + } | ||
148 | + if (options.attempt > 10) { | ||
149 | + return 1000 * 60 * 60 * 0.5; | ||
150 | + } | ||
151 | + return Math.min(options.attempt * 100, 1000); | ||
152 | + } | ||
153 | + } | ||
154 | + } | ||
137 | }; | 155 | }; |
138 | 156 | ||
139 | if (isProduction) { | 157 | if (isProduction) { |
@@ -167,7 +185,26 @@ if (isProduction) { | @@ -167,7 +185,26 @@ if (isProduction) { | ||
167 | open: false, | 185 | open: false, |
168 | url: 'http://123.206.2.55/strategy' | 186 | url: 'http://123.206.2.55/strategy' |
169 | }, | 187 | }, |
170 | - zookeeperServer: 'web.zookeeper.yohoops.org:2181' | 188 | + zookeeperServer: 'web.zookeeper.yohoops.org:2181', |
189 | + redis: { | ||
190 | + connect: { | ||
191 | + host: 'web.redis.yohoops.org' | ||
192 | + }, | ||
193 | + port: '6379', | ||
194 | + retry_strategy(options) { | ||
195 | + if (options.error && options.error.code === 'ECONNREFUSED') { | ||
196 | + console.log('redis连接不成功'); | ||
197 | + } | ||
198 | + if (options.total_retry_time > 1000 * 60 * 60 * 6) { | ||
199 | + console.log('redis连接超时'); | ||
200 | + return; | ||
201 | + } | ||
202 | + if (options.attempt > 10) { | ||
203 | + return 1000 * 60 * 60 * 0.5; | ||
204 | + } | ||
205 | + return Math.min(options.attempt * 100, 1000); | ||
206 | + } | ||
207 | + } | ||
171 | }); | 208 | }); |
172 | } else if (isTest) { | 209 | } else if (isTest) { |
173 | Object.assign(module.exports, { | 210 | Object.assign(module.exports, { |
libs/redis.js
0 → 100644
1 | +const redis = require('redis'); | ||
2 | +const bluebird = require('bluebird'); | ||
3 | +const config = require('../config/config'); | ||
4 | +let client; | ||
5 | + | ||
6 | +try { | ||
7 | + client = redis.createClient(config.redis.connect); | ||
8 | + | ||
9 | + bluebird.promisifyAll(redis.RedisClient.prototype); | ||
10 | + bluebird.promisifyAll(redis.Multi.prototype); | ||
11 | + | ||
12 | + client.on('error', function() { | ||
13 | + global.yoho.redis = ''; | ||
14 | + }); | ||
15 | + | ||
16 | + client.on('connect', function() { | ||
17 | + global.yoho.redis = client; | ||
18 | + }); | ||
19 | +} catch (e) { | ||
20 | + global.yoho.redis = ''; | ||
21 | +} | ||
22 | + | ||
23 | +module.exports = client; |
@@ -23,6 +23,7 @@ | @@ -23,6 +23,7 @@ | ||
23 | "moment": "^2.18.1", | 23 | "moment": "^2.18.1", |
24 | "node-schedule": "^1.2.1", | 24 | "node-schedule": "^1.2.1", |
25 | "nodemon": "1.9.2", | 25 | "nodemon": "1.9.2", |
26 | + "redis": "^2.7.1", | ||
26 | "request": "^2.79.0", | 27 | "request": "^2.79.0", |
27 | "request-promise": "^4.1.1", | 28 | "request-promise": "^4.1.1", |
28 | "shelljs": "^0.7.7", | 29 | "shelljs": "^0.7.7", |
-
Please register or login to post a comment