最近项目需要部署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 客户端的更多相关文章

  1. 原创:Javascript Websocket客户端封装

    调试中,马马虎虎能用var LeesWebSocket = function (options) { this.defaults = { host: "127.0.0.1", po ...

  2. 微信团队原创分享:iOS版微信的内存监控系统技术实践

    本文来自微信开发团队yangyang的技术分享. 一.前言 FOOM(Foreground Out Of Memory),是指App在前台因消耗内存过多引起系统强杀.对用户而言,表现跟crash一样. ...

  3. 让互联网更快:新一代QUIC协议在腾讯的技术实践分享

    本文来自腾讯资深研发工程师罗成在InfoQ的技术分享. 1.前言 如果:你的 App,在不需要任何修改的情况下就能提升 15% 以上的访问速度,特别是弱网络的时候能够提升 20% 以上的访问速度. 如 ...

  4. 【转】手把手教你读取Android版微信和手Q的聊天记录(仅作技术研究学习)

    1.引言 特别说明:本文内容仅用于即时通讯技术研究和学习之用,请勿用于非法用途.如本文内容有不妥之处,请联系JackJiang进行处理!   我司有关部门为了获取黑产群的动态,有同事潜伏在大量的黑产群 ...

  5. 全面解密QQ红包技术方案:架构、技术实现、移动端优化、创新玩法等

    本文来自腾讯QQ技术团队工程师许灵锋.周海发的技术分享. 一.引言 自 2015 年春节以来,QQ 春节红包经历了企业红包(2015 年).刷一刷红包(2016 年)和 AR 红包(2017 年)几个 ...

  6. 微信团队分享:Kotlin渐被认可,Android版微信的技术尝鲜之旅

    本文由微信开发团队工程是由“oneliang”原创发表于WeMobileDev公众号,内容稍有改动. 1.引言   Kotlin 是一个用于现代多平台应用的静态编程语言,由 JetBrains 开发( ...

  7. 腾讯技术分享:GIF动图技术详解及手机QQ动态表情压缩技术实践

    本文来自腾讯前端开发工程师“ wendygogogo”的技术分享,作者自评:“在Web前端摸爬滚打的码农一枚,对技术充满热情的菜鸟,致力为手Q的建设添砖加瓦.” 1.GIF格式的历史 GIF ( Gr ...

  8. 微信技术分享:微信的海量IM聊天消息序列号生成实践(算法原理篇)

    1.点评 对于IM系统来说,如何做到IM聊天消息离线差异拉取(差异拉取是为了节省流量).消息多端同步.消息顺序保证等,是典型的IM技术难点. 就像即时通讯网整理的以下IM开发干货系列一样: <I ...

  9. 手把手教你读取Android版微信和手Q的聊天记录(仅作技术研究学习)

    1.引言 特别说明:本文内容仅用于即时通讯技术研究和学习之用,请勿用于非法用途.如本文内容有不妥之处,请联系JackJiang进行处理!   我司有关部门为了获取黑产群的动态,有同事潜伏在大量的黑产群 ...

随机推荐

  1. Spring MVC 使用Servlet原生API作为参数

    具体看代码: @RequestMapping("/testServletAPI") public void testServletAPI(HttpServletRequest re ...

  2. python 常用 time, datetime处理

    python 中 time 有三种格式: float, struct tuple(time.struct_time 或 datetime.datetime), str 常用的: float --> ...

  3. Calculating and saving space in PostgreSQL

    Q: I have a table in pg like so: CREATE TABLE t ( a BIGSERIAL NOT NULL, -- 8 b b SMALLINT, -- 2 b c ...

  4. Educational Codeforces Round 24 A 水 B stl C 暴力 D stl模拟 E 二分

    A. Diplomas and Certificates time limit per test 1 second memory limit per test 256 megabytes input ...

  5. 洛谷P3740 [HAOI2014]贴海报

    题目描述 Bytetown城市要进行市长竞选,所有的选民可以畅所欲言地对竞选市长的候选人发表言论.为了统一管理,城市委员会为选民准备了一个张贴海报的electoral墙. 张贴规则如下: electo ...

  6. 2017 ACM-ICPC 西安网络赛 F.Trig Function Chebyshev多项式

    自己太菜,数学基础太差,这场比赛做的很糟糕.本来想吐槽出题人怎么都出很数学的题,现在回过头来想还是因为自己太垃圾,竞赛就是要多了解点东西. 找$f(cos(x))=cos(nx)$中$x^m$的系数模 ...

  7. PHP扩展开发--02.包裹第三方的扩展

    背景 也许最常见的PHP扩展是那些包裹第三方C库的扩展.这些扩展包括MySQL或Oracle的数据库服务库,libxml2的 XML技术库,ImageMagick 或GD的图形操纵库. 在本节中,我们 ...

  8. 批量提取图片主要3个颜色匹配中文名字并写入到excel设置对应颜色的背景

    from gevent import monkey monkey.patch_all() import gevent from haishoku.haishoku import Haishoku im ...

  9. Centos7环境下消息队列之ActiveMQ实战

    Activemq介绍 对于消息的传递有两种类型: 一种是点对点的,即一个生产者和一个消费者一一对应: 另一种是发布/订阅模式,即一个生产者产生消息并进行发送后,可以由多个消费者进行接收. JMS定义了 ...

  10. spring-boot 更换依赖版本

    创建Spring Boot操作步骤如下: 在File菜单里面选择 New > Project,然后选择Spring Initializr 更换版本 或 pom spring-boot-start ...