[转载]SQL索引学习-索引结构 - min.jiang - 博客园

mikel阅读(1163)

[转载]SQL索引学习-索引结构 – min.jiang – 博客园.

前一阵无意中和同事讨论过一个SQL相关的题(通过一个小问题来学习SQL关联查询), 很惭愧一个非常简单的问题由于种种原因居然没有回答正确,数据库知识方面我算不上技术好,谈起SQL知识的学习我得益于2008年进的一家公司,有几个 DBA技术相当专业,正好手上有一个项目遇到了一些数据库查询性能问题,就试着想办法优化,于是自己将相法和DBA沟通后,居然得到了他们的赞同,让我信 心大增,后来一段时间我又主动找他们聊了一些其它的知识,所以在数据库索引这块我算是相对一般的.net程序员要更加有见解一些。当时我们部门由于分工的 不同,部门20多人基本上工作中从来不和SQL打交道,后台的接口都由其它部门来完成了,我们注意的 业务逻辑,所以有一些完全不懂SQL的程序员。之后的四年我大部分都是做一些通用平台架构方面的工作,也比较少直接接触SQL,直到后来换了公司,特别是 去年开始由于项目性质的变化,我开始慢慢又开始接触SQL。

工作时间的长短在某种程度上能决定一个人的技术水平,但往往技术水平和实际工作的产出不一定成正比。比如我上面提到那个SQL问题,很多有经验的程 序员在第一个答案中往往回答错误,但他确实能将项目做好,因为大家平时观注的还是结果,只要结果出来了比什么都强,至于为什么出这样的结果一般也就不会多 做分析研究。这种形式呢,对那些对技术提升没有强烈要求的人来讲,已经够用了,多试几次,只要最终能出结果也就万事大吉了,做的多了,后续遇到类似的问题 也就轻车熟路了,这就是所谓的经验,只知道这样做就能出结果。

其实这种工作学习方式呢,有一个比较显著的问题,就是对自己写出来的东西没有足够的信心,因为靠的是以往的经验。是出现错误之后通过不断的尝试来取 得的经验,有一种探索的味道,在工作效率上会存在问题,因为总有你以前没有遇到过的场景,这样你可能对第一方案做多次尝试才找到正解,反之的话,第一个方 案可能花的时间稍长一些,但后续反复修改的次数会相当较少。

SQL索引目录

借这次机会呢,将SQL索引的理解整理出来,供大家一起学习提高,这是我的学习笔记,有错误的地方,欢迎大家批评指正。下面是预计的目录:

  • 索引基础知识
  • 聚集索引
  • 非聚集索引
  • 认识执行计划
  • 灵活设计数据库

页和区

要想做好索引优化,知道索引的存储结构是至关重要的。谈到存储就需要了解SQL中的页和区的概念:

  • SQL中存储数据的基础单位就是页,一个页大小为8K,数据库可以将数据从逻辑上分成页,磁盘的I/O操作就是在页级执行。页包信三项内容:
    • 96字节大小的标头,存储统计信息,包括页码、页类型、页的可用空间以及拥有该页的对象的分配单元 ID。页类型我们知识如下三项基本就够用:
      • 数据页,除了大型对象的数据列之外的数据存储页,比如int,float,varchar等。
      • 索引页,存放索引的条目。
      • 大型对象数据类型,比如text,image,nvarchar(max)等。
    • 数据行
    • 行偏移量
  • 一个区包含8个页,它是管理空间的单位,分为如下两类
    • 统一区,由单个对象所有。
    • 混合区,最多可由八个对象共享。
  • 一般情况下,给表或者索引申请新的空间时,从混合区分配,当这个表或者索引的空间超过8个页大小时,会将原本在混合区的页转移到统一区管理。

表存储结构

知识了区以及页的概念,再看下数据表和这两者之间的联系, 表包含一个或多个分区,每个分区在一个堆或一个聚集索引结构中包含数据行。从下图的结构中,我们就看到了索引的重要结构B-树了。

 

聚集索引结构

索引中的底层节点称为叶节点。根节点与叶节点之间的任何索引级别统称为中间级。在聚集索引中,叶节点包含基础表的数据页。根节点和中间级节点包含存 有索引行的索引页。每个索引行包含一个键值和一个指针,该指针指向 B -树上的某一中间级页或叶级索引中的某个数据行。每级索引中的页均被链接在双向链接列表中。

非聚集索引结构

非聚集索引与聚集索引之间的显著差别在于以下两点:

  • 基础表的数据行不按非聚集键的顺序排序和存储。
  • 非聚集索引的叶层是由索引页而不是由数据页组成。

问题:

  • 索引的结构到底分多少层?

我们先看下B-树,这种索引结构有一个重要的参数n,它决定了索引存储页的布局,每个存储 页需要存放n个节点,以及n+1个指针。 这里我们来做个计算:比如我们的索引是一个整形数字,4个字节,指针需要8个字节,这里不考虑索引页标头信息的占用,算下最大的n,公式: 4n+8(n+1)<=8*1024 ,这个值是680,即最大可存放680个键,再按B-树充满度来取75%等于510,根结点有510个,那么它会有510*510个叶结点,这些叶结点会 有510*510*510个指向最终记录的指针。这个数据足以说明绝多数情况下,只要三层就能够用。

  • 什么是稠密索引?

索引中的键顺序与数据文件中的排序顺序相同,所以我们的索引结构中,叶级均采用稿密索引。

  • 什么是稀疏索引?

它只为每个存储块设计键-指针对,比稿密索引节约空间,出现在叶级之上的结构中。

  • 索引结构中会出现如下情况吗?

要想回答这个问题,就需要了解索引在维护过程中对于B-树的调整,SQL会通过一定的算法将B-树的充满度达到一定的平衡,这里就会涉及的节点的拆分以及合并,所以一般情况下无论对数据做怎样的更新,也不会出现下图中如此不平衡的情况。

注:如果问重建索引的好处时,如果你回答是为了平衡B-树,那么要谨慎回答。

   

总结

数据存储的基础知识,索引结构对于我们后续理解聚集索引以及非聚集索引都非常重要,也才有可能快速准确的做出优化方案。

参考:http://technet.microsoft.com/zh-cn/library/ms180978(v=sql.105).aspx

[转载]SQL开发各阶段常见问题及学习资料汇总 - 数据库 - Tech - ITeye论坛

mikel阅读(1536)

[转载]SQL开发各阶段常见问题及学习资料汇总 – 数据库 – Tech – ITeye论坛.

应广大网友需求,51CTO下载中心花费了一些时间为大家整理出SQL开发中一些常见问题,其中不乏有论坛的精华帖以及博客的优质博文。无论您是新手,还是多年的老鸟,看过这些资料之后,对您今后的开发一定会有很大的帮助。
资源名称       资源地址
SQL语句经典教程【入门精品】 http://down.51cto.com/data/59093
SQL Server 2008编程入门经典(第3版) http://down.51cto.com/data/248244
经典SQL入门书籍 http://down.51cto.com/data/67557
入门篇  深入解析Oracle. DBA入门进阶与诊断案例http://down.51cto.com/data/240107
学习SQL的最好方法是? http://bbs.51cto.com/thread-494288-1.html
SQL基础[论坛推荐] http://bbs.51cto.com/thread-18814-1.html
SQL Server存储过程入门案例详解 http://down.51cto.com/data/32319

两台SQL Server数据同步解决方案(经典)http://down.51cto.com/data/32136
oracle+SQL语法大全【中文版】 http://down.51cto.com/data/64803
SQL语句妙用:各种sql语句的详细用法与讲解http://down.51cto.com/data/70032
Oracle 实战工具Toad(小青蛙)使用手册http://down.51cto.com/data/32809
MySQL技术内幕(第4版)【PDF】 http://down.51cto.com/data/616219
【讨论】如何编写高效的SQL语句? http://bbs.51cto.com/thread-1038655-1.html
进阶篇  SQL Server 2005——有关开发的10个最重要的特点http://bbs.51cto.com/thread-22654-1.html
解决SQLServer事物日志过大的方法 http://bbs.51cto.com/thread-1023360-1.html
一个牛人总结的ORACL+UNIX易错问题集锦http://bbs.51cto.com/thread-693355-1.html
Oracle技术大牛整理常见问题(PDF) http://down.51cto.com/data/888876
MySQL性能优化的最佳20条经验【技术文http://down.51cto.com/data/888181
深入学习MySQL人员必看:MYSQL数据库优化技术文档http://down.51cto.com/data/819579

