python绕过图片滑动验证码实现爬取PTA所有题目功能 附源码

python教程

共 4141字,需浏览 9分钟

 ·

2021-01-13 01:40

这篇文章主要介绍了python绕过图片滑动验证码实现爬取PTA所有题目 附源码,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

最近学了python爬虫,本着学以致用的态度去应用在生活中。突然发现算法的考试要来了,范围就是PTA刷过的题。让我一个个复制粘贴?不可能,必须爬它!

先开页面,人傻了,PTA的题目是异步加载的,爬了个寂寞(空数据)。AJAX我又不熟,突然想到了selenium。

selenium可以模拟人的操作让浏览器自动执行动作,具体的自己去了解,不多说了。干货来了:

登录界面有个图片的滑动验证码

破解它的最好方式就是用opencv,opencv巨强,自己了解。
思路开始:
1.将背景图片和可滑动的图片下载
2.用opencv匹配这两张图片的最匹配位置,不用在意怎么实现的,算法极其BT,不是我这种数学不及格的人能想的。最终会得到一个匹配度最高的XY值
3.由于Y值不用考虑,拖动滑块是X值的事情,调用selenium里抓放的函数,把X值丢进去,让浏览器自动滑动即可。
注意:由于算法问题,可能不能一次成功,重启程序就行了,或者改动代码。
4.进去之后就用selenium各种操作爬就完事了
以下是源码:

  1. from selenium import webdriver

  2. from selenium.webdriver.common.action_chains import ActionChains

  3. import requests

  4. import time

  5. import numpy

  6. import cv2

  7. import os

  8.  

  9. #作者:许文鸿

  10. #未经允许不可转载,转载时注明出处

  11.  

  12. #创建 WebDriver 对象,指明使用chrome浏览器驱动

  13. web = webdriver.Chrome(r'd:\chromedriver.exe')

  14. web.implicitly_wait(5)

  15. #调用WebDriver 对象的get方法 可以让浏览器打开指定网址

  16. web.get('https://pintia.cn/auth/login')

  17. zh = web.find_element_by_xpath('/html/body/div[1]/div[3]/div/div[2]/form/div[1]/div[1]/div/div/div[1]/input')

  18. mm = web.find_element_by_xpath('/html/body/div[1]/div[3]/div/div[2]/form/div[1]/div[2]/div/div/div[1]/input')

  19.  

  20. #在PTA的账号密码:

  21. zh.send_keys('******@qq.com')

  22. mm.send_keys('******')

  23. #找到登录按钮并点击

  24. web.find_element_by_xpath('/html/body/div[1]/div[3]/div/div[2]/form/div[2]/button/div/div').click()

  25. #等待两秒,验证码加载完成

  26. time.sleep(2)

  27. #bg背景图片

  28. bg_img_src = web.find_element_by_xpath(

  29. '/html/body/div[3]/div[2]/div/div/div[2]/div/div[1]/div/div[1]/img[1]').get_attribute('src')

  30. #front可拖动图片

  31. front_img_src = web.find_element_by_xpath(

  32. '/html/body/div[3]/div[2]/div/div/div[2]/div/div[1]/div/div[1]/img[2]').get_attribute('src')

  33. #保存图片

  34. with open("bg.jpg", mode="wb") as f:

  35. f.write(requests.get(bg_img_src).content)

  36. with open("front.jpg", mode="wb") as f:

  37. f.write(requests.get(front_img_src).content)

  38. #将图片加载至内存

  39. bg = cv2.imread("bg.jpg")

  40. front = cv2.imread("front.jpg")

  41. js = 'alert("本人可能将此程序用于python课设,请靓仔靓女不要直接提交本人代码。即将报错,需要删除第42~44行代码即可正常运行");'

  42. web.execute_script(js)

  43. time.sleep(15)

  44. #将背景图片转化为灰度图片,将三原色降维

  45. bg = cv2.cvtColor(bg, cv2.COLOR_BGR2GRAY)

  46. #将可滑动图片转化为灰度图片,将三原色降维

  47. front = cv2.cvtColor(front, cv2.COLOR_BGR2GRAY)

  48. front = front[front.any(1)]

  49. #用cv算法匹配精度最高的xy值

  50. result = cv2.matchTemplate(bg, front, cv2.TM_CCOEFF_NORMED)

  51. #numpy解析xy,注意xy与实际为相反,x=y,y=x

  52. x, y = numpy.unravel_index(numpy.argmax(result), result.shape)

  53. #找到可拖动区域

  54. div = web.find_element_by_xpath('/html/body/div[3]/div[2]/div/div/div[2]/div/div[2]/div[2]')

  55. #拖动滑块,以实际相反的y值代替x

  56. ActionChains(web).drag_and_drop_by_offset(div, xoffset=// 0.946, yoffset=0).perform()

  57.  

  58. #至此成功破解验证码,由于算法问题,准确率不能达到100%,可能需要多运行1~2次

  59.  

  60. for page in range(0, 1000):

  61. time.sleep(1)

  62. #此处的网址为PTA固定网页,仅需要更换page

  63. web.get('https://pintia.cn/problem-sets?tab=1&filter=all&page={page_}'.format(page_=page))

  64. #获取当前页面题目集网址,A_s为a标签的列表,urls用户存放网址

  65. A_s = web.find_elements_by_class_name('name_QIjv7')

  66. urls = []

  67. for a in A_s:

  68. urls.append(a.get_attribute('href'))

  69. #当页面不存在可爬取的网址,则退出程序

  70. if urls.__len__() == 0:

  71. print('爬取完成')

  72. os._exit()

  73. #对刚才获取的网址列表进行遍历

  74. for url in urls:

  75. web.get(url)

  76. #找到对应的题目对象

  77. tm = web.find_elements_by_css_selector("[class='problemStatusRect_3kpmC PROBLEM_ACCEPTED_1Dzzi']")

  78. tm_total = 0

  79. for i in range(0, 1000):

  80. # 遍历该页面的题型

  81. try:

  82. tm_type = web.find_element_by_xpath(

  83. '/html/body/div/div[3]/div[2]/div/div[2]/div[{i_}]/div/div[2]'.format(i_=* 2 + 2)).text

  84. # 如果题型为编程/函数,记录对应的数量,方便后续爬取

  85. if tm_type == '编程题' or tm_type == '函数题':

  86. tm_total += int(web.find_element_by_xpath(

  87. '/html/body/div/div[3]/div[2]/div/div[2]/div[{i_}]/a/div/div'.format(i_=* 2 + 2)).text[0])

  88. except:

  89. break

  90. # 根据函数/编程题数量取相应的题目对象,舍弃其他题目

  91. if tm_total != 0:

  92. tm = tm[-tm_total:]

  93. else:

  94. tm = []

  95. # 遍历剩余题目

  96. for tm_index in tm:

  97. try:

  98. tm_index.click()

  99. time.sleep(0.5)

  100. #获取题目中的代码

  101. tm_title = web.find_element_by_css_selector(

  102. "[class='text-center black-3 text-4 font-weight-bold my-3']").text

  103. mycode = web.find_element_by_css_selector('textarea').get_attribute('value')

  104. print('题目:' + tm_title)

  105. print(mycode)

  106. #接下来可以存入

  107. except:

  108. continue

到此这篇关于python绕过图片滑动验证码实现爬取PTA所有题目功能 附源码的文章就介绍到这了

  1. 扫下方二维码加老师微信

  2. 或是搜索老师微信号:XTUOL1988【切记备注学习Python】

  3. 领取Python web开发,Python爬虫,Python数据分析,人工智能等学习教程。带你从零基础系统性的学好Python!

  4. 欢迎大家点赞,留言,转发,转载,感谢大家的相伴与支持

    万水千山总是情,点个【在看】行不行

  5. *声明:本文于网络整理,版权归原作者所有,如来源信息有误或侵犯权益,请联系我们删除或授权事

浏览 46
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报