经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » Python » 查看文章
Python实现网页截图(PyQT5)过程解析
来源:jb51  时间:2019/8/13 8:54:10  对本文有异议

方案说明

功能要求:实现网页加载后将页面截取成长图片

涉及模块:PyQT5 PIL

逻辑说明:

1:完成窗口设置,利用PyQT5 QWebEngineView加载网页地址,待网页加载完成后,调用check_pag;

  1. class MainWindow(QMainWindow):
  2. def __init__(self, parent=None):
  3. super(MainWindow, self).__init__(parent)
  4. self.setWindowTitle('易哈佛')
  5. self.temp_height = 0
  6. self.setWindowFlag(Qt.WindowMinMaxButtonsHint, False) # 禁用最大化,最小化
  7. # self.setWindowFlag(Qt.WindowStaysOnTopHint, True) # 窗口顶置
  8. self.setWindowFlag(Qt.FramelessWindowHint, True) # 窗口无边框
  9. def urlScreenShot(self, url):
  10. self.browser = QWebEngineView()
  11. self.browser.load(QUrl(url))
  12. geometry = self.chose_screen()
  13. self.setGeometry(geometry)
  14. self.browser.loadFinished.connect(self.check_page)
  15. self.setCentralWidget(self.browser)
  16. def get_page_size(self):
  17. size = self.browser.page().contentsSize()
  18. self.set_height = size.height()
  19. self.set_width = size.width()
  20. return size.width(), size.height()
  21. def chose_screen(self):
  22. width, height = 750, 1370
  23. desktop = QApplication.desktop()
  24. screen_count = desktop.screenCount()
  25. for i in range(0, screen_count):
  26. rect = desktop.availableGeometry(i)
  27. s_width, s_height = rect.width(), rect.height()
  28. if s_width > width and s_height > height:
  29. return QRect(rect.left(), rect.top(), width, height)
  30. return QRect(0, 0, width, height)
  31. if __name__ == '__main__':
  32. app = QApplication(sys.argv)
  33. win = MainWindow()
  34. win.show()
  35. app.exit(app.exec_())

2:收集页面高度,并计算分次截屏的次数和余量高度;实例化图片合并工具,设置定时器,超时信号发出后,执行exe_command;

  1. def check_page(self):
  2. p_width, p_height = self.get_page_size()
  3. self.page, self.over_flow_size = divmod(p_height, self.height())
  4. if self.page == 0:
  5. self.page = 1
  6. self.ssm = ScreenShotMerge(self.page, self.over_flow_size)
  7. self.timer = QTimer(self)
  8. self.timer.timeout.connect(self.exe_command)
  9. self.timer.setInterval(400)
  10. self.timer.start()

3:exe_command用来控制截图次数,并在每次截图完成后控制网页向下滑屏幕的高度;所有的页面都已截取时,完成图片合并。

  1. def exe_command(self):
  2. if self.page > 0:
  3. self.screen_shot()
  4. self.run_js()
  5. elif self.page < 0:
  6. self.timer.stop()
  7. self.ssm.image_merge()
  8. self.close()
  9. elif self.over_flow_size > 0:
  10. self.screen_shot()
  11. self.page -= 1
  12. def run_js(self):
  13. script = """
  14. var scroll = function (dHeight) {
  15. var t = document.documentElement.scrollTop
  16. var h = document.documentElement.scrollHeight
  17. dHeight = dHeight || 0
  18. var current = t + dHeight
  19. if (current > h) {
  20. window.scrollTo(0, document.documentElement.clientHeight)
  21. } else {
  22. window.scrollTo(0, current)
  23. }
  24. }
  25. """
  26. command = script + '\n scroll({})'.format(self.height())
  27. self.browser.page().runJavaScript(command)

4:screen_shot在每次截图完成后将图片保存,并将图片对象由图片合并根据保存到列表中。

  1. def screen_shot(self):
  2. screen = QApplication.primaryScreen()
  3. winid = self.browser.winId()
  4. pix = screen.grabWindow(int(winid))
  5. name = '{}/temp.png'.format(self.ssm.root_path)
  6. pix.save(name)
  7. self.ssm.add_im(name)

