Python实现网页截图(PyQT5)
方案说明
功能要求:实现网页加载后将页面截取成长图片
涉及模块:PyQT5 PIL
逻辑说明:
1:完成窗口设置,利用PyQT5 QWebEngineView加载网页地址,待网页加载完成后,调用check_pag;
class MainWindow(QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.setWindowTitle('易哈佛')
self.temp_height = 0
self.setWindowFlag(Qt.WindowMinMaxButtonsHint, False) # 禁用最大化,最小化
# self.setWindowFlag(Qt.WindowStaysOnTopHint, True) # 窗口顶置
self.setWindowFlag(Qt.FramelessWindowHint, True) # 窗口无边框 def urlScreenShot(self, url):
self.browser = QWebEngineView()
self.browser.load(QUrl(url))
geometry = self.chose_screen()
self.setGeometry(geometry)
self.browser.loadFinished.connect(self.check_page)
self.setCentralWidget(self.browser) def get_page_size(self):
size = self.browser.page().contentsSize()
self.set_height = size.height()
self.set_width = size.width()
return size.width(), size.height() def chose_screen(self):
width, height = 750, 1370
desktop = QApplication.desktop()
screen_count = desktop.screenCount()
for i in range(0, screen_count):
rect = desktop.availableGeometry(i)
s_width, s_height = rect.width(), rect.height()
if s_width > width and s_height > height:
return QRect(rect.left(), rect.top(), width, height)
return QRect(0, 0, width, height) if __name__ == '__main__':
app = QApplication(sys.argv)
win = MainWindow()
win.show()
app.exit(app.exec_())
2:收集页面高度,并计算分次截屏的次数和余量高度;实例化图片合并工具,设置定时器,超时信号发出后,执行exe_command;
def check_page(self):
p_width, p_height = self.get_page_size()
self.page, self.over_flow_size = divmod(p_height, self.height())
if self.page == 0:
self.page = 1
self.ssm = ScreenShotMerge(self.page, self.over_flow_size)
self.timer = QTimer(self)
self.timer.timeout.connect(self.exe_command)
self.timer.setInterval(400)
self.timer.start()
3:exe_command用来控制截图次数,并在每次截图完成后控制网页向下滑屏幕的高度;所有的页面都已截取时,完成图片合并。
def exe_command(self):
if self.page > 0:
self.screen_shot()
self.run_js() elif self.page < 0:
self.timer.stop()
self.ssm.image_merge()
self.close() elif self.over_flow_size > 0:
self.screen_shot()
self.page -= 1 def run_js(self):
script = """
var scroll = function (dHeight) {
var t = document.documentElement.scrollTop
var h = document.documentElement.scrollHeight
dHeight = dHeight || 0
var current = t + dHeight
if (current > h) {
window.scrollTo(0, document.documentElement.clientHeight)
} else {
window.scrollTo(0, current)
}
}
"""
command = script + '\n scroll({})'.format(self.height())
self.browser.page().runJavaScript(command)
4:screen_shot在每次截图完成后将图片保存,并将图片对象由图片合并根据保存到列表中。
def screen_shot(self):
screen = QApplication.primaryScreen()
winid = self.browser.winId()
pix = screen.grabWindow(int(winid))
name = '{}/temp.png'.format(self.ssm.root_path)
pix.save(name)
self.ssm.add_im(name)
5:截图合并工具,在每次截图完成后将图片对象保存,完成余量截图的重绘和截图的合并。
class ScreenShotMerge():
def __init__(self, page, over_flow_size):
self.im_list = []
self.page = page
self.over_flow_size = over_flow_size
self.get_path() def get_path(self):
self.root_path = Path(__file__).parent.joinpath('temp')
if not self.root_path.exists():
self.root_path.mkdir(parents=True)
self.save_path = self.root_path.joinpath('merge.png') def add_im(self, path):
if len(self.im_list) == self.page:
im = self.reedit_image(path)
else:
im = Image.open(path)
im.save('{}/{}.png'.format(self.root_path, len(self.im_list) + 1))
self.im_list.append(im) def get_new_size(self):
max_width = 0
total_height = 0
# 计算合成后图片的宽度(以最宽的为准)和高度
for img in self.im_list:
width, height = img.size
if width > max_width:
max_width = width
total_height += height
return max_width, total_height def image_merge(self, ):
if len(self.im_list) > 1:
max_width, total_height = self.get_new_size()
# 产生一张空白图
new_img = Image.new('RGB', (max_width - 15, total_height), 255)
x = y = 0
for img in self.im_list:
width, height = img.size
new_img.paste(img, (x, y))
y += height
new_img.save(self.save_path)
print('截图成功:', self.save_path)
else:
obj = self.im_list[0]
width, height = obj.size
left, top, right, bottom = 0, 0, width, height
box = (left, top, right, bottom)
region = obj.crop(box)
new_img = Image.new('RGB', (width, height), 255)
new_img.paste(region, box)
new_img.save(self.save_path)
print('截图成功:', self.save_path) def reedit_image(self, path):
obj = Image.open(path)
width, height = obj.size
left, top, right, bottom = 0, height - self.over_flow_size, width, height
box = (left, top, right, bottom)
region = obj.crop(box)
return region
截图功能完整代码
#!/usr/bin/env python
# -*- coding:UTF-8 -*-
# Author:Leslie-x
import sys
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from PyQt5.QtWebEngineWidgets import *
from PIL import Image
from pathlib import Path class ScreenShotMerge():
def __init__(self, page, over_flow_size):
self.im_list = []
self.page = page
self.over_flow_size = over_flow_size
self.get_path() def get_path(self):
self.root_path = Path(__file__).parent.joinpath('temp')
if not self.root_path.exists():
self.root_path.mkdir(parents=True)
self.save_path = self.root_path.joinpath('merge.png') def add_im(self, path):
if len(self.im_list) == self.page:
im = self.reedit_image(path)
else:
im = Image.open(path)
im.save('{}/{}.png'.format(self.root_path, len(self.im_list) + 1))
self.im_list.append(im) def get_new_size(self):
max_width = 0
total_height = 0
# 计算合成后图片的宽度(以最宽的为准)和高度
for img in self.im_list:
width, height = img.size
if width > max_width:
max_width = width
total_height += height
return max_width, total_height def image_merge(self, ):
if len(self.im_list) > 1:
max_width, total_height = self.get_new_size()
# 产生一张空白图
new_img = Image.new('RGB', (max_width - 15, total_height), 255)
x = y = 0
for img in self.im_list:
width, height = img.size
new_img.paste(img, (x, y))
y += height
new_img.save(self.save_path)
print('截图成功:', self.save_path)
else:
obj = self.im_list[0]
width, height = obj.size
left, top, right, bottom = 0, 0, width, height
box = (left, top, right, bottom)
region = obj.crop(box)
new_img = Image.new('RGB', (width, height), 255)
new_img.paste(region, box)
new_img.save(self.save_path)
print('截图成功:', self.save_path) def reedit_image(self, path):
obj = Image.open(path)
width, height = obj.size
left, top, right, bottom = 0, height - self.over_flow_size, width, height
box = (left, top, right, bottom)
region = obj.crop(box)
return region class MainWindow(QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.setWindowTitle('易哈佛')
self.temp_height = 0
self.setWindowFlag(Qt.WindowMinMaxButtonsHint, False) # 禁用最大化,最小化
# self.setWindowFlag(Qt.WindowStaysOnTopHint, True) # 窗口顶置
self.setWindowFlag(Qt.FramelessWindowHint, True) # 窗口无边框 def urlScreenShot(self, url):
self.browser = QWebEngineView()
self.browser.load(QUrl(url))
geometry = self.chose_screen()
self.setGeometry(geometry)
self.browser.loadFinished.connect(self.check_page)
self.setCentralWidget(self.browser) def get_page_size(self):
size = self.browser.page().contentsSize()
self.set_height = size.height()
self.set_width = size.width()
return size.width(), size.height() def chose_screen(self):
width, height = 750, 1370
desktop = QApplication.desktop()
screen_count = desktop.screenCount()
for i in range(0, screen_count):
rect = desktop.availableGeometry(i)
s_width, s_height = rect.width(), rect.height()
if s_width > width and s_height > height:
return QRect(rect.left(), rect.top(), width, height)
return QRect(0, 0, width, height) def check_page(self):
p_width, p_height = self.get_page_size()
self.page, self.over_flow_size = divmod(p_height, self.height())
if self.page == 0:
self.page = 1
self.ssm = ScreenShotMerge(self.page, self.over_flow_size)
self.timer = QTimer(self)
self.timer.timeout.connect(self.exe_command)
self.timer.setInterval(400)
self.timer.start() def exe_command(self):
if self.page > 0:
self.screen_shot()
self.run_js() elif self.page < 0:
self.timer.stop()
self.ssm.image_merge()
self.close() elif self.over_flow_size > 0:
self.screen_shot()
self.page -= 1 def run_js(self):
script = """
var scroll = function (dHeight) {
var t = document.documentElement.scrollTop
var h = document.documentElement.scrollHeight
dHeight = dHeight || 0
var current = t + dHeight
if (current > h) {
window.scrollTo(0, document.documentElement.clientHeight)
} else {
window.scrollTo(0, current)
}
}
"""
command = script + '\n scroll({})'.format(self.height())
self.browser.page().runJavaScript(command) def screen_shot(self):
screen = QApplication.primaryScreen()
winid = self.browser.winId()
pix = screen.grabWindow(int(winid))
name = '{}/temp.png'.format(self.ssm.root_path)
pix.save(name)
self.ssm.add_im(name) if __name__ == '__main__':
url = 'http://blog.sina.com.cn/lm/rank/focusbang//'
app = QApplication(sys.argv)
win = MainWindow()
win.urlScreenShot(url)
win.show()
app.exit(app.exec_())
Python实现网页截图(PyQT5)的更多相关文章
- Python中使用 Selenium 实现网页截图实例
Selenium 是一个可以让浏览器自动化地执行一系列任务的工具,常用于自动化测试.不过,也可以用来给网页截图.目前,它支持 Java.C#.Ruby 以及 Python 四种客户端语言.如果你使用 ...
- Python各种花式截图工具,截到你手软
前言: 最近,项目中遇到了一个关于实现通过给定URL,实现对网页屏幕进行截图的一个功能,前面代码中已经用python的第三方库实现了截图功能,但在上线以后出现了一些bug,所以就改bug的任务就落在了 ...
- Python下载网页的几种方法
get和post方式总结 get方式:以URL字串本身传递数据参数,在服务器端可以从'QUERY_STRING'这个变量中直接读取,效率较高,但缺乏安全性,也无法来处理复杂的数据(只能是字符串,比如在 ...
- 使用PhantomJS实现网页截图服务
这是上半年遇到的一个小需求,想实现网页的抓取,并保存为图片.研究了不少工具,效果都不理想,不是显示太差了(Canvas.Html2Image.Cobra),就是性能不怎么样(如SWT的Brower). ...
- html2canvas 网页截图 下载 上传
利用html2canvas插件 对网页截图 并下载和上传图片. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//E ...
- Python编写网页爬虫爬取oj上的代码信息
OJ升级,代码可能会丢失. 所以要事先备份. 一開始傻傻的复制粘贴, 后来实在不能忍, 得益于大潇的启示和聪神的原始代码, 网页爬虫走起! 已经有段时间没看Python, 这次网页爬虫的原始代码是 p ...
- 爬虫学习笔记(1)-- 利用Python从网页抓取数据
最近想从一个网站上下载资源,懒得一个个的点击下载了,想写一个爬虫把程序全部下载下来,在这里做一个简单的记录 Python的基础语法在这里就不多做叙述了,黑马程序员上有一个基础的视频教学,可以跟着学习一 ...
- iPhone 收藏网址[添加到书签] 和 [添加到主屏幕] 显示自定义图标,而不是网页截图
iPhone 收藏网址[添加到书签] 和 [添加到主屏幕] 显示自定义图标,而不是网页截图: <!-- Safari浏览器[添加到书签] --> <link rel="sh ...
- chrome也可以整张网页截图,保存完整网页为图片
转自:http://www.webkaka.com/blog/archives/chrome-save-a-webpage.html 关于浏览器截图,一直以为Chrome无能为力,最近发现,原来Chr ...
随机推荐
- VRP基础及操作
VRP基础及操作 前言 通用路由平台VRP(Versatile Routing Platform)是华为公司数据通信产品的通用操作系统平台,它以IP业务为核心,采用组件化的体系结构,在实现丰富功能特性 ...
- PAT甲题题解-1034. Head of a Gang (30)-并查集
给出n和k接下来n行,每行给出a,b,c,表示a和b之间的关系度,表明他们属于同一个帮派一个帮派由>2个人组成,且总关系度必须大于k.帮派的头目为帮派里关系度最高的人.(注意,这里关系度是看帮派 ...
- linux gcc编译多个源文件的方法
http://blog.csdn.net/yinjiabin/article/details/7731817
- 20135337朱荟潼 Linux第一周学习总结——计算机是如何工作的
朱荟潼 + 原创作品转载请注明出处 + <Linux内核分析>MOOC课http://mooc.study.163.com/course/USTC-1000029000 1.冯诺依曼体系结 ...
- windows 64bit 服务器下安装32位oracle database 11g 问题集
1.中文乱码 问题描述: 利用vs2008调试的时候正常,发布到IIS8.5上的时候,当查询语句中包含中文的时候会乱码,比如"select * from tb where name='小s' ...
- [百家号]华为:最强ARM服务器芯片,华为鲲鹏920处理器发布
华为:最强ARM服务器芯片,华为鲲鹏920处理器发布 泡泡网 百家号2019-01-0716:11 https://baijiahao.baidu.com/s?id=162198839753232 ...
- BZOJ2547 CTSC2002玩具兵(最短路径+二分答案+最大流)
先不考虑只有一个显得有些特殊的天兵. 可以发现超能力的作用实质上是使兵更换职业.每一个兵到达某个位置最少需要更换职业的次数是彼此独立的,因为如果需要某两人互换职业可以使他们各自以当前职业到达需要到的地 ...
- SP4487 GSS6 - Can you answer these queries VI
题目大意 给出一个由N个整数组成的序列A,你需要应用M个操作: I p x 在 p 处插入插入一个元素 x D p 删除 p 处的一个元素 R p x 修改 p 处元素的值为 x Q l r 查询一 ...
- Fantastic Graph 2018 沈阳赛区网络预赛 F题
题意: 二分图 有k条边,我们去选择其中的几条 每选中一条那么此条边的u 和 v的度数就+1,最后使得所有点的度数都在[l, r]这个区间内 , 这就相当于 边流入1,流出1,最后使流量平衡 解析: ...
- The Super Powers UVA - 11752(合数幂)
题意: 求1~2^64-1之间所有的 至少是两个不同的正整数的幂的数 升序输出 一个数的合数次幂即为这样的数 找出1~2^64-1中所有数的合数次幂 用set存起来(既能防止重复 又能升序) 最后输 ...