【原创】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进行处理! 我司有关部门为了获取黑产群的动态,有同事潜伏在大量的黑产群 ...
随机推荐
- dfs.datanode.du.reserved 预留空间不生效的问题
生产环境(cdh5.5.1)遇到一个问题:已经设置 dfs.datanode.du.reserved预留空间为20G,但是磁盘仍然被写满了. 当挂载磁盘作为datanode的存储空间,如果磁盘大小为2 ...
- Linux常用网络工具:fping主机扫描
Linux下有很多强大网络扫描工具,网络扫描工具可以分为:主机扫描.主机服务扫描.路由扫描等. fping是一个主机扫描工具,相比于ping工具可以批量扫描主机. fping官方网站:http://f ...
- HTML5 Web Notifications 桌面推送小记
目录 简介 常用API 手动设置权限 简介 Web Notifications目前在w3c的协议中已经是"推荐"(REC:Recommendation)阶段,除了iE外,各大现代浏 ...
- is_int is_float 判断数值是否为整数
is_float — 检测变量是否是浮点型 http://cn.php.net/manual/zh/function.is-float.php is_int — 检测变量是否是整数 http://cn ...
- CentOS下安装JDK1.8
0.卸载旧版本 键入命令java-version,查询当前JDK版本 如果版本号不是想要的,键入rpm -qa|grep gcj 键入命令 yum -y remove (后接查询得到的版本),移除老版 ...
- ASP.NET Session详解笔记
(一) 描述 当用户在 Web 应用程序中导航 ASP.NET 页时,ASP.NET 会话状态使您能够存储和检索用户的值.HTTP 是一种无状态协议.这意味着 Web 服务器会将针对页面的每个 HTT ...
- 简易版jquery
最近写了一个简易版的jquery github地址:https://github.com/jiangzhenfei/Easy-Jquery 完成的方法: 1.$('#id') 2.extend扩展 ...
- React Native DEMO for Android
Demo1: 主要知识:navigator,fecth 地址:https://github.com/hongguangKim/ReactNativeDEMO1 Demo2: 主要知识:navigato ...
- TinyOS在ubuntu 14.04下安装教程
1:打开/etc/apt/sources.list 文件,在文件最底部添加安装源: deb http://tinyos.stanford.edu/tinyos/dists/ubuntu lucid m ...
- python中随机数生成
1.random.random random.random()用于生成一个0到1的随机符小数: 0 <= n < 1.0 2.random.uniform random.uniform的函 ...