Sql数据库自动备份恢复助手V1.0b(含相关说明与文档)http://down.51cto.com/data/206963
[SQL工具] PL/SQL Developer10.0.3.1701http://down.51cto.com/data/790022
工具篇    sqljdbc.jar sql2005驱动包 http://down.51cto.com/data/147517
SQL查询分析器绿色版 http://down.51cto.com/data/31963
mysql管理工具MySQLFront+破解补丁 http://down.51cto.com/data/185655
更多资源
http://down.51cto.com/detail_list.php?c_it=45&c_re=0&t_j=&isfree=&sortby=t

[转载]缓存增强用户体验感 - csdbfans - 博客园

mikel阅读(1073)

[转载]缓存增强用户体验感 – csdbfans – 博客园.

  搞Web开发的人,都会听说过缓存,开发中偶尔会遇到换图片、修改引入进来的脚本文件或者是替换Flash文件,你会发现运行出来的结果不变,这时候你肯定也会想过是缓存的原因,会把浏览器的缓存给清除掉。步骤可以如下清除浏览器缓存

清除缓存

今天想写写ASP.NET缓存,搞Web开发,不使用缓存是不可能的。

缓存有分客户端缓存与服务端缓存,但是通常使用服务端缓存。因为客户端的请求都是服务端来响应,那么在服务端来做缓存的话,客户端的请求都可以由缓存来响应。从而使响应的速度更快。缓存是什么?它就像一个时间片段的数据副本,在缓存的有效时间内,客户的请求,服务器都只用相同的数据副本来进行响应。

就因为缓存的这种特征,它使得请求后的响应时间更短,有效提高了服务器的性能,降 低带宽的成本。总之,相同的环境下,使用缓存与不使用缓存,在响应时间比较长的情况下,使用缓存的响应速度会让你惊叹不已。但是缓存虽棒,也有不足之处。 提高了响应速度,带来了数据的不准确性。因为前面也说了缓存是一个时间片段的数据副本,也就是说数据经过增加、删除、更改等加工之后,显示给用户看的效果 还是原来那样。这有时候会让人很恼火,尤其像我这样急性子的人。但使用缓存依赖就可以解决此问题。

同一个人,对于某些人来说,是好人,对于某些人来说,是坏人。所以对事对人来说, 总不能以偏盖全。避开缺点,发挥优势,才是我们需要做的。缓存可以使用在加工频率要求不是特别高的地方 。假如对于用户来说,数据实时性并不特别重要,也 就是对时间的制约不是特别高的话,那么使用缓存确实可以增速不少。

下面我们来看看服务端缓存与客户端缓存。


服务端缓存:

(1)Session针对小量数据,服务于单个用户,默认失效时间为20分钟。

包括三种实现方式,分别是:

=>InProc方式:

数据存储在aspnet_wp.exe 进程中,数据会因为IIS的重启而丢失。

=>StateServer方式 :

较InProc不同,可以存储于不同的服务器中。

=>SQLServer:

数据存储于数据库中,数据不会因为IIS的重启而丢失。

后两种方法与InProc最大的区别在于,我们要确保缓存的数据是可序列化的。否则只能用第一种方式,为此我们要仔细分析从而选出最适合自己的方式.

使用方法:

//存数据

Session[“key”] = value;

//取数据

Object value = Session[“key”]

 

(2)Application任意数据大小,服务于所有用户,拥有整个应用程序的生命周期。通常是针对小数据存储,像实现网站访问量等。

与Session的使用方法相同:

//存数据

Application[“key”] = value;

//取数据

Object value = Application[“key”];

(3)Cache任意数据大小,服务于所有用户,程序指定生命周期。

移除Cache,我们可以使用Cache.Remove(“key”),也可以根据缓存依赖关系来让Cache失效。当依赖的关系有改动时,此时Cache会自动失效。

 

 =》缓存依赖:缓存的生命周期依赖于数据来源的变化,缓存依赖有多种,限于篇幅,只介绍下面两种。

 

I、依赖于文件或文件夹:当磁盘上的一个文件或文件夹发生变化时(修改或者是删除)自动让Cache失效。使用缓存依赖,你可以实例化微软的CacheDependency对象,并给对象传递文件的路径或者是文件夹的路径。如果是文件夹的路径,它会监视该文件夹下的所有文件和里面第一级子文件夹。

   string cacheData="缓存内容";
   CacheDependency fileDependency =new CacheDependency(Server.MapPath("test.xml"));

   Cache.Insert("ERROR_INFO", cacheData, fileDependency);

 

II、依赖于数据库:当数据库中的相关数据被修改时自动让Cache失效。

依赖于文件或文件夹,微软提供CacheDependency对象,但是依赖于数据库,则需要使用另一个对象SQLCacheDependcy。

需要结合SQL Server 2005数据库,目前还没有Oracle数据库的缓存依赖。

使用数据库依赖,ASP.NET可以按如下方式实现:

第一步:web.config两配置

一配置数据库连接字符串:

复制代码
<configuration>
...
     <connectionStrings>
          <add name="ApplicationServices"
          connectionString="data source=.\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|\aspnetdb.mdf;User Instance=true"
          providerName="System.Data.SqlClient" />
     </connectionStrings>
...
</configuration>


 
复制代码

二配置缓存依赖数据库(缓存数据库依赖主要是说明依赖哪个数据库,下面的connectionStringName值与一中的name是一致的)

复制代码
<system.web>
     <caching>
          <SQLCacheDependency enabled = “true” pollTime = “1000” >
              <databases>
                   <add name=”testCache
                      connectionStringName=”ApplicationServices
                      pollTime = “1000”      />
              </databases>
          </sqlCacheDependency>
     </caching>
</system.web>
复制代码

第二步:需要使用缓存数据库的ASPX页面再增加如下语句即可:

复制代码

<%@ Page Title=”主页” Language=”C#” MasterPageFile=”~/Site.master” AutoEventWireup=”true”
CodeBehind=”Default.aspx.cs” Inherits=”SqlCacheDenpendcy._Default” %>

 <%@ OutputCache Duration=”3600″ SqlDependency=”testCache:CacheTable” VaryByParam=”none” %>

复制代码

(4)ASP.NET 页面输出缓存 —ASPX和ASCX页面

在Web站点中,最简单直接有效的方式可以使用页面输出缓存。通过缓存页面来输 出,数据则不像依赖缓存那么准确,因为页面是指定时间失效。这里的页面包括ASPX页面也包括ASCX用户控件页面。ASPX页面是整页面缓存,而 ASCX用户控件页面则是局部缓存。两者的使用方式一样。

代码跟与第数据库依赖的第二步类似:

复制代码

<%@ Page Title=”主页” Language=”C#” MasterPageFile=”~/Site.master” AutoEventWireup=”true”
CodeBehind=”Default.aspx.cs” Inherits=”SqlCacheDenpendcy._Default” %>

<%@ OutputCache Duration=”60″ VaryByParam=”empNum” Location=”Server“%>

复制代码

参数解释:

参数 说明 备注
Duration 页或用户控件进行缓存的时间(以秒计)。 在页或用户控件上设置该特性为来自对象的 HTTP 响应建立了一个过期策略,并将自动缓存页或用户控件输出。 此特性必选。 如果未包含该属性,将出现分析器错误。

除非你的Location=None,可以不添加此属性,其余时候都是必须的。

