今天上半年为了满足客户网站的排名需求,在大环境不好的情况下开辟一些新客户,公司特别组织我们几个资深研发人员成立了一个研发小组,来专门研发了这款网站SEO网站排名刷量工具,目的是帮助客户网站迅速提升热度和关键词排名,网站前期访问量少可以帮助客户提升网站流量,网站中期内容建设差不多了帮助客户提升关键词排名。研发过程中还是踩了不少的雷,现在把排名刷量功能实现过程中踩过的一些坑分享出来,避免大家穿新鞋走老路。
坑1、动态切换Ip
SEO网站排名刷量代码中的动态切换IP代码是为了应对搜索引擎反爬虫模拟真实用户访问而设计的一段代码,这段代码需要运行在ADSL服务器上才能起到切换Ip的效果,这段其实没啥技术难度,宽带信息从对应配置文件中读取,包括3个信息:宽带名称、登陆账号和登陆密码。但有几个细节要注意,这几个细节主要是为了保证重新拨号功能代码的稳定性,其实都是由于ADSL拨号技术的局限性造成的。
细节1:拨号断开和重新拨号之间的时间间隔,这个时间间隔可以设置为3~5秒,一般都不超过10秒,如果时间间隔过短,可能会导致重新包好失败
细节2:重新拨号连接成功后也要等待几秒,再去执行刷量操作,一般也不超过10秒,如果时间间隔过短,可能会导致后续刷量代码执行失败
细节3:有时候会出现第一次重新拨号失败的情况,这时候可以再重新尝试一次
# 动态切换IP
def switchIp():
# 断开连接
stopADSL()
# 等待10秒再重新连接,10秒防止间隔过快
runIdleSomeTime(10)
# 重新连接
runADSL()
# 连接成功10秒后再进行操作
runIdleSomeTime(10)
# 通过ADSL拨号上网
def runADSL():
name = adsler.getValueByKey("name")
user = adsler.getValueByKey("user")
pwd = adsler.getValueByKey("pwd")
p = myPopen("Rasdial %s %s %s"%(name,user,pwd))
my_logger_info(logger, p)
if "错误" in p: #如果发生连接错误,重试一次
runIdleSomeTime(10)
p = myPopen("Rasdial %s %s %s"%(name,user,pwd))
if "错误" in p:
raise Exception("ADSL重新连接发生错误")
# 断开ADSL拨号上网
def stopADSL():
try:
name = adsler.getValueByKey("name")
p = myPopen("Rasdial %s /disconnect"%(name))
my_logger_info(logger, p)
except Exception as e:
info = traceback.format_exc()
my_logger_info(logger, info)
坑2、浏览器占用内存过多
SEO网站排名刷量代码中的第一段就是要通过selenium框架来创建浏览器,然后在浏览器中进行搜索查询,现在流行的浏览器当然非chrome莫属,但chrome浏览器的缺点是开的标签页越多占用的内存越多,这就要求你的服务器内存配置就要高,否则跑着跑着服务器内存就不够用了,这就意味着你的服务器成本要增加。为了节省成本后来就选用了Phantomjs浏览器,好处是无界面占用内存小,chrome浏览器虽然现在也出了headless无界面版本,但我们测试后发现标签页开多了内存占用还是很多。chrome浏览器可以用来做测试程序,因为模拟访问过程都能看得见。
下面为创建Chrome浏览器的代码:
#创建Chrome浏览器
def createChromeWebDriver():
# 配置参数
options = webdriver.ChromeOptions()
# 手动指定使用的浏览器位置
# options.binary_location = r"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe"
# 设置网页编码
options.add_argument('lang=zh_CN.UTF-8')
# 禁止加载图片
options.add_argument('blink-settings=imagesEnabled=false')
# 禁用sandbox
options.add_argument('--no-sandbox')
# 禁用显卡
options.add_argument('--disable-gpu')
# 无界面模式
# options.add_argument('--headless')
# 禁用浏览器正在被自动化程序控制的提示,目前看起来没啥用
# options.add_argument('--disable-infobars')
# # 设置不同请求头
# useragent=['--User-Agent=Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:34.0) Gecko/20100101 Firefox/34.0',
# '--User-Agent=Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6',
# '--User-Agent=Mozilla/5.0 (Windows NT 6.2) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.12 Safari/535.11',
# '--User-Agent=Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0)',
# '--User-Agent=MozillaOnRunButtonClickNewThread/5.0 (X11; Ubuntu; Linux x86_64; rv:40.0) Gecko/20100101 Firefox/40.0',
# '--User-Agent=Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/44.0.2403.89 Chrome/44.0.2403.89 Safari/537.36']
# options.add_argument(useragent[random.randint(0,len(useragent)-1)])
# ua=getPcUserAgent()
# options.add_argument('--User-Agent=%s'%(ua))
# # 使用代理IP
# ip=getProxyId()
# logger.info("proxyIp:%s" % ip)
# options.add_argument('--proxy-server=http://%s' % ip)
driver = webdriver.Chrome(options=options, keep_alive=None)
# 防止selenium访问被识别出来,不算流量
driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
"source": """
Object.defineProperty(navigator, 'webdriver', {
get: () => undefined
})
"""
})
return driver
下面为创建Phantomjs浏览器的代码:
#创建Phantomjs浏览器
def createPhantomjsWebDriver():
# 调用环境变量指定的PhantomJS浏览器,创建浏览器对象
# driver = webdriver.PhantomJS()
# 如果没有在环境变量指定的phantomjs的位置
# 伪装成chrome,防止被反爬虫
cap = webdriver.DesiredCapabilities.PHANTOMJS
ua=getPcUserAgent()
cap["phantomjs.page.settings.userAgent"] = ua
cap["phantomjs.page.customHeaders.User-Agent"] = ua
# cap["phantomjs.page.settings.resourceTimeout"] = 1000*60*5
# 禁用缓存
cap["phantomjs.page.settings.disk-cache"] = False
# 不载入图片,爬页面速度会快很多
cap["phantomjs.page.settings.loadImages"] = False
driver=webdriver.PhantomJS (executable_path="./phantomjs.exe",desired_capabilities=cap)
# 设置页面加载超时时间
driver.set_page_load_timeout(60)
return driver
坑3、网站反爬虫应对
SEO网站排名刷量代码中访问客户网站那一段代码,在运行过程中最容易出现问题,就是触发了客户网站的发爬虫机制,因为现在客户网站一般都安装了防攻击软件,所以频繁的对网站访问很容易触发网站防攻击软件的防御机制,因此在代码中要对相关异常进行处理,避免刷量程序因为这些异常(例如ConnectionRefusedError,NewConnectionError,MaxRetryError)而中断执行。网站的防御机制被触发的表现一般是网站禁止你访问不让你跟它建立连接。处理这些异常的代码如下:
try:
wd_s_ary=wdary[n].split(":")
wd_hour=wd_s_ary[0] #几点开始搜索该关键词
wd_name=wd_s_ary[1] #关键词名称
wd_site=wd_s_ary[2] #对应网站url
hourstr = getNowHourStr() #获取当前小时点
if int(wd_hour) < int(hourstr):
continue
elif int(wd_hour) == int(hourstr):
pass
elif int(wd_hour) > int(hourstr):
while int(wd_hour) > int(hourstr) and not myframe.stop_refresh_page_thread:
runIdleSomeTime(60)
hourstr = getNowHourStr()
# 支持人工停止刷量
if (myframe.stop_refresh_page_thread):
break
.....
except (ConnectionRefusedError,NewConnectionError,MaxRetryError,TimeoutException) as e :
info = traceback.format_exc()
my_logger_info(logger, info)
# 连接异常处理
# 以下为被百度服务器或者网站服务器积极拒绝,无法连接异常现象的处理手段
# 关闭浏览器
driver.quit()
driver = None
# 切换IP
switchIp()
# 重新启动浏览器
driver = createPhantomjsWebDriver()
# 异常处理完成后,等待20~30秒后,再进行下一个词的搜索
runIdleSomeTime(random.randint(20,30))
其他
在程序运行过程中,还有几点要做到,这样后期运营起来才会比较省心。
点1:要注意记录各台服务器上的刷量日志,以便于统计各个关键词的刷量数量和排名
点2:能够自动分发任务到各台执行服务器机子上,这样就可以随时增加/编辑刷量任务
点3:程序运行过程中,遇到不可预见的异常导致程序中断,要发送异常邮件给运营人员
最后
欢迎各位同学留言沟通探讨。