5:截图合并工具,在每次截图完成后将图片对象保存,完成余量截图的重绘和截图的合并。

  1. class ScreenShotMerge():
  2. def __init__(self, page, over_flow_size):
  3. self.im_list = []
  4. self.page = page
  5. self.over_flow_size = over_flow_size
  6. self.get_path()
  7.  
  8. def get_path(self):
  9. self.root_path = Path(__file__).parent.joinpath('temp')
  10. if not self.root_path.exists():
  11. self.root_path.mkdir(parents=True)
  12. self.save_path = self.root_path.joinpath('merge.png')
  13.  
  14. def add_im(self, path):
  15. if len(self.im_list) == self.page:
  16. im = self.reedit_image(path)
  17. else:
  18. im = Image.open(path)
  19. im.save('{}/{}.png'.format(self.root_path, len(self.im_list) + 1))
  20. self.im_list.append(im)
  21.  
  22. def get_new_size(self):
  23. max_width = 0
  24. total_height = 0
  25. # 计算合成后图片的宽度(以最宽的为准)和高度
  26. for img in self.im_list:
  27. width, height = img.size
  28. if width > max_width:
  29. max_width = width
  30. total_height += height
  31. return max_width, total_height
  32.  
  33. def image_merge(self, ):
  34. if len(self.im_list) > 1:
  35. max_width, total_height = self.get_new_size()
  36. # 产生一张空白图
  37. new_img = Image.new('RGB', (max_width - 15, total_height), 255)
  38. x = y = 0
  39. for img in self.im_list:
  40. width, height = img.size
  41. new_img.paste(img, (x, y))
  42. y += height
  43. new_img.save(self.save_path)
  44. print('截图成功:', self.save_path)
  45. else:
  46. obj = self.im_list[0]
  47. width, height = obj.size
  48. left, top, right, bottom = 0, 0, width, height
  49. box = (left, top, right, bottom)
  50. region = obj.crop(box)
  51. new_img = Image.new('RGB', (width, height), 255)
  52. new_img.paste(region, box)
  53. new_img.save(self.save_path)
  54. print('截图成功:', self.save_path)
  55.  
  56. def reedit_image(self, path):
  57. obj = Image.open(path)
  58. width, height = obj.size
  59. left, top, right, bottom = 0, height - self.over_flow_size, width, height
  60. box = (left, top, right, bottom)
  61. region = obj.crop(box)
  62. return region

