在全国企业信用信息系统中搜索信息时,可以看到以下验证码:
破解思路:
1.从div中或取乱序的图片及坐标,乱序图片如下图:
2.根据获取到的乱序图片及坐标将图片拼完整,如下图:
,
3.计算两张图片的像素差,并计算缺口位置,如下图:
4.根据缺口位置模拟人的行为拖动滑块
具体代码如下:
def get_merge_image(filename,location_list): ''' 根据位置对图片进行合并还原 :filename:图片 :location_list:图片位置 ''' pass im = image.open(filename) new_im = image.new('RGB', (260,116)) im_list_upper=[] im_list_down=[] for location in location_list: if location['y']==-58: pass im_list_upper.append(im.crop((abs(location['x']),58,abs(location['x'])+10,166))) if location['y']==0: pass im_list_down.append(im.crop((abs(location['x']),0,abs(location['x'])+10,58))) new_im = image.new('RGB', (260,116)) x_offset = 0 for im in im_list_upper: new_im.paste(im, (x_offset,0)) x_offset += im.size[0] x_offset = 0 for im in im_list_down: new_im.paste(im, (x_offset,58)) x_offset += im.size[0] return new_im def get_image(driver,div): ''' 下载并还原图片 :driver:webdriver :div:图片的div ''' pass #找到图片所在的div background_images=driver.find_elements_by_xpath(div) location_list=[] imageurl='' for background_image in background_images: location={} #在html里面解析出小图片的url地址,还有长高的数值 location['x']=int(re.findall("background-image: url\((\S+)\); background-position: (.*)px (.*)px;",background_image.get_attribute('style'))[0][1]) location['y']=int(re.findall("background-image: url\((\S+)\); background-position: (.*)px (.*)px;",background_image.get_attribute('style'))[0][2]) imageurl=re.findall("background-image: url\((\S+)\); background-position: (.*)px (.*)px;",background_image.get_attribute('style'))[0][0] location_list.append(location) imageurl=imageurl.replace("webp","jpg") image_bytes = urllib.request.urlopen(imageurl).read() data_stream = BytesIO(image_bytes) jpgfile = Image.open(data_stream) jpgfile.save("%s.png" % 'rr') #重新合并图片 image=get_merge_image("rr.png",location_list ) return image # 计算缺口位置 def getlocation(image3): for i in range(5,260): for j in range(0,116): pixel1 = image3.getpixel((i, j)) if(pixel1[0]>100 or pixel1[1]>100): return i # 获取图片并计算缺口位置 def getImgAndLoc(driver): # 下载图片 image1 = get_image(driver, "//div[@class='gt_cut_bg gt_show']/div") image2 = get_image(driver, "//div[@class='gt_cut_fullbg gt_show']/div") image3 = ImageChops.difference(image1, image2) image1.save("%s.png" % '3') image2.save("%s.png" % '4') image3.save("%s.png" % '5') loc = getlocation(image3) print("缺口位置:", loc) return loc # 移动滑块 def mourse(driver,element,loc): action = ActionChains(driver) action.move_to_element(to_element=element).perform() action.click_and_hold(element).perform() # 鼠标左键按下不放 action.reset_actions() id = random.randint(0, 2) print('track==%d'%id) #将图片划分成几个区域,对不同区域使用不同的行为数据,进一步提高通过率 if loc <= 75: moveStep = gehostMouse.read_txt('./trackData/1_%d.txt' % id) elif loc > 75 and loc <= 100: moveStep = gehostMouse.read_txt('./trackData/2_%d.txt' % id) elif loc > 100 and loc <= 150: moveStep = gehostMouse.read_txt('./trackData/3_%d.txt' % id) elif loc > 150 and loc <= 200: moveStep = gehostMouse.read_txt('./trackData/4_%d.txt' % id) else: moveStep = gehostMouse.read_txt('./trackData/5_%d.txt' % id) countStep = 0 idx = 0 while countStep <= loc-5 and idx < len(moveStep): # print(moveStep[idx][0], moveStep[idx][1], moveStep[idx][2]) action.move_by_offset(moveStep[idx][0], moveStep[idx][1]).perform() # 移动一个位移 action.reset_actions() time.sleep(moveStep[idx][2]) # 等待停顿时间 countStep += moveStep[idx][0] idx += 1 # countStep-=moveStep[idx-1][0] print(countStep) subStep = loc-5-countStep print("subStep=",subStep) while subStep <0: rd=random.randint(-2,-1) action.move_by_offset(rd, 0).perform() action.reset_actions() subStep-=rd time.sleep(random.randint(5, 10) / 100) action.release().perform() # 鼠标左键松开 action.reset_actions()
说明:
1.滑块滑动距离=缺口位置-5 的原因是滑块的位置相对于缺口位置的计算距离来说,滑块初始位置离图片最左边大约距离5个像素距离。
2.验证码破解的难点是模拟人的行为数据,滑太快或太慢都不行,人的行为是一个慢-快-慢的过程,因此我通过获取自己滑动验证码的行为数据,生成了以下形式的几组数据:
第一列是x方向的偏移量,第二列是y方向的偏移量,第三列为耗时。可以使用GhostMouse获取鼠标行为数据。
GhostMouse获取鼠标偏移量数据代码如下:
import os # xyd_typical = (1,0,0.04) def read_rms(file_rms,file_txt): with open(file_rms) as fp: # os.path.sep LMouse_down = False for line in fp: if 'LMouse down' in line or (LMouse_down == True and 'Move' in line): if 'LMouse down' in line: LMouse_down = True xyd_records = [] x_last, y_last = 0, 0 # 保证第一个偏移量为实际开始位置 xy_pos = line.split('(')[1].split(')')[0].split(',') x_pos, y_pos = [int(i) for i in xy_pos] continue if LMouse_down == True and 'Delay' in line: x_delta, y_delta = x_pos - x_last, y_pos - y_last if x_delta == 0 and y_delta == 0 and len(xyd_records) != 0: # len 可能起点就是0,0 continue else: delay = float(line.split(' ')[1].split('}')[0]) xyd_records.append((x_delta, y_delta, delay)) x_last, y_last = x_pos, y_pos continue # {LMouse up (790,659)} if LMouse_down == True and 'LMouse up' in line: # x_init y_init x_change y_change # x y d 每一次偏移量 # x y d with open(file_txt, 'a') as fh_txt: # x_change = sum(x for x,y,d in xyd_records) x_init = xyd_records[0][0] y_init = xyd_records[0][1] x_change = sum(x for x, y, d in xyd_records[1:]) y_change = sum(y for x, y, d in xyd_records[1:]) fh_txt.write('{} {} {} {}\n'.format(x_init, y_init, x_change, y_change)) # 加os.linesep是'\r\n' for x, y, d in xyd_records[1:]: # 第一个记录为起始位置,value记录之后的每一次偏移 fh_txt.write('{} {} {}\n'.format(x, y, d)) LMouse_down = False xyd_records = [] def read_txt(file_txt): with open(file_txt, 'r') as fp: result = [] # (x_init, y_init, x_change, y_chang): [(x0,y0,d0), (x1,y1,d1)...] # i=0; for line in fp: line = line.strip().split() if len(line) == 3: x, y, d = line x, y, d = int(x), int(y), float(d) tp=(x,y,d) result.append(tp) return result def main(): # file_rms = os.path.join(os.path.abspath('.'), 'night.rms') file_txt = os.path.join(os.path.abspath('.'), 'mouse.txt') # read_rms(file_rms,file_txt) result = read_txt(file_txt) for k, v in result.items(): print(k,v) if __name__ == '__main__': pass main()
当然也可以通过request方式模拟请求破解验证码,但需要的参数需要通过其js文件才能搞明白,现在的js文件都加密了,目前能力解决不了。(可参考:http://www.jianshu.com/p/3726581d218a)
相关推荐
linux 开源爬虫 phantomjs-1.9.7 32/64位
Python 爬虫可用 phantomjs-2.1.1-windows.rar phantomjs 的windows 支持程序
python爬虫技术用到的phantomjs驱动,无界面化的浏览器访问
该PPT介绍了Python爬虫在爬取动态网页方面会用到的软件PhantomJS, Selenium, 以及AutoIt. 欢迎对爬虫有兴趣的童鞋进行下载哈,本人亲自制作的PPT~~
这是基于Selenium和PhantomJs的Python爬虫,具体可以参考我的博客:http://blog.csdn.net/ProgramChangesWorld/article/details/59489406
需要的添加的jar包及工具:我这里使用maven来构建项目,添加依赖如下: <groupId>org.seleniumhq.selenium ...python版使用webdriver+PhantomJs爬虫使用,参考http://www.cnblogs.com/kuqs/p/6395284.html
利用casperjs +phantomjs实现登录抓取网页 并且截图;下载后解压后,在环境变量path中配置解压后bin目录的地址,如:E:\Program Files\casperjs\bin;E:\Program Files\phantomjs\bin
基于CasperJS和PhantomJS,可以自动渲染网页、动态解析js,支持ajax和各类前端交互。 代码基于phantomjs爬虫小记 by wils0n ,在tuicool上也有这篇文章http://www.tuicool.com/articles/JbEfIvV , 原作者的代码在...
本课程使用java作为编程语言,主要内容包括爬虫的基本原理,使用Phantomjs技术抓取拉钩企业招聘信息进行系统分析、Phantomjs的详细使用方法,如何使用Phantomjs分析html代码,基于队列的爬虫、数据存储、数据拆分、...
PhantomJS是一个基于webkit的JavaScript API。它使用QtWebKit作为它核心浏览器的功能,使用webkit来编译解释执行JavaScript代码。任何你可以在基于webkit浏览器做的事情,它都能做到。它不仅是个隐形的浏览器,提供...
phantomJS jar包 1.2.1版本 适用于python爬虫 抓取网页
最新的 phantomjs-2.1.1-macosx.zip For this static build, the binary is self-contained with no external dependency. It will run on a fresh install of OS X 10.7 (Lion) or later versions. There is no ...
phantomjs2.1.1安装包以及生成图片中遇到中文需要安装的字体包 运行于本地或者正式环境上需要安装这些软件
基于python+phantomjs开发的百度文库爬虫.zip 基于python+phantomjs开发的百度文库爬虫.zip 基于python+phantomjs开发的百度文库爬虫.zip 基于python+phantomjs开发的百度文库爬虫.zip
爬虫简介: WebCollector是一个无须配置、便于二次开发的JAVA爬虫框架(内核),它提供精简的的API,只需少量代码即可实现一个功能强大的爬虫。 爬虫内核: WebCollector致力于维护一个稳定、可扩的爬虫内核,...
完成PhantomJS安装配置完成之后,下面进行简单的入门操作。首先通过一个小例子来演示PhantomJS,在电脑上新建一个JavaScript文件,在里面输入代码: console.log('Hello, world!'); phantom.exit(); 在命令行输入:...
无界面浏览器 爬虫使用的无界面浏览器 爬虫使用的无界面浏览器 爬虫使用的无界面浏览器 爬虫使用的无界面浏览器 爬虫使用的无界面浏览器 爬虫使用的
8. phantomjs_win 9. phantomjs_mac 10.phantomjs_linux 验证程序(以Opera为例) from selenium import webdriver import time browser = webdriver.Opera() browser.get('http://www.baidu.com/') browser.find_...
毕业设计-基于mysql和solr采用phantomjs实现网页内容爬虫
PhantomJS浏览器