python实现自动监测目标网站的爬取速度_以及整体网络环境分析
实现的功能:在win7下,分别通过使用和不使用代理获取网页速度,以及使用系统自带的ping,tracert命令分析整个网络的环境,分析爬虫在速度上的瓶颈,以及排查解决网络故障。
分四步:
- 第一步:计算不使用代理获取目标网页的平均速度。
- 第二步:计算使用代理获取目标网页的平均速度。
- 第三步:使用win7自带的ping命令测试网络的连通度。
- 第四步:使用win7自带的tracert命令查看网络各节点路由的连通度。
1. 环境。
- Python:3.6.1
- Python IDE:pycharm
- 系统:win7
2. 影响爬虫爬取速度的关键因素。
首先,思考一下,爬虫爬取目标网站的速度受哪几个因素的影响?
- 第一,本地网络带宽。
- 第二,代理的稳定性,以及到目标网站的速度。
- 第三,目标网站的状态。
- 第四,本地,代理,目标网站之间的网络链路状态。
3. 监测哪些数据?
3.1. 使用本地网络访问目标网站的速度
在不使用代理的情况下,访问目标网站的不同详情页,计算访问每个网页需要的时间,成功率,以及失败率。
For example:
# python 3.6.1
import requests
import datetime
detailUrl = "www.amazon.com"
startTime = datetime.datetime.now()
response = requests.get(url=detailUrl, timeout = myTime)
endTime = datetime.datetime.now()
usedTime = endTime - startTime
success_count = 0 # statusCode == 200
if response.status_code == 200:
success_count += 1
注意:
1. 使用本地网络访问时,一定要注意目标网站的反爬技术,最好是设置延时 time.sleep(5)。
3.2. 使用代理访问目标网站的速度 —— 与3.1进行对比
使用代理,访问目标网站的不同详情页,计算访问每个网页需要的时间,成功率,以及失败率。
For example:
# python 3.6.1
import requests
import datetime
url = "www.amazon.com"
proxies = {
"http": proxy,
"https": proxy}
header = {
"User-Agent": "Mozilla/2.0 (compatible; Ask Jeeves/Teoma)"}
success_count = 0 # statusCode == 200
connectFail_count = 0 # statusCode != 200 or timeout
proxyFail_count = 0 # requests Exception
startTime = datetime.datetime.now()
try:
s = requests.session()
response = s.get(url=url, proxies=proxies, headers=header, timeout=30)
endTime = datetime.datetime.now()
usedTime = endTime - startTime
if response.status_code == 200:
success_count += 1
else:
connectFail_count += 1
except Exception as e:
proxyFail_count += 1
print( f"Exception: url={url}, e:{e}")
注意:
1. 使用代理访问时,为了防止程序异常终止,最好加上异常处理,因为代理总会有这样那样的问题。
3.3. 使用ping命令来测试目标网站的连通度
使用系统自带的ping命令,查看目标网站的网络连通度,以及延时信息。
For example:
# python 3.6.1
import subprocess
import os
ip_address = "www.amazon.com"
p = subprocess.Popen(["ping.exe", ip_address],
stdin = subprocess.PIPE,
stdout = subprocess.PIPE,
stderr = subprocess.PIPE,
shell = True)
# 在Windows上需要用gbk解码,python默认utf-8,会出现乱码
cmdOut = p.stdout.read().decode('gbk')
结果:
注意:
1. 指标:一般延时在100ms以下说明连通度非常高。还需要关注丢包率。
3.4. 使用tracert命令来查看到目标网站的路由详情
使用系统自带的tracert命令,查看到目标网站需要经过多少跳路由,到每个路由的时间,协助分析整个网络链路状态。
For example:
# python 3.6.1
import subprocess
import os
ip_address = "www.amazon.com"
p = subprocess.Popen(["tracert.exe", ip_address],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
shell=True)
# 在Windows上需要gbk解码,python默认utf-8,会出现乱码
cmdOut = p.stdout.read().decode('gbk')
结果:
注意:
- 访问 http://www.ip138.com/ips138.asp?ip=52.84.239.51&action=2 就能查到IP对应的地址在哪,注意将ip的值更换成自己的。
- 请求超时的,不是指链路不通,而是这个节点路由不遵守这个协议,不返回包。
这些信息能说明什么?
- 第一,对比3.1和3.2的数据,可以知道爬虫速度的瓶颈在哪。如果使用代理和不使用代理速度差不多,那么瓶颈就在本地带宽,想提升爬取速度,就要想办法提高本地网速。反之,就是代理拉慢了爬虫速度,需要寻找更稳定更快速的代理。
- 第二,如果爬虫爬不动了,首先要检查一下目标网站的连通度,因为有可能是服务器故障。
- 第三,如果ping的结果不理想,延时很大,tracert结果有助于我们分析是哪一段网络之间发生问题,再去思考详细的解决方案。
4. 代码详解
- 4.1. Import包:
# python 3.6.1
import subprocess
import re
import time
import datetime
import functools
from ftplib import FTP
import os
import requests
import random
- 4.2. 定义配置信息:
# 定义配置信息
domains = ["www.amazon.com", "www.amztracker.com"] # 待测试的域名
target_folder = r"F:\NetworkEnvDaily\\" # 测试结果文件存放位置
ftp_url = "192.168.0.101" # FTP服务器地址
ftp_port = 21 # FTP服务端口号
ftpUploadFolder = "NetworkEnvup" # 文件上传至FTP服务器的位置
ids_req = ["B018A2RRG4", "B002GCJOC0", "0071386211", "B00MHIKRIS"] # 用于构造detaiUrl
useragent = [
'Mozilla/2.0 (compatible; Ask Jeeves/Teoma)',
'Baiduspider ( http://www.baidu.com/search/spider.htm)',
'FAST-WebCrawler/3.8 (crawler at trd dot overture dot com; http://www.alltheweb.com/help/webmaster/crawler)',
'AdsBot-Google ( http://www.google.com/adsbot.html)',
'Mozilla/5.0 (compatible; Googlebot/2.1; http://www.google.com/bot.html)'
]
- 4.3. 定义装饰器,计算函数执行时间:
# 装饰器
def timeDecorator(func):
'''
装饰器,记录函数的执行时间
:param func:
:return:
'''
@functools.wraps(func) # 方便调试,堆栈能显示真实的func name,而不是wrapper
def wrapper(*args, **kwargs):
startTime = datetime.datetime.now()
print(f"Enter func:{func.__name__} at {startTime}")
res = func(*args, **kwargs)
endTime = datetime.datetime.now()
print(f"Leave func:{func.__name__} at {endTime}, usedTime: {endTime-startTime}")
return res
return wrapper
- 4.4. 定义Log处理和url构造函数:
# 处理Log
def myHandleLog(toSave, log):
'''
保存Log,用于写到文件中,并打印log。因为str是不可变量
:param toSave:
:param log:
:return:
'''
toSave += log
toSave += '\n'
print(log)
return toSave
def getUrlsFromIds(domain, ids_lst):
'''
构造url,amazon商品详情页url格式:www.amazon.com/dp/ASIN_ID
:param domain: domain of amazon
:param ids_lst: batch operator
:return:
'''
urls_lst = [f"http://{domain}/dp/{ID}" for ID in ids_lst]
return urls_lst
- 4.5. 定义 ping ip_address 的函数:
# Ping IP 测试网络连通度
@timeDecorator
def get_ping_result(ip_address):
'''
测试目标网站的连通度,也测试本地到目标站的网速。
:param ip_address: ping ip_address
:return:
'''
p = subprocess.Popen(["ping.exe", ip_address],
stdin = subprocess.PIPE,
stdout = subprocess.PIPE,
stderr = subprocess.PIPE,
shell = True)
cmdOut = p.stdout.read().decode('gbk') # 在Windows上需要用gbk解码,python默认utf-8,会出现乱码
# 定义正则表达式,筛选数字,提取连通率信息
re_receive = "已接收 = \d"
re_lost = "丢失 = \d"
re_ip = "来自 [\d\.]+"
match_receive = re.search(re_receive, cmdOut)
match_lost = re.search(re_lost, cmdOut)
match_ip = re.search(re_ip, cmdOut)
receive_count = -1
if match_receive:
receive_count = int(match_receive.group()[6:])
lost_count = -1
if match_lost:
lost_count = int(match_lost.group()[5:])
re_ip = "127.0.0.1"
if match_ip:
re_ip = match_ip.group()[3:]
# 接受到的反馈大于0,表示网络通,提取延时信息
if receive_count > 0:
re_min_time = '最短 = \d+ms'
re_max_time = '最长 = \d+ms'
re_avg_time = '平均 = \d+ms'
match_min_time = re.search(re_min_time, cmdOut)
min_time = int(match_min_time.group()[5:-2])
match_max_time = re.search(re_max_time, cmdOut)
max_time = int(match_max_time.group()[5:-2])
match_avg_time = re.search(re_avg_time, cmdOut)
avg_time = int(match_avg_time.group()[5:-2])
return [re_ip, receive_count, lost_count, min_time, max_time, avg_time]
else:
print(f"网络不通,{ip_address}不可达")
return ["127.0.0.1", 0, 9999, 9999, 9999, 9999]
- 4.6. 定义 tracert ip_address 的函数:
# tracert IP 查看各网络节点连通情况
@timeDecorator
def