Location OutputCacheLocation 枚举值之一。 默认值为 Any。
Location当被设置为None时,其余的任何设置将不起作用;
Any——页面被缓存在浏览器、代理服务器端和web服务器端;
Client——缓存在浏览器;
DownStream——页面被缓存在浏览器和任何的代理服务器端;
None——页面不缓存;
ServerAndClient——页面被缓存在浏览器和web服务器端。
包含在用户控件(.ascx 文件)中的 @ OutputCache 指令不支持此特性。
CacheProfile 与该页关联的缓存设置的名称。 这是可选特性,默认值为空字符串 (“”)。 包含在用户控件(.ascx 文件)中的 @ OutputCache 指令不支持此特性。 在页中指定此属性时,属性值必须与 outputCacheSettings 节下面的 outputCacheProfiles 元素中的一个可用项的名称匹配。 如果此名称与配置文件项不匹配,将引发异常。参考CacheProfile实例
NoStore 一个布尔值,它决定了是否阻止敏感信息的二级存储。 包含在用户控件(.ascx 文件)中的 @ OutputCache 指令不支持此特性。 将此特性设置为 true 等效于在请求期间执行以下代码:
Response.Cache.SetNoStore();
ProviderName 一个字符串值,标识要使用的自定义输出缓存提供程序。 此属性仅在用户控件(.ascx 文件)中受到支持。 它不受包含在 ASP.NET 页(.aspx 文件)中的 @ OutputCache 指令的支持。
Shared 一个布尔值,确定用户控件输出是否可以由多个页共享。 默认值为 false。 包含在 ASP.NET 页(.aspx 文件)中的 @ OutputCache 指令不支持此特性。
SqlDependency 标识一组数据库/表名称对的字符串值,页或控件的输出缓存依赖于这些名称对。 请注意,SqlCacheDependency 类监视输出缓存所依赖的数据库中的表,因此当更新表中的项时,使用基于表的轮询时将从缓存中移除这些项。 如果以值 CommandNotification 使用通知(在 Microsoft SQL Server 2005 中),则最终会使用 SqlDependency 类向 SQL Server 2005 服务器注册查询通知。 SqlDependency 特性的 CommandNotification 值仅在网页 (.aspx) 中有效。 用户控件只能将基于表的轮询用于 @ OutputCache 指令。

参考SqlDependency和SqlCacheDependency缓存的用法及具体步骤

VaryByCustom 任何表示自定义输出缓存要求的文本。 如果特性的赋值为 browser,缓存将随浏览器名称和主要版本信息的不同而异。 如果输入自定义字符串,则必须在应用程序的 Global.asax 文件中重写 GetVaryByCustomString 方法。
VaryByHeader 分号分隔的 HTTP 标头列表,用于使输出缓存发生变化。 将该特性设为多标头时,对于每个指定标头组合,输出缓存都包含一个不同版本的请求文档。
Accept-Language——代表请求页面中用户最希望的有优先级顺序的人类语言列表;
User-Agent——代表请求页面设备的类型;
Cookie——代表当前域名下创建的浏览器的cookie项。
设置 VaryByHeader 特性将启用在所有 HTTP 1.1 版缓存中缓存项,而不仅仅在 ASP.NET 缓存中进行缓存。 用户控件中的 @ OutputCache 指令不支持此特性。
例如:设置VaryByHeader=”Accept-Language”。
网站有多种语言版本时,可以为每种语言都进行缓存。
VaryByParam 分号分隔的字符串列表,用于使输出缓存发生变化。 默认情况下,这些字符串对应于使用 GET 方法特性发送的查询字符串值,或者使用 POST 方法发送的参数。 将该特性设置为多个参数时,对于每个指定参数组合,输出缓存都包含一个不同版本的请求文档。 可能的值包括 none、星号 (*) 以及任何有效的查询字符串或 POST 参数名称。 在 ASP.NET 页和用户控件上使用 @ OutputCache 指令时,需要此特性或 VaryByControl 特性。 如果没有包含它,则发生分析器错误。 如果不希望通过指定参数来改变缓存内容,请将值设置为 none。 如果希望通过所有的参数值改变输出缓存,请将特性设置为星号 (*))。
例如:
如果命令设置为:
<%@ OutputCache Duration=”60″  VaryByParam=”ProductType” %>
当 请求路径 bitauto.com/test.aspx?ProductType=1发生时,会建立缓存当ProductType的值变为2时,系统会建立新的缓 存,但是原来的缓存在有效期内并不会失效。相当于为不同的ProductType值建立了不同版本的缓存。如果熟悉.Net数据缓存的话,很类似于下面的 用法。
Cache.Add(“productType1”,cachedObject)
Cache.Add(“productType2”,cachedObject)
VaryByControl  分号分隔的字符串列表,用于改变用户控件的输出缓存。 这些字符串代表用户控件中声明的 ASP.NET 服务器控件的 ID 属性值。  在 ASP.NET 页和用户控件上使用 @ OutputCache 指令时,需要此特性或 VaryByParam 特性。
例如下面:根据页面上下拉列表控件的选择的值不同进行不同的缓存输出
<%@ OutputCache Duration=”100″ VaryByControl=”dropTest”%>
VaryByContentEncodings  以分号分隔的字符串列表,用于更改输出缓存。 将 VaryByContentEncodings 特性用于 Accept-Encoding 标头,可确定不同内容编码获得缓存响应的方式。  

客户端缓存:

  上面介绍了部分服务端缓存的方法,但有的时候我们为了提高服务器的性能我们也需要把数据缓存到客户端。使用这种缓存机制,可以适当缓解服务器压力,不过在客户端缓存数据会有一定的安全性问题。

Cookies:在Web站点中应用非常广,它可以非常方便的在客户端与服务器端之间进行相互访问,最大只能支持4KB,所以一般只能保存小数据。可以储存到客户端的硬盘或内存。

复制代码
if (this.Request.Cookies["key"] == null)
{
    this.Response.Cookies.Add(new HttpCookie("key","test"));
}
else
{
    this.Response.Write(this.Request.Cookies["key"].Value);
}
复制代码

 

题外话,客户端缓存及服务端缓存,在网上查找了很多相关的文章,内容都很丰富,也很详细,通过整理学习,并写成博客,我觉得这种学习方式挺好的。虽然写作能力有高下之分,但是长期以往地坚持,笨鸟也可以先飞。至此,本文告一段落,希望能抛我的砖引大家的玉 🙂

[转载]挺好用的SQLSERVER数据库自动备份工具SQLBackupAndFTP(功能全面) - 桦仔 - 博客园

mikel阅读(1008)

[转载]挺好用的SQLSERVER数据库自动备份工具SQLBackupAndFTP(功能全面) – 桦仔 – 博客园.

这个工具主要就是自动备份数据库,一键还原数据库,发送备份数据库日志报告到邮箱,自动压缩备份好的数据库

定期执行数据库备份任务,取代SSMS的维护计划,上传数据库备份文件到FTP服务器、其他网络硬盘等

软件有免费付费两种模式,不过本人觉得免费版本的功能已经足够了

支持SQLServer版本:SQLServer2000、SQLServer2005、SQLSERVER2008、SQLSERVER2008 R2、SQLSERVER2012

当你的电脑是 SQL Server Express 2005 and SQL Server Express 2008版本的时候特别有用

因为SQLSERVER Express版本没有维护计划,使用SQLBackupAndFTP可以解决这个问题

这个工具也有MYSQL版本

MYSQL版本下载地址:http://mysqlbackupftp.com/download/

SQLSERVER Azure特别版下载地址:http://files.cnblogs.com/lyhabc/SqlBakSetupAzure.rar

官方网站http://sqlbackupandftp.com/

 

安装路径:C:\Program Files\Pranas.NET\SQLBackupAndFTP

安装目录下主要都是一些DLL

SQLBackupAndFTP会新建一个Windows服务,用来定时备份数据库,取代SSMS的维护计划,

我们公司开发的数据库备份软件也是使用Windows服务的方式来定时备份数据库的,其实这些软件的原理差不多

 

 


看到上面这些图片,我相信想破解这款软件的人开始蠢蠢欲动了,不过最好不要破解,尊重一下别人

大家使用免费版本就行了,最好不要破解他的付费功能

一些设置选项

首先设置数据库连接

