英文:
python subprocess - google-chrome headless - self-signed certificate - screenshot
问题
从您提供的信息来看,问题可能与在对象方法中运行subprocess
时的环境权限有关。在对象方法中,可能会受到不同的环境限制,导致某些功能不起作用。
为了解决这个问题,您可以尝试以下几点:
-
确保在对象方法中使用相同的用户权限和环境变量。您可以在对象方法中添加一些代码,以确保使用相同的环境设置,尤其是在涉及文件路径和权限的情况下。
-
在对象方法中添加适当的错误处理和日志记录,以便更好地了解问题所在。这将有助于识别哪些部分可能失败,并提供更多的上下文信息。
-
尝试在对象方法中运行其他简单的
subprocess
命令,以查看是否存在相同的问题。这可以帮助缩小问题的范围,确定是否仅与特定的subprocess
调用有关。 -
考虑使用其他方法来截取网页内容,例如使用Python的
requests
库来下载网页内容,而不是依赖于subprocess
来运行浏览器。
通过执行上述步骤,您可以更好地诊断和解决问题,以确保在对象方法中正确运行您的subprocess
调用。
英文:
When opening a django shell:
python manage.py shell
and typing in:
import subprocess
command = [
f'google-chrome',
'--headless=new',
f'--screenshot=/home/user/tmp/screen.png',
f'--window-size=800,1700',
'--no-first-run',
'--allow-http-screen-capture',
'--force-device-scale-factor=1',
'--ignore-certificate-errors',
'--ignore-urlfetcher-cert-requests',
'--disable-test-root-certs',
'--allow-running-insecure-content',
'--hide-scrollbars',
'--allow-insecure-localhost',
'--disable-system-font-check',
'--disable-gpu',
'--disable-extensions',
'--disable-dev-shm-usage',
'--disable-software-rasterizer',
'--disable-notifications',
'--user-data-dir=/tmp/chromium-home',
'/home/user/tmp/screen.html',
]
subprocess.run(command, **{})
The console output is the following:
[32873:32901:0419/083534.872076:ERROR:bus.cc(399)] Failed to connect to the bus: Failed to connect to socket /run/user/0/bus: Permission denied
[32873:32901:0419/083534.884135:ERROR:bus.cc(399)] Failed to connect to the bus: Failed to connect to socket /run/user/0/bus: Permission denied
[32873:32901:0419/083534.970536:ERROR:bus.cc(399)] Failed to connect to the bus: Failed to connect to socket /run/user/0/bus: Permission denied
[32873:32901:0419/083534.970630:ERROR:bus.cc(399)] Failed to connect to the bus: Failed to connect to socket /run/user/0/bus: Permission denied
(process:32873): dconf-CRITICAL **: 08:35:35.289: unable to create directory '/run/user/0/dconf': Permission denied. dconf will not work properly.
(process:32873): dconf-CRITICAL **: 08:35:35.314: unable to create directory '/run/user/0/dconf': Permission denied. dconf will not work properly.
(process:32873): dconf-CRITICAL **: 08:35:35.350: unable to create directory '/run/user/0/dconf': Permission denied. dconf will not work properly.
[32873:32899:0419/083537.631303:ERROR:cert_verify_proc_builtin.cc(679)] CertVerifyProcBuiltin for 127.0.0.1 failed:
----- Certificate i=0 (<snip>) -----
ERROR: No matching issuer found
[32873:32897:0419/083537.639022:ERROR:cert_verify_proc_builtin.cc(679)] CertVerifyProcBuiltin for 127.0.0.1 failed:
----- Certificate i=0 (<snip>) -----
ERROR: No matching issuer found
572051 bytes written to file /home/user/tmp/screen.png
CompletedProcess(args=['google-chrome', '--headless=new', '--screenshot=/home/user/tmp/screen.png', '--window-size=800, 1700', '--no-first-run', '--allow-http-screen-capture', '--force-device-scale-factor=1', '--ignore-certificate-errors', '--ignore-urlfetcher-cert-requests', '--disable-test-root-certs', '--allow-running-insecure-content', '--hide-scrollbars', '--allow-insecure-localhost', '--disable-system-font-check', '--disable-gpu', '--disable-extensions', '--disable-dev-shm-usage', '--disable-software-rasterizer', '--disable-notifications', '--user-data-dir=/tmp/chromium-home', '/home/user/tmp/screen.html'], returncode=0)
Looks worrying, but the screen.png
file is properly "screenshotted".
We can even see the certificate errors, which are mentioned but apparently ignored as requested in the subprocess call.
By the way, the bash calling works too, i.e., :
$ google-chrome --headless=new --screenshot=/home/user/tmp/screen.png --window-size=800,1700 --no-first-run --allow-http-screen-capture --force-device-scale-factor=1 --ignore-certificate-errors --ignore-urlfetcher-cert-requests --disable-test-root-certs --allow-running-insecure-content --hide-scrollbars --allow-insecure-localhost --disable-system-font-check --disable-gpu --disable-extensions --disable-dev-shm-usage --disable-software-rasterizer --disable-notifications --user-data-dir=/tmp/chromium-home /home/user/tmp/screen.html
works too.
Google chrome version is google-chrome-unstable.x86_64 114.0.5696.0-1
on Rocky Linux 9. The problem described below is the same with the stable version.
Now I would like to ru the above subprocess call from within a model function, like so:
class MyModel(models.Model):
<snip>
def render(self):
import subprocess
commands = [
f'google-chrome',
'--headless=new',
f'--screenshot=/home/user/tmp/screen.png',
f'--window-size=800,1700',
'--no-first-run',
'--allow-http-screen-capture',
'--force-device-scale-factor=1',
'--ignore-certificate-errors',
'--ignore-urlfetcher-cert-requests',
'--disable-test-root-certs',
'--allow-running-insecure-content',
'--hide-scrollbars',
'--allow-insecure-localhost',
'--disable-system-font-check',
'--disable-gpu',
'--disable-extensions',
'--disable-dev-shm-usage',
'--disable-software-rasterizer',
'--disable-notifications',
'--user-data-dir=/tmp/chromium-home',
'/home/user/tmp/screen.html',
]
subprocess.run()
The command line output is:
[33681:33708:0419/085053.463656:ERROR:bus.cc(399)] Failed to connect to the bus: Failed to connect to socket /run/user/0/bus: Permission denied
[33681:33708:0419/085053.464599:ERROR:bus.cc(399)] Failed to connect to the bus: Failed to connect to socket /run/user/0/bus: Permission denied
[33681:33708:0419/085053.589267:ERROR:bus.cc(399)] Failed to connect to the bus: Failed to connect to socket /run/user/0/bus: Permission denied
[33681:33708:0419/085053.589373:ERROR:bus.cc(399)] Failed to connect to the bus: Failed to connect to socket /run/user/0/bus: Permission denied
(process:33681): dconf-CRITICAL **: 08:50:53.761: unable to create directory '/run/user/0/dconf': Permission denied. dconf will not work properly.
(process:33681): dconf-CRITICAL **: 08:50:53.768: unable to create directory '/run/user/0/dconf': Permission denied. dconf will not work properly.
(process:33681): dconf-CRITICAL **: 08:50:53.821: unable to create directory '/run/user/0/dconf': Permission denied. dconf will not work properly.
8899 bytes written to file /home/user/tmp/screen.png
Errors are similar, but the SSL certificate errors are not there.
Given that the contents of the HTML file are (or very similar, the file is dynamically generated):
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no, shrink-to-fit=no">
<style>
*{
box-sizing:border-box;
margin:0;
padding:0;
}
html{
-webkit-print-color-adjust:exact;
}
.upload{
overflow:hidden;
height:1600px;
width:800px;
display:block;
}
.upload > img{
display:block;
width:100%;
}
</style>
</head>
<body>
<div class="upload">
<img src="https://docs.celeryq.dev/en/stable/_static/celery_512.png"><br>
<img src="https://127.0.0.1:1310/m/u/befe5aa9-690b-410d-a3bc-7ba9a75c382a.webp" alt="This is a test">
</div>
</body>
</html>
I am guessing subnprocess
is somehow skipping? ignoring? discarding? the image calls made by the headless browser?
In a word:
- works from bash command line
- works from "normal" python shell
- does not work from an object method
I am at a loss -- any clues?
答案1
得分: 1
如果你原谅我打岔一下,我是个白痴
将答案贴出以备后人,因为网络是永恒的,也是为了提醒自己。
答案位于HTML文件的动态生成中:
错误版本:
def render(self):
html_render = '<some /><markup />'
with open(temp_html_full_path, 'w') as f:
f.write(html_render)
command = []
subprocess.run(command, **{})
正常版本:
def render(self):
html_render = '<some /><markup />'
with open(temp_html_full_path, 'w') as f:
f.write(html_render)
command = []
subprocess.run(command, **{})
请注意 subprocess
调用是在 with
文件写入块内/外部完成的。
英文:
If you'll excuse my French, I am an idiot
Will post the answer for posterity and since the internet is forever, as a reminder for myself.
the answer was in the dynamic generation of the HTML file:
Broken version:
def render(self):
html_render = '<some /><markup />'
with open(temp_html_full_path, 'w') as f:
f.write(html_render)
command = []
subprocess.run(command, **{})
Working version:
def render(self):
html_render = '<some /><markup />'
with open(temp_html_full_path, 'w') as f:
f.write(html_render)
command = []
subprocess.run(command, **{})
Notice how the subprocess
call is made inside/outside the with
file writing block.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论