开发一个看电影资讯的VSCode插件

前言

VSCode这款开发工具相信大家是非常熟悉的了,那么VSCode仅仅是一款代码编辑工具吗?非也,在VSCode上有非常多的工(mo)作(yu)的插件,比如看股票呀,玩玩小游戏呀,看看小说呀,听听音乐呀,本文就不在过多说明了,感兴趣的朋友可以去搜一下。
在这里插入图片描述
VSCode上有非常多的插件供你选择,那么问题就来了,自己如何开发一个插件呢?来实现自己想要的功能,如果你感兴趣的话,请继续看吧,本文是拿作者自己开发的一个插件做示例,简单讲述一下VSCode插件开发的过程,以及我如何从0到1开发一个插件的心路历程,并非专业的教程,还请酌情观看。
专业的教程请移步https://code.visualstudio.com/api/references/vscode-api

先睹为快

首先先看一下我做好的VSCode插件,在VSCode中搜索movie-news即可。第一个应该就是了。全名是movie-news-for-vscode嗯,有点长,还不如直接起个中文名。
在这里插入图片描述
直接点击安装即可,这里有两点需要注意下,由于这个插件没有采用第三方的接口,而是采用python爬虫的方式获取的数据,所以除了需要安装Node.js 之外,还需要安装Python3,以及Python下的beautifulsoup4requests模块,Python安装不做过多介绍了,注意Python和Node.js安装之后需要加入环境变量。

#python下用pip安装模块
pip install beautifulsoup4
pip install requests

安装好之后,就可以去打开插件了,如图。
在这里插入图片描述

左边是正在热映和即将上映的电影列表,点击电影名称会打开一个标签页,可以查看海报、导演、时长、类型等信息。功能还是比较简单的。

确定需求

现在知道要开发一个VSCode插件了,那么具体做一个什么样的插件呢?本人呢非常喜欢看电影,于是就想做一个可以查看正在热映和即将上映的电影的信息的插件。页面布局就如上面的图片所示了,需要一个图标去点击,进入到插件中,然后显示正在热映和即将上映的电影的列表,点击列表中的电影名称可以查看影片信息,嗯,暂时就想到这些简单的功能。

有哪些难点

  • 去哪里获取正在热映和即将上映的电影的信息?
  • JS如何获取python的执行结果?

还有一些问题,比如如何在VSCode侧边栏显示插件图标?如何显示正在热映和即将上映的折叠面板?如何打开一个webview?这些不作为考虑范围,这些东西在官方文档里已经写的很清楚了,不算难点。

找呀找呀找接口

去哪里找电影的相关的免费的接口呢?说实话光这一步就花费了两天的时间,而且结果还是没找到,很气人,既然找不到免费好用的接口,那就只能自己动手了,获取电影信息的话,我首先找的是猫眼电影,但是发现猫眼电影分类很多,确实很专业,但是页面也比较复杂,于是又找到了淘票票,页面如下。
在这里插入图片描述
在这里插入图片描述

看到淘票票的页面,嘴角微微上扬,果断F12查看下页面元素。
在这里插入图片描述
多么直白,多么简单,还不用分页,正在热映和即将上映也都是分类好并且在一个页面中。这对我这个python小菜鸟来说,简直是舒服极了。写代码过程就不说了,直接上源码。

Python淘票票正在热映和即将上映的电影信息。

import io
import sys
from bs4 import BeautifulSoup
import requests
import json

#伪装浏览器请求
headers={
    'User-Agent':'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0;',
    'Referer':'https://www.taopiaopiao.com/showList.htm?spm=a1z21.3046609.header.4.1d69112aGq86y0&n_s=new'
}

#获取网页信息
def getPage(url):
    try:
        response=requests.get(url)
        if response.status_code==200:   #http状态码,200表示请求成功
            return response.text
        else:
            return None
    except Exception:
        return None
#解析html标签内容
def getInfo(html):
    soup=BeautifulSoup(html,'html.parser')    #创建bs对象 解析器为html.parser
    items=soup.select('div .movie-card-wrap')            #查询所有的电影卡片里的信息
    i=1
    result = []  #创建一个空的数组
    for item in items:
        name=item.find(name='div',class_='movie-card-name').get_text().strip() #这个是找你要内容的标签和它的类
        if '\n' in name:
            name = name[:name.index('\n')] #若包含评分,则去掉评分,因为有些电影没有评分
        obj={}
        obj['movie_name'] = name
        poster = item.find(name='img').get("src")   #获取海报图片地址
        obj['poster'] = poster  
        info=item.find(name='div',class_='movie-card-list').get_text().strip()  #这里包含 主演 类型 时长等信息
        infoArr = info.split('\n')
        for index in range(len(infoArr)):
            obj[index] = infoArr[index]
        #获取的包括正在热映以及即将上映
        soon = item.find(name='a',class_='movie-card-soon')
        if(soon==None): #正在热映
            obj["bool_showed"] = True
        else: #即将上映
            obj["bool_showed"] = False
        result.append(obj)  #向集合中添加元素
        i=i+1
    return result