勾选中要备份的数据库

设置邮件,把备份报告发到邮箱

设置定时任务,可以设置完整备份,差异备份,事务日志备份,

还可以设置使用系统任务计划来运行定时任务还是使用软件的Windows服务来运行

软件本身也预设了一些定时选项,用鼠标点击一下就可以应用了

设置备份选项,包括大型数据库临时文件存放路径,压缩备份文件选项,是否校验备份文件,备份数据库日志存放路径,加密备份文件(收费)

我把备份数据库日志和大型数据库临时文件的路径都设置在D:\MSSQL\Databackup

设置了上面的备份路径之后还需要回到主界面设置备份路径,备份数据库文件可以上传到FTP服务器,DROPBOX,SKYDRIVE(要付费)等

我把备份文件放到与备份数据库日志同一路径下 D:\MSSQL\Databackup

软件还可以设置自动删除多久以前的备份文件,还可以备份到远程路径,NAS存储上,

如果是网络路径,可以点击“Test”按钮测试是否连通

设置FTP


 

全部设置完毕之后可以把配置保存起来,当重装软件,或者换了机器之后就不用再设置了

导出配置文件

设置好之后可以点击“run now”按钮手动执行备份,以后就会按照定时任务设置里的设置计划去执行数据库备份操作了

打开邮箱就能看到邮件了

在路径下可以看到日志和已经压缩了的备份文件

日志

View Code

可以看到备份文件大小为5.1MB,压缩之后是886KB,压缩比例挺高的

 


一键还原数据库

点击还原按钮

选择数据库备份文件的路径

如果数据库正在使用中,他会问你是否终止数据库的所有进程

点击”是”

还原成功


主要功能限制

定时任务只支持2个数据库,不过这些功能限制对于我本人来讲影响不大o(∩_∩)o

SQLBackupAndFTP软件介绍到这里了~

[转载]asp.net实现通用水晶报表 - 虾米瓦格 - 博客园

mikel阅读(1172)

[转载]asp.net实现通用水晶报表 – 虾米瓦格 – 博客园.

此片博文是在你有一定水晶报表基础的前提下参阅的;如果对于水晶报表的基础知识比较薄弱建议先去了解下水晶报表;

因为项目需要,研究了下水晶报表。说实在,这个组件很强大,但是用起来也很麻烦。刚开始使用遇到了老多问题。然后上了搜索引擎搜索。但是我发 现,有一个很痛疼的问题。那就是现在搜索引擎搜索到的东西都是COPY的。大家到处复制别人的答案,却连测试都不测试就贴上了,然后一搜索出来的都是千篇 一律的东西。要找到正确的解决方案真的是一件很痛苦的事。我不知道你们有没有这样的经理。反正我经常是这样。所以也萌生了自己写帖子的想法。把自己遇到的 问题的解决方案写出来。但是因为水平有限,所以可能也会存在很多问题。希望大家多多谅解。多多提出;

好了 进入今天的主题。所谓通用报表,我们来模拟一个需求:现在需要做个报表。这个报表要实现的功能是。配置一个配置文件,配置好要显示的数据表,和数据字段, 配置好每个字段在报表中的显示宽度,配置好报表数据要按那个字段的什么排序方式排序;这样,我就只需要一个报表就能显示不同的表的数据,并且可以根据字段 数据的长度设置报表中列的宽度;其实这里的通用也是有点牵强的。为什么牵强看下面的解决方案就知道了。

解决方案:通用报表是一个很强大的组件。所以其实很多东西都是我们还为挖掘的。那么通用报表怎么实现呢。我的想法是。先在报表上放一堆公式字 段,或者文本对象。然后通过代码,设置每个公式字段(报表的列)的宽度和左边偏移量;而要按照配置文件的需求则可以获取配置文件的条件,然后组合成为 SQL语句。获取数据填充到一个dataset中。在将这个dataset作为报表的数据源;就可以实现了;

第一步:

假设我的报表最多有10列;那么我需要创建一个DataSet.xsd文件。然后创建一张表;

  问题:为什么一定要创建这个文件,代码中创建一个DataSet可不可以?

  水晶报表在初始化的时候,需要关联已个数据源,这个数据源哪怕没有数据也没关系,关联数据源有两种方式。一是直接和数据库的表关联,二就是像我们这样创建一个DataSet.xsd文件,然后与这个DataSet.xsd文件关联;

  如果没有用任何一种关联的话,会提示:

  该报表不包含表。

  说明: 执行当前 Web 请求期间,出现未处理的异常。请检查堆栈跟踪信息,以了解有关该错误以及代码中导致错误的出处的详细信息。   

  异常详细信息: CrystalDecisions.CrystalReports.Engine.DataSourceException: 该报表不包含表。

  所以如果不创建创建DataSet文件,而是代码中创建一个DataSet,那么就没有关联数据源,会报如上错误;

  接着讲:新增项创建一个DataSet.xsd后,右键新增一张表:然后在表上右键新增列,完事后如下

  

  然后与报表关联:

第二步:创建水晶报表;然后右键公式字段,新增公式字段。然后把公式字段放到报表上,最后结果如下。

然后右键每个公式字段,选择设置对象个数,修改里面的对象名称,这里的对象名称是代码要使用的。建议设置成如:colu1,colu2….colu10  这样在代码中可以用循环来找到每个公式字段!

这里的公式字段我是为每个设置类单线边框,样式可能不是很好看。你也可以自己画线。这个下面的字报表会讲到;

 

第三步:创建页面,然后在页面上拉个水晶报表的控件

创建完后 有人可能不想要左边的这个组树。水晶报表的版本不一样。可能设置也不一样。我这个是10的。设置方式是将下面的属性改为none;

水晶报表的工具栏很多也是可以去掉的,然后在右上角会有个微标,点击会跳到该组件的官网,可以通过设置属性:

  接着是创建配置文件

  

复制代码
<?xml version="1.0" encoding="utf-8" ?>
<ConfigManage>
<Config ID="1">
  <TableName Title="系统日志报表">SYS_Log</TableName>
  <OrderBy Order="desc">logid</OrderBy>
  <Fields>
    <Field ChinesName="编号" IsShow="true" Width="1800">logid</Field>
    <Field ChinesName="日志类别" IsShow="true" Width="1800">logtype</Field>
    <Field ChinesName="用户编号" IsShow="true" Width="1800">userid</Field>
    <Field ChinesName="日志内容" IsShow="true" Width="1800">logcontent</Field>
    <Field ChinesName="操作用户名" IsShow="true" Width="1800">username</Field>
    <Field ChinesName="操作用户名" IsShow="true" Width="1800">username</Field>
  </Fields>
</Config>
</ConfigManage>
复制代码

 

 

 

然后就是为报表设置数据源和控制列宽的代码了。

