【原创】Scrapyd 的 .net 客户端
最近项目需要部署Scrapy爬虫,采用最简单的Scrapyd服务进行部署,基于.net core 进行了客户端的封装。
1)Scrapyd API文档:http://scrapyd.readthedocs.io/en/latest/api.html
2)使用HttpClient进行交互
比较麻烦的是部署爬虫所需要的使用 HttpClient 上传文件的代码,使用了 “MultipartFormDataContent” 对象进行上传,添加字符串内容,及StreamContent,直接可以将MVC中的File对象传入,不用自行处理临时文件。
var content = new MultipartFormDataContent("Upload-----" + Guid.NewGuid().ToString().Replace("-", "")); content.Add(new StringContent(project), "\"project\"");
content.Add(new StringContent(version), "\"version\"");
content.Add(new StreamContent(eggStream), "\"egg\"", "\"" + project + ".egg" + "\""); var resp = client.PostAsync("addversion.json", content).Result; var strResult = resp.Content.ReadAsStringAsync().Result; return JsonConvert.DeserializeObject<AddVersionResponse>(strResult);
完整代码
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Text;
using Newtonsoft.Json;
using Scrapyd.Client.Response; namespace Scrapyd.Client
{
/// <summary>
/// A Client used to communicate with the Scrapyd Daemon
/// </summary>
public class ScrapydClient
{
private readonly string _host;
private readonly int _port; public ScrapydClient(string host, int port)
{
_host = host;
_port = port;
} /// <summary>
/// 查询状态
/// </summary>
/// <returns></returns>
public DaemonStatusResponse QueryStatus()
{
HttpClient client = new HttpClient()
{
BaseAddress = new Uri($"http://{_host}:{_port}")
}; try
{
var strResult = client.GetStringAsync("daemonstatus.json").Result; var jresult = JsonConvert.DeserializeObject<DaemonStatusResponse>(strResult);
return jresult;
}
catch (Exception e)
{
return new DaemonStatusResponse { status = "failed", message = e.Message };
}
} public AddVersionResponse AddVersion(string project, string version, Stream eggStream)
{
if (string.IsNullOrEmpty(project)) throw new ArgumentNullException(nameof(project));
if (eggStream == null) throw new ArgumentNullException(nameof(eggStream)); var client = new HttpClient()
{
BaseAddress = new Uri($"http://{_host}:{_port}")
}; try
{
var content = new MultipartFormDataContent("Upload-----" + Guid.NewGuid().ToString().Replace("-", "")); content.Add(new StringContent(project), "\"project\"");
content.Add(new StringContent(version), "\"version\"");
content.Add(new StreamContent(eggStream), "\"egg\"", "\"" + project + ".egg" + "\""); var resp = client.PostAsync("addversion.json", content).Result; var strResult = resp.Content.ReadAsStringAsync().Result; return JsonConvert.DeserializeObject<AddVersionResponse>(strResult);
}
catch (Exception e)
{
return new AddVersionResponse { status = "failed", message = e.Message };
}
} public ScheduleResponse ScheduleJob(string project, string spider,
string setting = "",
string jobid = "",
string version = "",
Dictionary<string, string> arguments = null)
{
if (string.IsNullOrEmpty(project)) throw new ArgumentNullException(nameof(project));
if (string.IsNullOrEmpty(spider)) throw new ArgumentNullException(nameof(spider)); var client = new HttpClient()
{
BaseAddress = new Uri($"http://{_host}:{_port}")
}; try
{
var data = new Dictionary<string, string>()
{
{"project", project},
{"spider", spider}
}; if (!string.IsNullOrEmpty(jobid))
{
data.Add("jobid", jobid);
}
if (!string.IsNullOrEmpty(setting))
{
data.Add("setting", setting);
} if (!string.IsNullOrEmpty(version))
{
data.Add("_version", version);
} if (arguments != null && arguments.Count > )
{
foreach (var argument in arguments)
{
data.Add(argument.Key, argument.Value);
}
} var strResult =
client.PostAsync("schedule.json", new FormUrlEncodedContent(data))
.Result.Content.ReadAsStringAsync()
.Result; return JsonConvert.DeserializeObject<ScheduleResponse>(strResult); }
catch (Exception e)
{
return new ScheduleResponse { status = "failed", message = e.Message };
}
} public CancelResponse CancelJob(string project, string jobid)
{
if (string.IsNullOrEmpty(project)) throw new ArgumentNullException(nameof(project));
if (string.IsNullOrEmpty(jobid)) throw new ArgumentNullException(nameof(jobid)); var client = new HttpClient()
{
BaseAddress = new Uri($"http://{_host}:{_port}")
}; try
{
var content = new FormUrlEncodedContent(new Dictionary<string, string>()
{
{"project", project},
{"job", jobid}
});
var strResult = client.PostAsync($"/cancel.json", content).Result.Content.ReadAsStringAsync().Result; return JsonConvert.DeserializeObject<CancelResponse>(strResult); }
catch (Exception e)
{
return new CancelResponse { status = "failed", message = e.Message };
}
} public ListProjectsResponse ListProjects()
{
try
{
var client = new HttpClient
{
BaseAddress = new Uri($"http://{_host}:{_port}")
};
var result = client.GetStringAsync("listprojects.json").Result;
return JsonConvert.DeserializeObject<ListProjectsResponse>(result);
}
catch (Exception e)
{
return new ListProjectsResponse { status = "failed", message = e.Message };
}
} public ListVersionsResponse ListVersions(string project)
{
if (string.IsNullOrEmpty(project)) throw new ArgumentNullException(nameof(project)); try
{
var client = new HttpClient
{
BaseAddress = new Uri($"http://{_host}:{_port}")
}; var result = client.GetStringAsync($"listversions.json?project={project}").Result;
return JsonConvert.DeserializeObject<ListVersionsResponse>(result);
}
catch (Exception e)
{
return new ListVersionsResponse { status = "failed", message = e.Message };
}
} public ListSpidersResponse ListSpiders(string project, string version = "")
{
if (string.IsNullOrEmpty(project)) throw new ArgumentNullException(nameof(project)); try
{
var client = new HttpClient
{
BaseAddress = new Uri($"http://{_host}:{_port}")
}; var result = client.GetStringAsync($"listspiders.json?project={project}&_version={version}").Result;
return JsonConvert.DeserializeObject<ListSpidersResponse>(result);
}
catch (Exception e)
{
return new ListSpidersResponse { status = "failed", message = e.Message };
}
} public ListJobsResponse ListJobs(string project)
{
if (string.IsNullOrEmpty(project)) throw new ArgumentNullException(nameof(project)); try
{
var client = new HttpClient
{
BaseAddress = new Uri($"http://{_host}:{_port}")
}; var result = client.GetStringAsync($"listjobs.json?project={project}").Result;
return JsonConvert.DeserializeObject<ListJobsResponse>(result);
}
catch (Exception e)
{
return new ListJobsResponse { status = "failed", message = e.Message };
}
} public ScrapydResponse DeleteVersion(string project, string version)
{
if (string.IsNullOrEmpty(project)) throw new ArgumentNullException(nameof(project));
if (string.IsNullOrEmpty(version)) throw new ArgumentNullException(nameof(version)); var client = new HttpClient()
{
BaseAddress = new Uri($"http://{_host}:{_port}")
}; try
{
var data = new Dictionary<string, string>()
{
{"project", project},
{"version", version}
}; var strResult =
client.PostAsync("delversion.json", new FormUrlEncodedContent(data))
.Result.Content.ReadAsStringAsync()
.Result; return JsonConvert.DeserializeObject<ScrapydResponse>(strResult); }
catch (Exception e)
{
return new ScrapydResponse { status = "failed", message = e.Message };
}
} public ScrapydResponse DeleteProject(string project)
{
if (string.IsNullOrEmpty(project)) throw new ArgumentNullException(nameof(project)); var client = new HttpClient()
{
BaseAddress = new Uri($"http://{_host}:{_port}")
}; try
{
var data = new Dictionary<string, string>()
{
{"project", project}
}; var strResult =
client.PostAsync("delproject.json", new FormUrlEncodedContent(data))
.Result.Content.ReadAsStringAsync()
.Result; return JsonConvert.DeserializeObject<ScrapydResponse>(strResult); }
catch (Exception e)
{
return new ScrapydResponse { status = "failed", message = e.Message };
}
} } }
博客地址 : http://www.cnblogs.com/mobwiz/
【原创】Scrapyd 的 .net 客户端的更多相关文章
- 原创:Javascript Websocket客户端封装
调试中,马马虎虎能用var LeesWebSocket = function (options) { this.defaults = { host: "127.0.0.1", po ...
- 微信团队原创分享:iOS版微信的内存监控系统技术实践
本文来自微信开发团队yangyang的技术分享. 一.前言 FOOM(Foreground Out Of Memory),是指App在前台因消耗内存过多引起系统强杀.对用户而言,表现跟crash一样. ...
- 让互联网更快:新一代QUIC协议在腾讯的技术实践分享
本文来自腾讯资深研发工程师罗成在InfoQ的技术分享. 1.前言 如果:你的 App,在不需要任何修改的情况下就能提升 15% 以上的访问速度,特别是弱网络的时候能够提升 20% 以上的访问速度. 如 ...
- 【转】手把手教你读取Android版微信和手Q的聊天记录(仅作技术研究学习)
1.引言 特别说明:本文内容仅用于即时通讯技术研究和学习之用,请勿用于非法用途.如本文内容有不妥之处,请联系JackJiang进行处理! 我司有关部门为了获取黑产群的动态,有同事潜伏在大量的黑产群 ...
- 全面解密QQ红包技术方案:架构、技术实现、移动端优化、创新玩法等
本文来自腾讯QQ技术团队工程师许灵锋.周海发的技术分享. 一.引言 自 2015 年春节以来,QQ 春节红包经历了企业红包(2015 年).刷一刷红包(2016 年)和 AR 红包(2017 年)几个 ...
- 微信团队分享:Kotlin渐被认可,Android版微信的技术尝鲜之旅
本文由微信开发团队工程是由“oneliang”原创发表于WeMobileDev公众号,内容稍有改动. 1.引言 Kotlin 是一个用于现代多平台应用的静态编程语言,由 JetBrains 开发( ...
- 腾讯技术分享:GIF动图技术详解及手机QQ动态表情压缩技术实践
本文来自腾讯前端开发工程师“ wendygogogo”的技术分享,作者自评:“在Web前端摸爬滚打的码农一枚,对技术充满热情的菜鸟,致力为手Q的建设添砖加瓦.” 1.GIF格式的历史 GIF ( Gr ...
- 微信技术分享:微信的海量IM聊天消息序列号生成实践(算法原理篇)
1.点评 对于IM系统来说,如何做到IM聊天消息离线差异拉取(差异拉取是为了节省流量).消息多端同步.消息顺序保证等,是典型的IM技术难点. 就像即时通讯网整理的以下IM开发干货系列一样: <I ...
- 手把手教你读取Android版微信和手Q的聊天记录(仅作技术研究学习)
1.引言 特别说明:本文内容仅用于即时通讯技术研究和学习之用,请勿用于非法用途.如本文内容有不妥之处,请联系JackJiang进行处理! 我司有关部门为了获取黑产群的动态,有同事潜伏在大量的黑产群 ...
随机推荐
- windows使用composer.phar
把composer.phar复制到php安装目录下, 新建一个composer.bat文件,编辑 @php "%~dp0composer.phar" %* 保存,然后就可以使用co ...
- python学习笔记(五) 200行实现2048小游戏
用前文提到的基础知识,和网上流行的2048源码,用python实现该游戏. 先将用户操作和游戏逻辑绑定. WASD分别对应移动方向上.左.下.右 然后实现矩阵的转置和逆置,这样只要实现一个方向的移动, ...
- Kubernetes Job配置
我们知道使用kubernetes的rc或者rs创建的pod,kubernetes会实时监控其健康状态,如果发现pod挂掉以后,会自动启动一个新的,让pod的数量始终保持在指定的replicas上.那么 ...
- org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'sessionFactory' is defined
请检查你在web.xml中加载spring.xml文件的时候没有加载成功,看你的路径是否正确 <context-param> <param-name>contextConfi ...
- 前端PHP入门-029-文件操作-掌握级别
人生只有三天,活在昨天的人迷惑:活在明天的人等待:活在今天的人最踏实.你永远无法预测意外和明天哪个来得更早,所以,我们能做的,就是尽最大的努力过好今天.请记住:今天永远是昨天死去的人所期待的明天. f ...
- UVA 818 Cutting Chains
https://vjudge.net/problem/UVA-818 题意: 有n个圆环,其中有一些已经扣在了一起.现在需要打开尽量少的圆环,使得所有圆环可以组成一条链 n<=15 因为n< ...
- css3中新增的样式使用方法
在PC版开发中由于IE原因,我们很少用到css3,但随着平板和智能手机进入我们的生活,以及现在越来越流行,在手机版和平板版开发中我们就可以大胆的使用了,下面我们探讨常用几个css3属性: 1.css3 ...
- System中关于Property的方法
System类在java.lang包中,所有方法都是静态的,里边有很多对系统的属性和控制方法 System类有三个成员变量:out-标准输出流(默认是控制台),in-标准输入流(默认是键盘),err- ...
- 旅游(CSUST省赛选拔赛2+状压dp+最短路)
题目链接:http://csustacm.com:4803/problem/1016 题目: 思路:状压dp+最短路,比赛的时候有想到状压dp,但是最短路部分写挫了,然后就卡死了,对不起出题人~dis ...
- 2017ACM暑期多校联合训练 - Team 2 1009 HDU 60563 TrickGCD (容斥公式)
题目链接 Problem Description You are given an array A , and Zhu wants to know there are how many differe ...