User-Agent:主要用来将我们的爬虫伪装成浏览器。
Cookie:主要用来保存爬虫的登录状态。
连接数:主要用来限制单台机器与服务端的连接数量。
代理IP:主要用来伪装请求地址,提高单机并发数量。
爬虫工作的方式可以归纳为两种:深度优先、广度优先。
深度优先就是一个连接一个连接的向内爬,处理完成后再换一下一个连接,这种方式对于我们来说缺点很明显。
广度优先就是一层一层的处理,非常适合利用多线程并发技术来高效处理,因此我们也用广度优先的抓取方式。
首先我们用Visual Studio 2015创建一个控制台程序,定义一个简单的SimpleCrawler类,里面只包含几个简单的事件:
public class SimpleCrawler
{
public SimpleCrawler() { }
/// <summary>
/// 爬虫启动事件
/// </summary>
public event EventHandler<OnStartEventArgs> OnStart;
/// <summary>
/// 爬虫完成事件
/// </summary>
public event EventHandler<OnCompletedEventArgs> OnCompleted;
/// <summary>
/// 爬虫出错事件
/// </summary>
public event EventHandler<Exception> OnError;
/// <summary>
/// 定义cookie容器
/// </summary>
public CookieContainer CookieContainer { get; set; }
}
接着我们创建一个OnStart的事件对象:
然后我们创建一个OnCompleted事件对象:
最后我们再给它增加一个异步方法,通过User-Agent将爬虫伪装成了Chrome浏览器
/// <summary>
/// 异步创建爬虫
/// </summary>
/// <param name="uri"></param>
/// <param name="proxy"></param>
/// <returns></returns>
public async Task<string> Start(Uri uri, WebProxy proxy = null)
{
return await Task.Run(() =>
{
var pageSource = string.Empty;
try
{
if (this.OnStart != null)
this.OnStart(this, new OnStartEventArgs(uri));
Stopwatch watch = new Stopwatch();
watch.Start();
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
request.Accept = "*/*";
//定义文档类型及编码
request.ContentType = "application/x-www-form-urlencoded";
request.AllowAutoRedirect = false;//禁止自动跳转
request.UserAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36";
//定义请求超时事件为5s
request.Timeout = 5000;
//长连接
request.KeepAlive = true;
request.Method = "GET";
//设置代理服务器IP,伪装请求地址
if (proxy != null)
request.Proxy = proxy;
//附加Cookie容器
request.CookieContainer = this.CookieContainer;
//定义最大链接数
request.ServicePoint.ConnectionLimit = int.MaxValue;
//获取请求响应
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
//将Cookie加入容器,保持登录状态
foreach (Cookie cookie in response.Cookies)
this.CookieContainer.Add(cookie);
//获取响应流
Stream stream = response.GetResponseStream();
//以UTF8的方式读取流
StreamReader reader = new StreamReader(stream,Encoding.UTF8);
//获取网站资源
pageSource = reader.ReadToEnd();
watch.Stop();
//获取当前任务线程ID
var threadID = Thread.CurrentThread.ManagedThreadId;
//获取请求执行时间
var milliseconds = watch.ElapsedMilliseconds;
reader.Close();
stream.Close();
request.Abort();
response.Close();
if (this.OnCompleted != null)
this.OnCompleted(this, new OnCompletedEventArgs(uri, threadID, milliseconds, pageSource));
}
catch (Exception ex)
{
if (this.OnError != null)
this.OnError(this, ex);
}
return pageSource;
});
}
在控制台里写下爬虫的抓取代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace TestPa
{
class Program
{
static void Main(string[] args)
{
//定义入口URl
var cityUrl = "http://hotels.ctrip.com/citylist";
//定义泛型列表存放城市名称及对应的酒店
var cityList = new List<City>();
//调用自己写的爬虫程序
var cityCrawler = new SimpleCrawler();
cityCrawler.OnStart += (s, e) =>
{
Console.WriteLine("爬虫开始抓取的地址:" + e.Uri.ToString());
};
cityCrawler.OnError += (s, e) =>
{
Console.WriteLine("爬虫抓取出现错误:" + e.Message);
};
cityCrawler.OnCompleted += (s, e) =>
{
var links = Regex.Matches(e.PageSource, @"<a[^>]+href=""*(?<href>/hotel/[^>\s]+)""\s*[^>]*>(?<text>(?!.*img).*?)</a>", RegexOptions.IgnoreCase);
foreach(Match match in links)
{
var city = new City
{
CityName = match.Groups["text"].Value,
Uri = new Uri("http://hotels.ctrip.com" + match.Groups["href"].Value)
};
if (!cityList.Contains(city))
cityList.Add(city);
Console.WriteLine(city.CityName + "||" + city.Uri);
}
Console.WriteLine(e.PageSource);
Console.WriteLine("**********************************");
Console.WriteLine("爬虫抓取完成");
Console.WriteLine("耗时:" + e.Milliseconds + " 毫秒");
Console.WriteLine("线程:" + e.ThreadID);
Console.WriteLine("地址:" + e.Uri.ToString());
};
cityCrawler.Start(new Uri(cityUrl)).Wait();
Console.ReadKey();
}
}
public class City
{
public string CityName { get; set; }
public Uri Uri { get; set; }
}
}
运行结果:
请看大神原文地址
基于.NET更高端智能化的网络爬虫
这篇是幕课网-MySQL5.7复制功能实战视频教程的学习笔记。http://www.imooc.com/learn/589第1章 MySQL复制基础MySQL是异步复制采取针对特定用户的读写分离,可以实现假无延迟。MySQL复制是基于binlog日志进行的。存在三种日志格式:statement格式 存储SQL语句,存储日志量最小row格式 ...
===========================华丽的main.c分界线====================================#include "stm32f10x.h"#include "LCD_driver.h"#include"chinese.h"#include"picture.h"#define LCD_cs(x) ...
一、硬件电路接口图片 1.ADXL345硬件接口图片使用的是SPI端口进行通信,这样读取数据比较快且后续也可以转化为IIC通信接口。在网上找一些发现IIC接口的比较多,所以本人就DIY做SPI的通信。2.STM32F103T系列单片机作为MCU 资源比较丰富、本人比较熟悉开发速度较快硬件电路首先是为了实现功能,所以设计比较简单。后续小编想做无线蓝牙的数据传输,所以硬件上...
欢迎加入ifast 交流群,群聊号码:746358408 ,关注的朋友请加群,博客留言信息不带回哈需求:登录用户产生一个二维码,下一个人扫描这个二维码之后关注公众号,登录之后自动成为第一个用户的粉丝吐槽一把,这个需求很操蛋。。。。但是,操不操蛋那是你程序猿说的不?微信开发本来就相当操蛋了。。。都懂得,文档又少,限制又多,傻逼的很。。。。首先看下微信官方的文档,我们先了解...
最近工作中遇到 一个需求,是需要通过QT的界面去调用adb命令完成将PC端的文件传输到安卓手机上。到网上查询资料后发现QT中的QProcess类可以完成这个需求,简单用法如下:QProcess *process = new QProcess(this);process->start("ls");ui->textEdit->append(process->readAl...
原文地址https://blog.csdn.net/Notzuonotdied/article/details/77876080简单演示import matplotlib.pyplot as pltimport numpy as np# 从[-1,1]中等距去50个数作为x的取值x = np.linspace(-1, 1, 50)print(x)y = 2*x + 1# 第一个是横坐标的值,第二个...
echarts使用入门导入echarts库import * as echarts from "echarts";ui<div id="manuChart" class="chart-div"></div>vue中的代码操作dom的代码尽量放在window.onload中。该横向柱状图可以实现鼠标上下滑动操作,并且禁止了放大缩小的功能。createdManuChart() { window.onload = () => { const m
毫米波雷达TI官方文档阅读笔记
原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://21cnbao.blog.51cto.com/109393/3376091.1 platform总线、设备与驱动在Linux 2.6的设备驱动模型中,关心总线、设备和驱动这3个实体,总线将设备和驱动绑定。在系统每注册一个设备的时候,会寻找与之匹配的驱动;相反的,
Android 并发第五篇本篇会讲解如何利用 HandlerThread 实现异步操作。HandlerThread 本身其实就是一个 Thread ,但是其内部还利用 Handler 机制。 对于提交的任务(或者说是信息 Message)依次处理。 所以在介绍 HandlerThread 原理以及如果使用之前,会首先说一个 Handler 异步机制。当然 Handler, Looper, Mes
1. Maximum license type (copying, scripts, etc. work now).2. Fixed integrity check #1.3. Fixed integrity check #2.4. All the telemetry has been cut out.5. Removed the update checks and other shit ...
基本用法show create table (目标表格) 结果为:+-----------------+---------------------------------------------------------------------------------------------------------------------------------------------------...