复制代码
/// <summary>
        /// 获取配置文件的配置信息配置报表
        /// </summary>
        public void GetData()
        {

            string Path = "";
            string reportPath = "";
            string tablename = "";//表名称
            string OrderKey = "";//排序的字段
            string Order = "";//按什么排序
            string title = "";//报表标题
            bool Separate = true;//显示页是分页还是连接
            string serch = "";//筛选条件
            Path = Server.MapPath("Config/ReportConfig.xml");
            reportPath = Server.MapPath("CrystalReport3.rpt");

            #region 获取配置文件的信息
            XmlDocument document = new XmlDocument();
            document.Load(Path);
            XmlNodeList NodeList = document.GetElementsByTagName("TableName");
            if (NodeList != null && NodeList.Count > 0)
            {
                tablename = NodeList[0].InnerText;
                title = NodeList[0].Attributes["Title"].Value;
            }
            else
            {
                return;
            }
            NodeList = document.GetElementsByTagName("OrderBy");
            if (NodeList != null && NodeList.Count > 0)
            {
                OrderKey = NodeList[0].InnerText;
                Order = NodeList[0].Attributes["Order"].Value;
            }
            else
            {
                return;
            }
            NodeList = document.GetElementsByTagName("Field");
            string fields = "";
            if (NodeList != null && NodeList.Count > 0)
            {
                foreach (XmlNode node in NodeList)
                {
                    if (node.InnerText != "")
                    {                       
                        fields += node.InnerText + ",";
                    }
                }
            }
            else
            {
                return;
            }
            #endregion
            if (fields.Length > 0)
            {
                fields = fields.Substring(0, fields.Length - 1);
                string sql = "select " + fields + " from " + tablename + " " + serch + " order by " + OrderKey + " " + Order;
                DataSet ds = new Maticsoft.BLL.CommonClass().Query(sql);

                if (ds != null && ds.Tables.Count > 0 && ds.Tables[0].Rows.Count > 0)
                {
                    ReportDocument myReport = new ReportDocument();
                    myReport.Load(reportPath);
                    DataTable dtx1 = new clsDyCrystalReportCore().dtx(ds.Tables[0]);
                    int left = 100;
                    #region 设置每列显示的数据和宽度
                    for (int i = 0; i < NodeList.Count; i++)
                    {
                        //设置公式字段对应的数据库字段
                        myReport.DataDefinition.FormulaFields["colu" + (i + 1).ToString()].Text = "{CryReport.colu" + (i + 1) + "}";
                        //设置公式字段的文本
                        myReport.DataDefinition.FormulaFields["mt" + (i + 1).ToString()].Text = "\"" + NodeList[i].Attributes["ChinesName"].Value + "\"";
                        //设置宽度和左边偏移量
                        FieldObject fo;
                        fo = (FieldObject)myReport.ReportDefinition.ReportObjects["colu" + (i + 1)];
                        //fo.Height = 567 * 3;                 
                        int width = int.Parse(NodeList[i].Attributes["Width"].Value);
                        fo.Width = width;
                        fo.Left = left;
                        fo.Top = 30;
                        fo = (FieldObject)myReport.ReportDefinition.ReportObjects["mt" + (i + 1)];
                        //fo.Height = 567 * 3;
                        fo.Width = width;
                        fo.Left = left;
                        fo.Top = 760;
                        left += width+100;

                    }
                    #endregion
                    HideColu(NodeList.Count, myReport);
                    myReport.DataDefinition.FormulaFields["title"].Text = "\"" + title + "\"";
                    //myReport.Database.Tables[0].ApplyLogOnInfo(GetConnectionInfo());//设置报表数据库连接信息
                    myReport.SetDataSource(dtx1);
                    CrystalReportViewer1.SeparatePages = Separate;
                    CrystalReportViewer1.ReportSource = myReport;
                    CrystalReportViewer1.DataBind();
                    CrystalReportViewer1.RefreshReport();
                }
            }

        }                
复制代码

GetData()方法的前报部分基本都是获取配置文件中的信息,然后组合成一个SQL语句,然后通过ado.net执行获取数据

隐藏不显示的列的方法

复制代码
    /// <summary>
        /// 将不显示的列隐藏
        /// </summary>
        /// <param name="StarCulu"></param>
        /// <param name="myReport"></param>
        private void HideColu(int StarCulu, ReportDocument myReport)
        {
            for (int i = StarCulu; i < 10; i++)
            {
                //myReport.DataDefinition.FormulaFields["mt" + (i + 1).ToString()].Text = "";
                FieldObject fo;
                fo = (FieldObject)myReport.ReportDefinition.ReportObjects["colu" + (i + 1)];
                fo.ObjectFormat.EnableSuppress = true;
                fo = (FieldObject)myReport.ReportDefinition.ReportObjects["mt" + (i + 1)];
                fo.ObjectFormat.EnableSuppress = true;

                ///TODO 此处少了个抑制显示的代码
            }
        }
复制代码

 

然后调用下面的类的方法,将获取的数据放入前面创建的DataSet.xsd文件的表中;

复制代码
 class clsDyCrystalReportCore
    {
        /// <summary>
        /// 将传入的datatable转换成报表模板所需要的datatable
        /// 数据全部转换为string
        /// </summary>
        /// <param name="dt">来源表</param>
        /// <returns>报表模板所需要的datatable</returns>

        public DataTable dtx(DataTable dt)
        {
            DataSet1.CryReportDataTable dtx1 = new DataSet1.CryReportDataTable();

            object[] obj = new object[dt.Columns.Count];
            //特别注意:所选择的表的列的数目需<=Bigtable的字段数目
            //请自行填写保护代码
            for (int i = 0; i < dt.Rows.Count; i++)
            {
                dtx1.Rows.Add(dtx1.NewRow());

                for (int j = 0; j < dt.Columns.Count; j++)
                {
                    dtx1.Rows[i][j] = dt.Rows[i][j].ToString();
                }
            }
            return dtx1;
        }

    }
复制代码

这里有个需要注意的是,如果你在报表关联的是DataSet.xsd文件,但是在个报表设置数据源的是你通过sql语句获取的dataset或这datatable,那么就会出现如下界面

我想你看到这个一定蒙了。你可能会去页面的报表控件去设置不需要提示连接数据库,但是当你设置成不需要后,在刷新就会出现这个错:

这是因为你关联的是解决方案中的数据集文件,却用获取的数据表当作数据源,这里应该用你关联的数据集文件作为数据源,这样的话,每次提示或不提 示数据库连接设置成true或false都无所谓了。但是如果是关联的是数据库中的表,设置数据源的时候也是用sql取得的数据表。那么要去掉每次提示连 接数据库,除了这只这个属性还得这是报表的数据库连接信息

设置方式

myReport.Database.Tables[0].ApplyLogOnInfo(GetConnectionInfo());//设置报表数据库连接信息

复制代码
  /// <summary>
        /// 返回设置报表对象的数据库信息的对象
        /// </summary>
        /// <returns></returns>
        private TableLogOnInfo GetConnectionInfo()
        {
            TableLogOnInfo info = new TableLogOnInfo();
            info.ConnectionInfo.ServerName = "192.168.2.1";
            info.ConnectionInfo.DatabaseName = "dad";
            info.ConnectionInfo.UserID = "sa";
            info.ConnectionInfo.Password = "123456";
            return info;
        }
复制代码

这样就可以不需要每次都刷新页面填写数据库连接信息了。

 

该报表中,关键在于设置列宽和为列绑定要显示的数据:

在代码中如下:

复制代码
//设置公式字段对应的数据库字段
                        myReport.DataDefinition.FormulaFields["colu" + (i + 1).ToString()].Text = "{CryReport.colu" + (i + 1) + "}";
                        //设置公式字段的文本
                        myReport.DataDefinition.FormulaFields["mt" + (i + 1).ToString()].Text = "\"" + NodeList[i].Attributes["ChinesName"].Value + "\"";
                        //设置宽度和左边偏移量
                        FieldObject fo;
                        fo = (FieldObject)myReport.ReportDefinition.ReportObjects["colu" + (i + 1)];
                        //fo.Height = 567 * 3;                 
                        int width = int.Parse(NodeList[i].Attributes["Width"].Value);
                        fo.Width = width;
                        fo.Left = left;
                        fo.Top = 30;
                        fo = (FieldObject)myReport.ReportDefinition.ReportObjects["mt" + (i + 1)];
                        //fo.Height = 567 * 3;
                        fo.Width = width;
                        fo.Left = left;
                        fo.Top = 760;
                        left += width+100;
复制代码
"{CryReport.colu" + (i + 1) + "}":这句是为公式字段关联要显示的数据,格式为表名加字段,这里的表名是DataSet.xsd中的表的名称和列的名称。而不是sql语句获取的表的名称和字段名称
int width = int.Parse(NodeList[i].Attributes["Width"].Value):这句是获取配置文件中的列宽,然后设置给相应的列,列的偏移量都是从报表的最左端算起的。所以每个公式字段的偏移量要是他前面的公式字段的宽度的和;

在这里,有一个需要注意的是:数据表返回的数据必须的是字符串类型的。否则当公式字段类型(如数字)和数据表中字段的类型不一样(如字符串)那么在设置列宽和偏移量的时候会报错。所以DataSet.xsd中的表的字段和报表上的公式字段都设置为字符串类型,就不会出现这种错误了;
  最后:将不现实的列隐藏掉:
          FieldObject fo;
                fo = (FieldObject)myReport.ReportDefinition.ReportObjects["colu" + (i + 1)];
                fo.ObjectFormat.EnableSuppress = true;