sys.stdout = io.TextIOWrapper(sys.stdout.detach(),encoding='utf-8')
url='https://www.taopiaopiao.com/showList.htm?spm=a1z21.3046609.header.4.20c5112aFDxxzq&n_s=new'
html=getPage(url)
data=getInfo(html)
print(json.dumps(data,ensure_ascii=False))  #转成json

接着可以打印下结果
在这里插入图片描述
这里是已经转成json格式的数据,OK到目前,问题已经解决了一个,还差一个问题解决了就可以正式开始写VSCode插件了。

Node.js中神奇的child_process

数据我们可以获取到了,但是由于是用python获取的数据,如何在JS中用呢,换句话说就是如何在用JS调用python脚本并执行,然后获取执行结果,首先我们需要知道一点,VSCode插件可以用JS和TS两种方式进行开发,且TS为JS的超集,所以都肯定是支持JS语法的。

那么神奇的child_process就要登场啦,官网在这里http://nodejs.cn/api/child_process.html

在child_process里可以创建一个子进程,在子进程里可以执行一些自己想要执行的命令,然后我们可以这样写。

const { spawn } = require('child_process');
const ls = spawn('python', ["D:\\MyProject\\python-shell\\api.py']);
ls.stdout.on('data', (data) => {
  console.log(`stdout: ${data}`);
});

ls.stderr.on('data', (data) => {
  console.error(`stderr: ${data}`);
});

ls.on('close', (code) => {
  console.log(`子进程退出,退出码 ${code}`);
});

首先我们需要把Python加入环境变量哈,然后上面就是用python命令来执行python脚本。
OK难点都解决了,接下来可以正式开始我们的VSCode插件开发之旅了。

生成项目

首先需要安装一个代码生成器

npm install -g yo generator-code

安装好之后用yo code命令来创建一个默认的项目。这里会让选择开发的插件类型,项目名称,开发者等信息。按自己的要求输入就好了。

yo code
# ? What type of extension do you want to create? New Extension (TypeScript)
# ? What's the name of your extension? HelloWorld
### Press <Enter> to choose default for all options below ###

# ? What's the identifier of your extension? helloworld
# ? What's the description of your extension? LEAVE BLANK
# ? Initialize a git repository? Yes
# ? Bundle the source code with webpack? No
# ? Which package manager to use? npm

然后一个项目就创建好了,用VScode打开,还原下npm包,就可以直接F5运行了,

配置项目

接下来需要配置下侧边栏的图标,以及显示正在热映和即将上映的折叠面板。打开项目的下的package.json文件,修改如下。

	"contributes": {
		"commands": [
			{
				"command": "limeng.helloWorld",
				"title": "Hello World"
			}
		],
		"viewsContainers": {
			"activitybar": [
				{
					"id": "sidebar",
					"title": "电影资讯",
					"icon": "resources/movie.png"
				}
			]
		},
		"views": {
			"sidebar": [
				{
					"id": "sidebar_hot",
					"name": "正在热映"
				},
				{
					"id": "sidebar_soon",
					"name": "即将上映"
				}
			]
		}
	},

其中的activitybar便是显示在侧边栏的图标,sidebar是显示在侧边栏右边的可折叠面板。

正在热映和即将上映的区域有了,接下来就需要的把电影列表填充到相应的区域。在src目录下新建一个名为sidebar.ts的文件

//执行py文件,获取正在热映和即将上映电影列表 
function getMovieData() {
    let json = {};
    const { spawnSync } = require('child_process');  //同步
    let pyPath = path.join(__dirname, '../api/api.py');
    const ls = spawnSync('python', [pyPath]);
    json = ls.stdout;
    console.log(ls.stderr + ''); //输出错误信息
    return json;
}
//正在热映
export class SidebarHot implements vscode.TreeDataProvider<EntryItem>
{
    onDidChangeTreeData?: vscode.Event<void | EntryItem | null | undefined> | undefined;
    getTreeItem(element: EntryItem): vscode.TreeItem | Thenable<vscode.TreeItem> {
        return element;
    }
    getChildren(element?: EntryItem): vscode.ProviderResult<EntryItem[]> {
        if (!element) {
            return getMovieList(true);
        }
    }
}
//返回电影列表
function getMovieList(this: any, flag: boolean) {
    let json = getMovieData() + "";   //buffer转字符串
    let obj = JSON.parse(json);  //解析json 
    let movies: any[] = [];
    for (let item of obj) {
        if (item["bool_showed"] === flag) {  //正在热映
            let movieName = new EntryItem(item["movie_name"]);
            movieName.command = {
                command: "sidebar_item.openWebview", //命令id
                title: "标题",
                arguments: [item] //命令接收的参数
            };
            movies.push(movieName);
        }
    };
    return movies;
}

现在还没完成,刚上面只是把数据绑定到TreeItem中,就接下来的才是重点。找到src目录下的extension.ts文件,里面有一个activate方法,修改如下。

export function activate(context: vscode.ExtensionContext) {

	//注册侧边栏面板的实现
	const sidebarHot = new sidebar.SidebarHot();
	const sidebarSoon = new sidebar.SidebarSoon();
	vscode.window.registerTreeDataProvider("sidebar_hot",sidebarHot);
	vscode.window.registerTreeDataProvider("sidebar_soon",sidebarSoon);
	//注册命令
	vscode.commands.registerCommand("sidebar_item.openWebview",args=>{
		//vscode.window.showInformationMessage(args);
		const panel = vscode.window.createWebviewPanel(
			'webview', // viewType
			 args["movie_name"], // 视图标题,为电影名称
			vscode.ViewColumn.One,
			{
				enableScripts: true, // 启用JS,默认禁用
				retainContextWhenHidden: true // webview被隐藏时保持状态,避免被重置
			}
		);
		//这里只能输入html内容
		let content = getContentHtml(args);
		panel.webview.html = showWebviewContent(args,content);
	    
	});
	// The command has been defined in the package.json file
	// Now provide the implementation of the command with registerCommand
	// The commandId parameter must match the command field in package.json
	let disposable = vscode.commands.registerCommand('movienews.helloWorld', () => {
		// The code you place here will be executed every time your command is executed

		// Display a message box to the user
		vscode.window.showInformationMessage('Hello World from 电影资讯!');
	});

	context.subscriptions.push(disposable);
}

这里还注册了一个openWebview的命令,用于点击电影名称,打开新的标签页。标签页中的内容就是简单的html,方法如下。

function showWebviewContent(args:any,content:string){
	let result = `
	<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
	<div style="height:500px;width: 500px; margin: 50px auto 0;">
	<div><img src="`+args["poster"]+`" style="width: 160px;height: 240px;"> 
	</div>
	<div style="position: relative;top: -265px;left: 180px;">
		<p>
		<h2>`+args["movie_name"]+`</h2>
		</p>
		`+content+`
	</div>
</div>
</body>
</html>`;
return result;
}

function getContentHtml(args:any){
	let content = '';
	for(var i in args) {
		if(!isNaN(Number(i))){
			content+="<p>"+args[i]+"</p>";
		}
	}
	return content;
}

项目地址我会放到最后,感兴趣的可以clone到本地运行查看,注意还是需要先配置环境哦。

发布项目

在本地运行没问题的话,接下来就是把我们的项目发布到应用商店了。地址参考:https://code.visualstudio.com/api/working-with-extensions/publishing-extension

  1. 首先需要注册Microsoft账号,
  2. 然后登录dev.azure,创建组织和项目。
  3. 创建Personal Access Tokens。
  4. 登录https://marketplace.visualstudio.com/VSCode创建发布者。

然后就可以发布你的项目了。发布的方式有两种,一种是用命令直接发布,还有一种可以打包成vsix,手动上传到应用商店。

打包需要安装vsce工具,常用命令如下。

//安装工具
npm install -g vsce   
//打包成vsix安装包
vsce package   
//登录
vsce login <publisher name>
//发布
vsce publish 

登录的时候需要Personal Access Token,这个需要提前创建好并复制下来。

注意一点,在创建Publisher的时候,需要在网页创建,传统的命令创建已经不行了。去下面提示的网址进行创建就好了。
在这里插入图片描述

写在最后

这款插件是兴趣使然,并没有花费很多精力在上面,功能也比较简单,以后有想法了在完善吧,就这样。
项目地址:https://gitee.com/limeng66/movie-news-for-vscode
转载请保留出处。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

李公子lm

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值