最近项目需要部署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. ICPC 2018 南京网络赛 J Magical Girl Haze(多层图最短路)

    传送门:https://nanti.jisuanke.com/t/A1958 题意:n个点m条边的路,你有k次机会将某条路上的边权变为0,问你最短路径长度 题解:最短路变形,我们需要在常规的最短路上多 ...

  2. poppo大根堆的原理与实现。

    大根堆的定义:1 大根堆是一个大根树 2 大根堆是一个完全二叉树 所以大根堆用数组表示是连续的,不会出现空白字段. 对于大根堆的插入 对于大根堆的插入,可以在排序前确定大根堆的形状,可以确定元素5从位 ...

  3. python---twisted的使用,使用其模拟Scrapy

    twisted的网络使用 twisted的异步使用 一:简单使用 from twisted.internet import defer from twisted.web.client import g ...

  4. Digging(DP)

    ZOJ Problem Set - 3689 Digging Time Limit: 2 Seconds      Memory Limit: 65536 KB When it comes to th ...

  5. c# WebService SOAP及Rest调用

    SOAP及Rest的调用区别参照如下: REST似乎在一夜间兴起了,这可能引起一些争议,反对者可以说REST是WEB诞生之始甚而是HTTP出现之日就相伴而生的原则.但是毋庸置疑的事实是,在Google ...

  6. delphi 7 连接 MySql

    网上有很多关于Delphi连接MySql数据库的文章,在这里,我只记录下自己测试过的方法,以备所需.系统环境:Windows XP SP3软件环境:Delphi 7 .mysql-installer- ...

  7. 【LibreOJ】#6257. 「CodePlus 2017 12 月赛」可做题2

    [题意]数列满足an=an-1+an-2,n>=3.现在a1=i,a2=[l,r],要求满足ak%p=m的整数a2有多少个.10^18. [算法]数论(扩欧)+矩阵快速幂 [题解]定义fib(i ...

  8. matlab核函数与滑窗

    在处理图像时,为了提取特征,经常用各种核函数和图像进行卷积,其实就是通过一个矩阵以滑窗的形式与原图像进行点乘求和,可以看作对一个像素和附近像素进行了加权平均. 比如经常用3x3的近似高斯卷积核 0 1 ...

  9. 59、有用过with statement吗?它的好处是什么?

    python中的with语句是用来干嘛的?有什么作用? with语句的作用是通过某种方式简化异常处理,它是所谓的上下文管理器的一种 用法举例如下: with open('output.txt', 'w ...

  10. eclipse启动项目

    今天做的任务不多,没有自己写代码,上午看了些文章,下午我司后台给配了配项目环境,全装C盘了..以后有我好受的.. 看着后台操作,修改了N多配置,tomcat.redis.zkServer..Nginx ...