MacOS Mojave 10.14.6
Python 3.7.6
Pip 19.3.1
Scrapy 1.8.0
CEF Python是一个开源项目,旨在为Chromium嵌入式框架(CEF)提供Python绑定
步骤一:安装 cefpython3
pip install cefpython3==66.0
步骤二:Hello World!示例
不需要任何第三方GUI框架即可运行的基本示例
创建及运行例子
mkdir cefpython_hello.py
cd cefpython_hello
python cefpython_hello.py
输入源码
from cefpython3 import cefpython as cef
import sys
HTML_code = """
def main():
sys.excepthook = cef.ExceptHook
cef.Initialize()
cef.CreateBrowserSync(url=cef.GetDataUrl(HTML_code))
cef.MessageLoop()
cef.Shutdown()
if __name__ == '__main__':
main()
源码解析
1.导入cefpython库并声明为cef变量
from cefpython3 import cefpython as cef
2.导入sys库
import sys
该模块提供对解释器使用或维护的某些变量以及与解释器交互的功能访问
3.处理异常
sys.excepthook = cef.ExceptHook全局(除钩子以外)可在错误时彻底退出应用程序
CEF具有多进程体系结构,退出时,您需要通过调用Shutdown()关闭所有进程(主浏览器进程,渲染器进程,GPU进程等)。该挂钩执行以下操作:万一发生异常,将其写入error.log文件,将其显示在控制台上,关闭CEF并立即退出应用程序。
4.初始化CEF
cef.Initialize()启动应用程序时,应在主应用程序线程(UI线程)上调用此函数以初始化CEF
调用Initialize()必须具有相应的Shutdown()调用,以便CEF干净退出。否则,当应用程序关闭时,数据(例如,存储,Cookie)可能不会保存到磁盘上
5.启用消息队列
cef.MessageLoop()运行CEF消息循环。使用此功能代替应用程序提供的消息循环,可以在性能和CPU使用率之间取得最佳平衡
该功能使得浏览器始终保持运行,类似一个Sleep 。但这是我们所期望的
6.设置GUI视图布局
cef.CreateBrowserSync(url=cef.GetDataUrl(HTML_code))
将数据转换为数据URL。返回值作为参数同步创建浏览器视图将数据转换为数据URL。当前仅支持“ html”媒体类型。
7.运行函数
if __name__ == '__main__':
main()
__name__是当前模块名称,这里运行当前文件作为主进程时运行main()函数
步骤三:加载 Python 本地资源服务!示例
8.开始之前我们可以创建基于 create-react-app 脚手架创建GUI工作目录:
# react typescript
npx create-react-app gui --template typescript
9.也可以加入ant design react框架:
$ cd gui
$ yarn start
$ yarn add antd
修改引用:
修改 src/App.tsx,引入 antd 的按钮组件。
import React, { Component } from 'react';
import Button from 'antd/es/button';
import './App.css';
class App extends Component {
render() {
return (
Button
);
}
}
export default App;
修改 src/App.css 引入 antd 的样式。
@import '~antd/dist/antd.css';
.App {
text-align: center;
}
...
重新启动 yarn start,现在你应该能看到页面上已经有了 antd 的蓝色按钮组件,接下来就可以继续选用其他组件开发应用了。其他开发流程你可以参考 create-react-app 的官方文档。
10.然后编写 cefpython 主线程
from cefpython3 import cefpython as cef
import sys
import os
def main():
sys.excepthook = cef.ExceptHook
cef.Initialize()
os.system('python -m http.server 8888')
browser = cef.CreateBrowserSync(url='http://localhost:8888/resources')
cef.MessageLoop()
cef.Shutdown()
if __name__ == '__main__':
main()
源码解析
11.启动本地服务
os.system('python -m http.server 8888')
12.浏览器指向本地服务
browser = cef.CreateBrowserSync(url='http://localhost:8888/resources')
到这里实现了HTML代码与Python代码分离 ,并且支持静态站点资源管理
异常:OSError: [Errno 48] Address already in use服务未关闭导致无法正常启动
1.检查端口进程ID
=> lsof -i:8888
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
Python 29075 *** 3u IPv4 *** 0t0 TCP *:irdmi (LISTEN)
2.关闭进程
kill 29075
步骤四:Python 和 JavaScript 通信!示例
from cefpython3 import cefpython as cef
import sys
def main():
sys.excepthook = cef.ExceptHook
cef.Initialize()
HTML_code = open('resources/index.html','r').read()
browser = cef.CreateBrowserSync(url=cef.GetDataUrl(HTML_code))
bindings = cef.JavascriptBindings()
bindings.SetFunction("alert",pyLeart)
browser.SetJavascriptBindings(bindings)
cef.MessageLoop()
cef.Shutdown()
def pyLeart(v):
print(v)
if __name__ == '__main__':
main()
源码解析
该方式可以实现 JavaScript 调用 Python 函数,具体步骤如下:
1.创建 JavaScript 绑定对象
bindings = cef.JavascriptBindings()
2.追加绑定关系
// 绑定方法
bindings.SetFunction("alert",pyLeart)
// 绑定对象
bindings.SetObject("external",external)
3.绑定到浏览器实例
browser.SetJavascriptBindings(bindings)
到这里实现了 Python 函数定义,以 JavaScript 函数触发。JS 调用 alert 函数时会覆盖默认消息框,将值打印到命令窗口输出
Python 主动触发 JavaScript !
1.运行 JavaScript 代码段
browser.ExecuteJavascript(jsCode='alert("hello world!")')
2.运行 JavaScript 函数,并传递参数
browser.ExecuteFunction("alert","hello world!")
步骤五:集成 Python Scrapy 框架!示例
集成CEFPython、Python、Python Scrapy框架的完整示例
安装 scrapy
pip install scrapy
输入源码
from cefpython3 import cefpython as cef
import sys
import scrapy
from scrapy.crawler import CrawlerProcess
def main():
sys.excepthook = cef.ExceptHook
cef.Initialize()
HTML_code = open('resources/index.html','r').read()
browser = cef.CreateBrowserSync(url=cef.GetDataUrl(HTML_code))
bindings = cef.JavascriptBindings()
bindings.SetFunction("alert",pyLeart)
browser.SetJavascriptBindings(bindings)
cef.MessageLoop()
cef.Shutdown()
def pyLeart(v):
exescrapy()
pass
class BlogSpider(scrapy.Spider):
name = 'blogspider'
start_urls = ['https://blog.scrapinghub.com']
def parse(self, response):
for title in response.css('.post-header>h2'):
yield {'title': title.css('a ::text').get()}
for next_page in response.css('a.next-posts-link'):
yield response.follow(next_page, self.parse)
def exescrapy():
process = CrawlerProcess({
'USER_AGENT': 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)'
})
process.crawl(BlogSpider)
process.start() # the script will block here until the crawling is finished
if __name__ == '__main__':
main()
源码解析
1.引用爬虫库
import scrapy
from scrapy.crawler import CrawlerProcess
2.定义爬虫
class BlogSpider(scrapy.Spider):
name = 'blogspider'
start_urls = ['https://blog.scrapinghub.com']
def parse(self, response):
for title in response.css('.post-header>h2'):
yield {'title': title.css('a ::text').get()}
for next_page in response.css('a.next-posts-link'):
yield response.follow(next_page, self.parse)
def exescrapy():
process = CrawlerProcess({
'USER_AGENT': 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)'
})
process.crawl(BlogSpider)
process.start() # the script will block here until the crawling is finished
到这里实现了CEFPython下Web作为GUI,并且在Web加载完毕后调用Python的exescrapy方法运行blogspider爬虫的完整流程
scrapy startproject scrapy
cd scrapy && scrapy genspider quotes quotes.org
图书cztomczak/cefpythongithub.com