截图功能完整代码

  1. #!/usr/bin/env python
  2. # -*- coding:UTF-8 -*-
  3. # Author:Leslie-x
  4. import sys
  5. from PyQt5.QtCore import *
  6. from PyQt5.QtWidgets import *
  7. from PyQt5.QtWebEngineWidgets import *
  8. from PIL import Image
  9. from pathlib import Path
  10. class ScreenShotMerge():
  11. def __init__(self, page, over_flow_size):
  12. self.im_list = []
  13. self.page = page
  14. self.over_flow_size = over_flow_size
  15. self.get_path()
  16. def get_path(self):
  17. self.root_path = Path(__file__).parent.joinpath('temp')
  18. if not self.root_path.exists():
  19. self.root_path.mkdir(parents=True)
  20. self.save_path = self.root_path.joinpath('merge.png')
  21. def add_im(self, path):
  22. if len(self.im_list) == self.page:
  23. im = self.reedit_image(path)
  24. else:
  25. im = Image.open(path)
  26. im.save('{}/{}.png'.format(self.root_path, len(self.im_list) + 1))
  27. self.im_list.append(im)
  28. def get_new_size(self):
  29. max_width = 0
  30. total_height = 0
  31. # 计算合成后图片的宽度(以最宽的为准)和高度
  32. for img in self.im_list:
  33. width, height = img.size
  34. if width > max_width:
  35. max_width = width
  36. total_height += height
  37. return max_width, total_height
  38. def image_merge(self, ):
  39. if len(self.im_list) > 1:
  40. max_width, total_height = self.get_new_size()
  41. # 产生一张空白图
  42. new_img = Image.new('RGB', (max_width - 15, total_height), 255)
  43. x = y = 0
  44. for img in self.im_list:
  45. width, height = img.size
  46. new_img.paste(img, (x, y))
  47. y += height
  48. new_img.save(self.save_path)
  49. print('截图成功:', self.save_path)
  50. else:
  51. obj = self.im_list[0]
  52. width, height = obj.size
  53. left, top, right, bottom = 0, 0, width, height
  54. box = (left, top, right, bottom)
  55. region = obj.crop(box)
  56. new_img = Image.new('RGB', (width, height), 255)
  57. new_img.paste(region, box)
  58. new_img.save(self.save_path)
  59. print('截图成功:', self.save_path)
  60. def reedit_image(self, path):
  61. obj = Image.open(path)
  62. width, height = obj.size
  63. left, top, right, bottom = 0, height - self.over_flow_size, width, height
  64. box = (left, top, right, bottom)
  65. region = obj.crop(box)
  66. return region
  67. class MainWindow(QMainWindow):
  68. def __init__(self, parent=None):
  69. super(MainWindow, self).__init__(parent)
  70. self.setWindowTitle('易哈佛')
  71. self.temp_height = 0
  72. self.setWindowFlag(Qt.WindowMinMaxButtonsHint, False) # 禁用最大化,最小化
  73. # self.setWindowFlag(Qt.WindowStaysOnTopHint, True) # 窗口顶置
  74. self.setWindowFlag(Qt.FramelessWindowHint, True) # 窗口无边框
  75. def urlScreenShot(self, url):
  76. self.browser = QWebEngineView()
  77. self.browser.load(QUrl(url))
  78. geometry = self.chose_screen()
  79. self.setGeometry(geometry)
  80. self.browser.loadFinished.connect(self.check_page)
  81. self.setCentralWidget(self.browser)
  82. def get_page_size(self):
  83. size = self.browser.page().contentsSize()
  84. self.set_height = size.height()
  85. self.set_width = size.width()
  86. return size.width(), size.height()
  87. def chose_screen(self):
  88. width, height = 750, 1370
  89. desktop = QApplication.desktop()
  90. screen_count = desktop.screenCount()
  91. for i in range(0, screen_count):
  92. rect = desktop.availableGeometry(i)
  93. s_width, s_height = rect.width(), rect.height()
  94. if s_width > width and s_height > height:
  95. return QRect(rect.left(), rect.top(), width, height)
  96. return QRect(0, 0, width, height)
  97. def check_page(self):
  98. p_width, p_height = self.get_page_size()
  99. self.page, self.over_flow_size = divmod(p_height, self.height())
  100. if self.page == 0:
  101. self.page = 1
  102. self.ssm = ScreenShotMerge(self.page, self.over_flow_size)
  103. self.timer = QTimer(self)
  104. self.timer.timeout.connect(self.exe_command)
  105. self.timer.setInterval(400)
  106. self.timer.start()
  107. def exe_command(self):
  108. if self.page > 0:
  109. self.screen_shot()
  110. self.run_js()
  111.  
  112. elif self.page < 0:
  113. self.timer.stop()
  114. self.ssm.image_merge()
  115. self.close()
  116.  
  117. elif self.over_flow_size > 0:
  118. self.screen_shot()
  119. self.page -= 1
  120.  
  121. def run_js(self):
  122. script = """
  123. var scroll = function (dHeight) {
  124. var t = document.documentElement.scrollTop
  125. var h = document.documentElement.scrollHeight
  126. dHeight = dHeight || 0
  127. var current = t + dHeight
  128. if (current > h) {
  129. window.scrollTo(0, document.documentElement.clientHeight)
  130. } else {
  131. window.scrollTo(0, current)
  132. }
  133. }
  134. """
  135. command = script + '\n scroll({})'.format(self.height())
  136. self.browser.page().runJavaScript(command)
  137.  
  138. def screen_shot(self):
  139. screen = QApplication.primaryScreen()
  140. winid = self.browser.winId()
  141. pix = screen.grabWindow(int(winid))
  142. name = '{}/temp.png'.format(self.ssm.root_path)
  143. pix.save(name)
  144. self.ssm.add_im(name)
  145.  
  146. if __name__ == '__main__':
  147. url = 'http://blog.sina.com.cn/lm/rank/focusbang//'
  148. app = QApplication(sys.argv)
  149. win = MainWindow()
  150. win.urlScreenShot(url)
  151. win.show()
  152. app.exit(app.exec_())

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持w3xue。

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号