11# -*- coding: utf-8 -*-
22
3- import logging , os , re , time
4- import urllib .parse , urllib .request
3+ import logging
4+ import os
5+ import re
6+ import time
7+ import urllib .parse
8+ import urllib .request
59from functools import reduce
610import oss2
711from aliyunsdkcore .client import AcsClient
812from aliyunsdkcore .request import CommonRequest
913from aliyunsdkcore .auth .credentials import AccessKeyCredential
10- from aliyunsdkcore .auth .credentials import StsTokenCredential
14+ from aliyunsdkcore .auth .credentials import StsTokenCredential
1115
1216LOGGER = logging .getLogger ()
1317
@@ -113,9 +117,16 @@ def download_file(src_url, dist_path):
113117'''
114118
115119
116- def parse_and_download_page (url ):
120+ def parse_and_download_page (url , level ):
117121 global downloaded_list
122+ global max_level
118123
124+ # # 达到最大抓取层级,终止递归
125+ if max_level > 0 and level > max_level :
126+ LOGGER .info ("max fetch level {0} reached" .format (max_level ))
127+ return
128+
129+ level += 1
119130 url_dict = parse_url (url )
120131 domain = url_dict ['domain' ]
121132
@@ -154,9 +165,11 @@ def parse_and_download_page(url):
154165 # http://www.baidu/com/static/index.js
155166 # static/js/index.js
156167 if resource_url .startswith ('../' ):
157- resource_url = urllib .parse .urljoin (url_dict ['full_path' ], resource_url )
168+ resource_url = urllib .parse .urljoin (
169+ url_dict ['full_path' ], resource_url )
158170 elif resource_url .startswith ('./' ):
159- resource_url = urllib .parse .urljoin (url_dict ['full_path' ], resource_url )
171+ resource_url = urllib .parse .urljoin (
172+ url_dict ['full_path' ], resource_url )
160173 elif resource_url .startswith ('//' ):
161174 resource_url = 'https:' + resource_url
162175 elif resource_url .startswith ('/' ):
@@ -189,7 +202,8 @@ def parse_and_download_page(url):
189202
190203 # 递归解析 html/htm/shtml
191204 if resource_url_dict ['ext' ] in ['html' , 'htm' , 'shtml' ]:
192- parse_and_download_page (resource_url )
205+ LOGGER .info ("parse_and_download_page, level {}" .format (level ))
206+ parse_and_download_page (resource_url , level )
193207
194208 if not os .path .exists (resource_dir ):
195209 os .makedirs (resource_dir )
@@ -219,11 +233,14 @@ def handler(event, context):
219233 global downloaded_list
220234 downloaded_list = []
221235
236+ global max_level
237+ max_level = int (os .environ ['MAX_FETCH_LEVEL' ])
238+
222239 # 备份源站(域名入口)
223240 # url = 'http://www.cgbchina.com.cn/index.html'
224241 # url = 'http://www.peersafe.cn/index.html'
225- url = os .environ ['SOURCE_URL ' ]
226- parse_and_download_page (url )
242+ url = os .environ ['ORIGIN ' ]
243+ parse_and_download_page (url , 0 )
227244 LOGGER .info ('总共下载了 %d 个资源' % len (downloaded_list ))
228245
229246 # 解析下载网页后备份和预热
@@ -234,37 +251,51 @@ def handler(event, context):
234251 creds .access_key_secret ,
235252 creds .security_token )
236253 # 备份目标到OSS
237- bucket_name = os .environ ['BUCKET_NAME' ]
238- endpoint = 'oss-' + context .region + '-internal.aliyuncs.com'
254+ backup_origin = os .environ ['BACKUP_ORIGIN' ]
255+ m = re .search (r'(.*).oss-(.*).aliyuncs.com' , backup_origin )
256+ if m is None :
257+ LOGGER .error (
258+ "Backup origin {} is not a valid oss domain" .format (backup_origin ))
259+ raise ValueError (
260+ "Backup origin {} is not a valid oss domain" .format (backup_origin ))
261+
262+ bucket_name = m .group (1 )
263+ region = m .group (2 )
264+ endpoint = 'oss-' + region + '.aliyuncs.com:'
239265 # endpoint = 'oss-cn-hangzhou-internal.aliyuncs.com'
240266 bucket = oss2 .Bucket (oss_auth , endpoint , bucket_name )
241267 # backup
242268 for tmp_file in downloaded_list :
243269 # /tmp/www.cgbchina.com.cn/index.html -> www.cgbchina.com.cn/index.html
244270 object_name = tmp_file [5 :]
245- LOGGER .info ("start to backup matched file = {}" .format (object_name ))
246- bucket .put_object_from_file (object_name , tmp_file )
271+ LOGGER .info (
272+ "start to backup matched file = {}" .format (object_name ))
273+ if bucket is not None :
274+ bucket .put_object_from_file (object_name , tmp_file )
247275
248276 # 预热目标到CDN域名
249- if "WARMUP_DOMAIN" in os .environ and os . environ [ "WARMUP_DOMAIN" ] != 'dummy' :
277+ if "WARMUP_DOMAIN" in os .environ :
250278 cdn_domain = os .environ ["WARMUP_DOMAIN" ]
251279 cdn_auth = StsTokenCredential (
252280 creds .access_key_id ,
253281 creds .access_key_secret ,
254282 creds .security_token )
255- client = AcsClient (region_id = context .region , credential = cdn_auth )
256-
283+ client = AcsClient (region_id = context .region ,
284+ credential = cdn_auth )
285+
257286 request = CommonRequest ()
258287 request .set_accept_format ('json' )
259288 request .set_domain ('cdn.aliyuncs.com' )
260289 request .set_method ('POST' )
261- request .set_protocol_type ('https' ) # https | http
290+ request .set_protocol_type ('https' ) # https | http
262291 request .set_version ('2018-05-10' )
263292 request .set_action_name ('PushObjectCache' )
264- cdn_url = cdn_domain + urllib .parse .urlparse ('http://' + object_name ).path
293+ cdn_url = cdn_domain + \
294+ urllib .parse .urlparse ('http://' + object_name ).path
265295 request .add_query_param ('ObjectPath' , cdn_url )
266-
296+
267297 response = client .do_action (request )
268- LOGGER .info ('PushObjectCache: ' + cdn_url + ', and returned: ' + str (response , encoding = 'utf-8' ))
298+ LOGGER .info ('PushObjectCache: ' + cdn_url +
299+ ', and returned: ' + str (response , encoding = 'utf-8' ))
269300
270- return ' success'
301+ return dict ( download_num = len ( downloaded_list ), success = True )
0 commit comments