通过设置EnableSuppress 属性,可以将公式字段设置为抑制显示,就可以隐藏掉了
 因为代码都是写完的,然后要去模拟错误,找错误信息,所以导致写的有点乱,有什么不懂的可以问我。我之所以没把源码贴出来,是我觉得 coding其实是一件很开心的事,特别是当自己通过搜索资料和努力实现了一个功能,那种心情只有自己明白,所以我希望大家可以照着帖子做一下。实在不行可以问我我的qq:282338159
后面会陆续贴一些帖子,会是各种知识点的。本人也处于一种学习状态,所以很多东西也还在摸索。希望公共探讨共同学习!!!!

[转载]dede二次开发文章类所关联的数据表 | www.ycyintao.com 官方博客

mikel阅读(721)

[转载]dede二次开发文章类所关联的数据表 | www.ycyintao.com 官方博客.

我们在使用dedecms系统时,每添加一篇文章,系统要往三个表中插入数据,这三个表的结构如下索引表:arctiny(后台PHP插入数据时这是第一个表)CREATE TABLE `arctiny` ( `id` mediumint(8) unsig…
我们在使用dedecms系统时,每添加一篇文章,系统要往三个表中插入数据,这三个表的结构如下

索引表:arctiny(后台PHP插入数据时这是第一个表)

CREATE TABLE `arctiny` (
`id` mediumint(8) unsigned NOT NULL auto_increment,
`typeid` smallint(5) unsigned NOT NULL default ’0′,
`typeid2` varchar(90) NOT NULL default ’0′,
`arcrank` smallint(6) NOT NULL default ’0′,
`channel` smallint(5) NOT NULL default ’1′,
`senddate` int(10) unsigned NOT NULL default ’0′,
`sortrank` int(10) unsigned NOT NULL default ’0′,
`mid` mediumint(8) unsigned NOT NULL,
PRIMARY KEY (`id`),
KEY `sortrank` (`sortrank`)
) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=gb2312;

主表:archives(这个表存放了类别编号,关键词,标题,短标题,简介等信息)

CREATE TABLE `archives` (
`id` mediumint(8) unsigned NOT NULL default ’0′,
`typeid` smallint(5) unsigned NOT NULL default ’0′,
`typeid2` varchar(90) NOT NULL default ’0′,
`sortrank` int(10) unsigned NOT NULL default ’0′,
`flag` set(‘c’,’h’,’p’,’f’,’s’,’j’,’a’,’b’) default NULL,
`ismake` smallint(6) NOT NULL default ’0′,
`channel` smallint(6) NOT NULL default ’1′,
`arcrank` smallint(6) NOT NULL default ’0′,
`click` mediumint(8) unsigned NOT NULL default ’0′,
`money` smallint(6) NOT NULL default ’0′,
`title` char(120) NOT NULL default ”,
`shorttitle` char(120) NOT NULL default ”,
`color` char(7) NOT NULL default ”,
`writer` char(20) NOT NULL default ”,
`source` char(30) NOT NULL default ”,
`litpic` char(100) NOT NULL default ”,
`pubdate` int(10) unsigned NOT NULL default ’0′,
`senddate` int(10) unsigned NOT NULL default ’0′,
`mid` mediumint(8) unsigned NOT NULL default ’0′,
`keywords` char(100) NOT NULL default ”,
`lastpost` int(10) unsigned NOT NULL default ’0′,
`scores` mediumint(8) NOT NULL default ’0′,
`goodpost` mediumint(8) unsigned NOT NULL default ’0′,
`badpost` mediumint(8) unsigned NOT NULL default ’0′,
`voteid` mediumint(8) NOT NULL,
`notpost` tinyint(1) unsigned NOT NULL default ’0′,
`description` varchar(255) NOT NULL default ”,
`filename` varchar(40) NOT NULL default ”,
`dutyadmin` mediumint(8) unsigned NOT NULL default ’0′,
`tackid` int(10) NOT NULL default ’0′,
`mtype` mediumint(8) unsigned NOT NULL default ’0′,
`weight` int(10) NOT NULL default ’0′,
PRIMARY KEY (`id`),
KEY `sortrank` (`sortrank`),
KEY `mainindex` (`arcrank`,`typeid`,`channel`,`flag`,`mid`),
KEY `lastpost` (`lastpost`,`scores`,`goodpost`,`badpost`,`notpost`)
) TYPE=MyISAM;

附加表:addonarticle(这个表只用于对文章详细内容显示的数据)
CREATE TABLE `addonarticle` (
`aid` mediumint(8) unsigned NOT NULL default ’0′,
`typeid` smallint(5) unsigned NOT NULL default ’0′,
`body` mediumtext,
`redirecturl` varchar(255) NOT NULL default ”,
`templet` varchar(30) NOT NULL default ”,
`userip` char(15) NOT NULL default ”,
PRIMARY KEY (`aid`),
KEY `typeid` (`typeid`)
) TYPE=MyISAM DEFAULT CHARSET=gbk;

[转载]护眼纯黑色VS2012配色方案 - _Arvin - 博客园

mikel阅读(1266)

[转载]护眼纯黑色VS2012配色方案 – _Arvin – 博客园.

   这些天由于公司项目比较忙,所以天天盯着电脑8小时,而且我的开发工具VS2012是白色背景的所以每天下班都搞的眼睛巨疼。

今天在网上找到一个很好的配色方案,所以有同样烦恼的童鞋们可以试试哦! 展示下效果由于图片太大,我就缩小的屏幕:

而且还可以有多种颜色让你选择哦!

如果你觉得不错可以试试,步骤如下:

1.下载配色方案:http://studiostyl.es/  点击第一个下载下来。

2.下在VS2012插件:

点击工具-〉扩展与更新,在联机中搜索theme Editor,把第一个插件下载下来。
重启vs后,工具一栏中会出现Change Color Theme这个选项,然后调成黑色就是我的样式了。

3.导入配色方案:

工具–>导入和导出设置–>导入指定的环境设置–>否,覆盖当前–>浏览 (找到你下载的配色方案) –>选择开发设置–>下一步 (完成)。

我测试了下 VS2010只能导入配色方案,那个插件用不了,不知道是不是个人原因。如果你觉得这个太小儿科的就笑笑就好,如果有更好的方案就拿出来分享吧。

我觉得纯黑色的最好,最不伤眼睛,如果觉得不错就顶一下吧,让更多IT人眼睛不那么受苦。

[转载]网络采集器 - 镇水古月 - 博客园

mikel阅读(831)

[转载]网络采集器 – 镇水古月 – 博客园.

我们在浏览网页的时候,都会在浏览器地址栏中输入需要访问的地址,通常这些地址都是以HTTP打头,表明是采用HTTP协议实现和站点通 讯,HTTP准确的说法是超文本传输协议,归根结底还是文本,所以传输的内容就是文本,浏览的网页也是文本,这就是我们可以采集网站数据的根本。

同时,在地址栏中我们还会看到网址中会包含www的字样,这表示我们请求的是Web服务,WWW服务(3W服务)是目前应用最广的一种基本互联网应 用。WWW服务使用的是超文本链接(HTML),所以可以很方便的从一个信息页转换到另一个信息页。它不仅能查看文字,还可以欣赏图片、音乐、动画。

至此,我们知道,浏览网页实际是采用HTTP协议向Web服务请求一个超文本(HTML),这个超文本包含有文字、图片、音乐等内容,这就是我们最 终看到的网页。同时我们所采集的数据也包含在这个超文本中。超文本(HTML)有自己的规则,通过这些规则,浏览器会自动识别超文本格式,知道该用何种方 式展示页面,这也是我们看到不同网页风格的根本。如果我们通过浏览器,查看网页源码就会发现很多<>标识的内容,这就是HTML的规范内容, 当然还有很多其他规范。

手工方式进行数据采集流程:

1、用浏览器(浏览器可是IE、Firefox)打开一个网页

2、用浏览器查看网页源代码(Firefox)或查看源文件(IE)的功能打开这个网页的传输文本内容

3、可以把这个文本内容全部拷贝到一个专业的文本编辑工具中,譬如:UltraEdit,也或者直接采用浏览器自带的功能

4、通过查找的功能,开始查找您想要的内容

5、找到之后需要把它拷贝出来

参考资料

网络矿工数据采集软件用户手册
http://www.soukey.com/help/index.html

 

C#多线程网页采集器(Spider)

http://programmingcanruinyourlife.themz.cn/spider.html

 

ASP.NET采集函数(采集、分析、替换、入库一体)

http://blog.csdn.net/mubingyun/archive/2008/12/09/3484548.aspx

 

ASP.NET(C#)经典采集代码

http://blog.csdn.net/mubingyun/archive/2008/12/09/3484534.aspx

 

ASP.NET下数据采集方法及示例

http://blog.csdn.net/mubingyun/archive/2008/12/09/3484481.aspx

 

魏言ASP.NET数据采集封装类,封装了所有数据采集需要的方法

http://blog.csdn.net/mubingyun/archive/2008/12/09/3484469.aspx

 

log4net使用详解

http://blog.csdn.net/mubingyun/archive/2008/12/09/3484462.aspx

 

ASP.NET采集系统万能正则表达式

http://blog.csdn.net/mubingyun/archive/2008/12/09/3484557.aspx

 

.NETC#群发HTML格式带附件中文发送者密送抄送的邮件

http://blog.csdn.net/mubingyun/archive/2008/12/09/3484564.aspx

 

.net程序中资源文件的保护办法探讨

http://blog.csdn.net/mubingyun/archive/2008/12/09/3484567.aspx

 

C#利用代理(proxy)爬网

http://blog.csdn.net/mubingyun/archive/2008/10/31/3194288.aspx

 

SQL生成100W条指定位数的随机数的方法(只花费了不足1分钟)(整理)

http://blog.csdn.net/mubingyun/archive/2008/10/21/3115456.aspx

[转载]网站采集 - jyshi - 博客园

mikel阅读(799)

[转载]网站采集 – jyshi – 博客园.

一、采集器的制作的基本知识点。

1、懂一些简单的正则表达式的知识,知道些基本知识对大家在采集软件设置规则的时候是有帮助,正则表达式的一些基础知识是很容易掌握的,而绝大多数采集用的是最基本的正则表达式的内容。
如: 你起码要知道”.” “\n” “\s” ”\d” “*” “+” “?” “{3,5}” “[3-6]”。 了解这些简单正则式的基本含义,这里不作详细详解,大家可以从网上查到资料。我个人觉得正则还是比较容易学习,但是不经常使用的话,忘记的比较快。经常会 出现边在网上查正则,边书写采集规则的情况。

2、会使用一些程序命令将网页的内容正确抓取下来。

——-使用webclient来抓取网页内容
String PageUrl = @”http://www.79zw.com/files/article/info/65/65670.htm”;
WebClient wc = new WebClient();
///方法一:
Byte[] pageData = wc.DownloadData(PageUrl);
ContentHtml.Text = Encoding.Default.GetString(pageData);

/// 方法二:
/// ***************代码开始**********
Stream resStream = wc.OpenRead(PageUrl);
StreamReader sr = new StreamReader(resStream,System.Text.Encoding.Default);
ContentHtml.Text = sr.ReadToEnd();
resStream.Close();
/// **************代码结束********
///
wc.Dispose();

——-使用webrequest来抓取网页内容

PageUrl = @”http://www.79zw.com/files/article/info/65/65670.htm”;
WebRequest   request = WebRequest.Create(PageUrl);
WebResponse response = request.GetResponse();
Stream resStream = response.GetResponseStream();
StreamReader sr = new StreamReader(resStream, System.Text.Encoding.Default);
String content = sr.ReadToEnd();
resStream.Close();
sr.Close();

——使用xmlhttp来抓取网页内容
XMLHTTP xhttp = new XMLHTTP();
string url=@”http://www.79zw.com/files/article/info/65/65670.htm”;
xhttp.open(“post”, url, false, null, null);
xhttp.send(“”);
Byte[] bb = (Byte[])xhttp.responseBody;
xhttp.abort();

二、对小说站进行采集的思路。

就看一下如何采集世纪,世纪的站长不在这里吧?

只要知道一个书本的ID号就可以开始啦。。。。。

书籍简介页面:http://www.79zw.com/files/article/info/59/59295.htm

<font size=”4″ color=”red”>佛本是道<img
<td width=”25%”>类    别:仙侠奇侠</td>
<td width=”25%”>作    者:梦入神机</td>
<td width=”25%”>管 理 员:</td>
<td width=”25%”>全文长度:2008072字</td>
<td>最后更新:2007-03-04</td>
<td>文章状态:完成</td>
<td>授权级别:暂未授权</td>
<td>首发状态:他站首发</td>
<td>总点击数:13197071</td>
<td>本月点击:693848</td>
<td>本周点击:270326</td>
<td>本日点击:20941</td>

书籍目录页面:http://www.79zw.com/files/article/html/59/59295/index.html

<td colspan=”3″ class=”vcss”>
正文 </td>
</tr>
<tr>
<td class=”ccss”>
<a href=”1639383.html”>前 言</a>
</td>
<td class=”ccss”>
<a href=”1639384.html”>第一章 原 由 第一节 奥林匹亚风云</a>
</td>
<td class=”ccss”>
<a href=”1639385.html”>第二节神符巨人</a>
</td>
</tr>

书籍章节内容页面:http://read.2100book.com/files/article/html/45/45647/2144288.html

通过前面的采集代码,一层一层的从网页上抓取数据,然后根据你设置的正则表达式标签,把所需要的内容取出来,判断是文字内容,还是图片内容,然后分别写入后端数据库。

如果是批量采集就按照设置的ID号不断循环,直到全部采集完。如果你设置从1-50000号开始采集,就基本可以目标书站的书全部采集完。

就算目标站中有空号,比如说:4678这个号没有书,这样大抓取这个号的时候会出现错误,通过正则采集判断是空号就放弃采集这个ID号就成啦。

手上的蓝心采集已经实现了三种批采模式

三、防采集的基本思路。

目前而言,防采集还没有一个还没有一个完全彻底的解决方案
一,增加采集的规则难度,经常变换规则,这种方法对于防止采集是比较容易使用的方法,而且效果比较好,容易。
大家请看两个地址:
1、 http://read.2100book.com/files/article/html/45/45647/index.html
2、 http://www.79zw.com/files/article/html/39/39621/index.html

抽出我们所需要的资料
世纪:<a href=”1639384.html”>第一章 原 由 第一节 奥林匹亚风云</a>
<a href=”1639385.html”>第二节神符巨人</a>
<a href=”1639386.html”>第三节异次元空间门</a>
<a href=”1639387.html”>第四节 龙之墓地</a>
世纪的章节规则:<a href=”\d+.html”>[^<|>]*</a>

79:<a   href=696794.html title=”第一章原由第一节奥林匹亚风云”>第一章原由第一节奥林匹亚风云</a>
<a title=” href=8384.html 生成时间:2007-3-9 12:33:57″ href=696795.html>第二节神符巨人</a>
<a   href=”696796.html”>第三节异次元空间门</a>
79的章节规则就不好写啦,有3个,难度比世纪就大多啦。
如果把内容页和图片页的规则也设置很多个的话,这样采集的难度就更大了,非牛人不能采集。

二、可以设置IIS和apache对图片的采集进行限制。
IIS通过重写一些附加模块可以实现,但是直接在IIS里通过设置来实现方法比较困难,需要附加模块来做这个事。
Apache可以实现图片简单防采和防盗链,设置比较简单,而且很实用。
SetEnvIfNoCase Referer “^http://www.88zw.com” local_ref=1
SetEnvIfNoCase Referer “^http://88zw.com” local_ref=1
SetEnvIfNoCase Referer “^$” local_ref=1
SetEnvIf Request_URI /images/logo(.)+ local_ref=1

<FilesMatch “\.(gif|jpg|bmp|jpeg|png)”>
Order Allow,Deny
Allow from env=local_ref
Allow from 127.0.0.1
</FilesMatch>

[转载]简单易用粗暴的文章内容采集程序 -【开源项目】 - 火地晋 - 博客园

mikel阅读(1125)

[转载]简单易用粗暴的文章内容采集程序 -【开源项目】 – 火地晋 – 博客园.

更新:通过一些朋友的回复,了解到,可能文章太长了,有朋友只是简略浏览,所以还没有明白程序工作流程。

简单介绍,这个程序是给程序员用的,使用这个软件,必须是会写正则的朋友,或者是有朋友帮忙写正则。

这个程序不是针对某个网站或者网页而写的,而是一个“采集框架 ”——说是框架,有点大了。

但是核心的一点就是,只要会写正则,几分钟就可以针对一个采集目标,编写一个采集规则。

只需要4(3)个正则,就可以完成任务。

列表网址、页面标题、页面内容、页面链接

 

如果是逐页采集模式,列表网址的正则可以忽略。

————————————————

前言

爱学习、爱使用移动设备阅读电子书的朋友,不能不拥有一款属于自己的采集利器。

而使用此程序即可以简单轻松的实现采集任务。

采集效果图

程序介绍

在程序运行子目录 Config是程序的配置的保存目录。

path.txt

[config]

Config\HtmlFormatConfig.xml

[task]

Config\task\

config 设置采集内容格式化的配置保存路径

task设置任务工作规则保存和加载路径

 

采集工作窗体

起始网址

采集开始的网址,如果是逐页的模式,则是第一页的地址;

如果是列表的模式,则是第一个列表页面的地址。

列表网址

匹配下一个列表页面地址的正则表达式。

在逐页模式下,不用填写。

 

页面标题

匹配页面标题的正则表达式

页面内容

匹配页面内容的正则表达式

页面链接

匹配内容页面链接的正则表达式

在逐页模式,采集到一个内容页面之后,可以匹配到下一个页面链接。

在列表模式,采集到一个列表页面之后,就可以匹配到若干个页面链接。

分页标识

识别是否为分页标题的匹配正则表达式

首页标识

第一页的标识,比如标题【科技业的员工到底有多年轻 1)】,那么标识可以是(1)

保存路径

采集内容的保存目录

分页处理

是指采集的文章资料是进行了分页的,那么程序会根据设定的规则,判断是否是分页章节,如果是,则不重复添加标题。

比如

科技业的员工到底有多年轻 1

科技业的员工到底有多年轻 2

科技业的员工到底有多年轻 3

那么采集过程中,只会写入一个标题【科技业的员工到底有多年轻】

保存为一个文件

如果勾选,则采集到的所有内容都写入到一个文件中

开始

开始采集并将内容保存

测试

在消息框显示采集的效果

格式化设置窗体

左边是匹配到的字符,后边是表示要替换成的字符。

程序运行时,会将第二行(如果有两行)的字符拷贝一份转换为大写组合在一起,进行格式化。

换行标签、空白标签、缩进标签

可以输入包含正则在内的字符进行匹配

章节标题

{0}表示采集的序号(采集一个地址则加1),{1}表示采集到的标题。

辅助功能

可以将输入的字符进行大小写转换

 

编写新规则

编写采集规则需要有一定的正则表达式的知识,如果不了解阅读这个页面:(正则表达式30分钟入门教程)http://deerchao.net/tutorials/regex/regex.htm

 

任务是以xml文件的形式保存,文件名命名格式是:任务名称网站名称.xml

在任何一个任务状态下,只需要修改任务名称,或者网站名称,再点击保存任务,即可新建一个任务。

如果名称一样会提示是否覆盖。

 

这里以博客园新闻为例

博客园新闻是一个列表式的采集任务——在一个页面可以匹配得到若干个页面地址

http://news.cnblogs.com/

使用firebug或者其它前端调试工具,可以轻松得到采集特征

比如下图

 

 

点击红框【点击查看页面中的元素】然后在页面的【创业公司如何评估度量公司潜力的方法】位置点下。

就可以定位到html代码

这样就可以获取到内容页面的链接特征

<h2 class=”news_entry”>
<target=”_blank” href=”/n/182026/”>创业公司如何估值 — 度量公司潜力的方法</a>
</h2>

然后需要观察这个标识是不是唯一特征的,也就是这个特征匹配到的都是自己期望中的内容。否则就需要增加更多的限制特征。

 

将特征编写为匹配的正则表达式

 

源码说明

解决方案有3个项目组成

Forms是视窗程序

Framework是采集程序

Helper是辅助程序

 

由于考虑到以后会增加不同的采集任务,因此采用MDI窗体。

Config目录是默认配置

FrmFormatConfig是内容格式化配置窗体

FrmGatherWorker是采集工作窗体

MDIParentMain是窗体容器

Config是内容格式化配置实体类

Task是采集任务规则实体类

Worker是采集工作类

 

 

Worker采集工作类说明

先看看3个主要事件

复制代码
/// <summary>
/// 错误触发事件,传入参数 引发的异常对象、错误的类型、当前工作的网址
/// </summary>
public event Action<Exception, ErrorType, string> OnError;

/// <summary>
/// 工作结束触发事件
/// </summary>
public event Action OnWorkEnd;

/// <summary>
/// 一次/地址采集完成触发事件,传入参数 采集内容的标题、内容、网址
/// </summary>
public event Action<stringstringstring> OnWorkItemEnd;

复制代码

 

创建对象

Worker work = new Worker(_httpRequest, _config, _task);
work.OnError += w_OnError;
work.OnWorkItemEnd += work_OnWorkItemEnd;
work.OnWorkEnd += work_OnWorkEnd;

定义内容处理

复制代码
/// <summary>
/// 一次(个网址)采集完成后,执行内容写入文件操作
/// </summary>
private void work_OnWorkItemEnd(string curWebTitle, string curWebContent, string curUrl)
{
//将采集到的内容写入到文件流中
    byte[] byteWebContent = Encoding.UTF8.GetBytes(curWebContent);
if (_task.IsSaveOnlyFile)
{
//如果当前内容标题为空,则可能分页
        if (!string.IsNullOrEmpty(curWebTitle))
{
byte[] byteWebTitle = Encoding.UTF8.GetBytes(curWebTitle);
_curSavaFile.Write(byteWebTitle, 0, byteWebTitle.Length);
}
_curSavaFile.Write(byteWebContent, 0, byteWebContent.Length);
}
else
{
using (FileStream curSavaFile2 = new FileStream({0}{1}.txt.FormatWith(_task.SavePath, curWebTitle), FileMode.OpenOrCreate, FileAccess.ReadWrite))
{
curSavaFile2.Write(byteWebContent, 0, byteWebContent.Length);
}
}
UpdateWorkMessage(\n已采集:{0},网址:{1}.FormatWith(curWebTitle, curUrl));
Application.DoEvents();
}
复制代码

 

其它更多,请下载源码查看

其它

运行程序下载:http://files.cnblogs.com/yelaiju/NWebGather.rar

源码下载:http://files.cnblogs.com/yelaiju/NWebGather-src.rar

 

开源地址:https://github.com/alifellod/NWebGather

不了解github下载源码的方式,请看文章:http://www.cnblogs.com/yelaiju/p/3180986.html

 

正则词典(手册)http://www.cnblogs.com/yelaiju/p/3182854.html

 

相关推荐项目:

 

 

园友:心态要好推荐 http://blog.csdn.net/sq_zhuyi/article/details/7924776
 

各位朋友对采集有兴趣,可以一起维护和贡献代码,如此大家都可以轻松的共享同一个采集框架。

 

QQ群:9524888

欢迎大家入群交流共享采集任务规则,讨论技术,讨论人生……

作者: 火地晋
出处: http://yelaiju.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。