Tuesday, July 16, 2013

Chuyển đổi chuỗi html chứa các thẻ table thành DataTable hoặc DataSet

Trong bài viết này tôi giới thiệu các bạn một Class khá hay có tác dụng chuyển đổi chuỗi html chứa các thẻ table thành DataTable hoặc DataSet - Convert Html Table Tag to Datatable or DataSet. DataTable, DataSet, Html, Table, Html Table, Convert,
Đây là một class tôi nghĩ khá hay mà bạn có thể dùng vào nhiều mục dích khác nhau, Ví dụ đơn giản nhất đó là bạn muốn bóc tách nội dung của 1 trang web mà source nguồn có chứa các thẻ html thành DataTable hoặc DataSet. Ví dụ như trang http://vov.vn/Media/List.aspx?catid=49 Khi view source lên bạn sẽ thấy từ dòng 351 đến dòng 616 là nội dung thẻ Table chứa danh sách các media đọc chuyện Nhật ký Đặng Thùy Trâm. Bạn muốn bóc tách và đưa các media đó về website của bạn? việc sử dụng Class chuyển đổi chuỗi html chứa các thẻ table thành DataTable hoặc DataSet sẽ nhanh và hiệu quả.
Dưới đây là toàn bộ nội dung của Class này. Tôi đã ghi tất cả các chú thích cho các hàm tương ứng. Tôi không tách từng hàm ra nữa.
using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Net;
using System.IO;
using System.Xml;
using System.Data.SqlClient;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
/// 
/// Summary description for HtmlTableParser
/// 
public class HtmlTableParser
{
    private const RegexOptions ExpressionOptions = RegexOptions.Singleline | RegexOptions.Multiline | RegexOptions.IgnoreCase;

    private const string CommentPattern = "";
    private const string TablePattern = "]*>(.*?)
"; private const string HeaderPattern = "]*>(.*?)"; private const string RowPattern = " ]*>(.*?) "; private const string CellPattern = "]*>(.*?)"; /// /// Một chuỗi html có nhiều bảng, phân tích và đưa các bảng này thành DataSet /// /// Một chuỗi HTML bao gồm nhiều bảng /// Một DataSet có chứa một DataTable cho mỗi bảng HTML trong chuỗi đầu vào public DataSet ParseDataSet(string html) { DataSet dataSet = new DataSet(); MatchCollection tableMatches = Regex.Matches( WithoutComments(html), TablePattern, ExpressionOptions); foreach (Match tableMatch in tableMatches) { dataSet.Tables.Add(ParseTable(tableMatch.Value)); } return dataSet; } /// /// Chuỗi HTML có chứa một bảng duy nhất, phân tích bảng thành một DataTable. /// /// Chuỗi HTML có chứa một bảng duy nhất /// Một DataTable public DataTable ParseTable(string tableHtml) { string tableHtmlWithoutComments = WithoutComments(tableHtml); DataTable dataTable = new DataTable(); MatchCollection rowMatches = Regex.Matches( tableHtmlWithoutComments, RowPattern, ExpressionOptions); dataTable.Columns.AddRange(tableHtmlWithoutComments.Contains(" /// Loại bỏ các comment của chuỗi html ///
/// Chuỗi html có chú thích /// Trả về chuỗi html đã được loại hết chú thích private string WithoutComments(string html) { return Regex.Replace(html, CommentPattern, string.Empty, ExpressionOptions); } /// /// Thêm 1 dòng vào DataTable sử dụng MatchCollection /// /// Tập hợp các dòng thêm vào DataTable /// Một DataTable đã được thêm các dòng private void ParseRows(MatchCollection rowMatches, DataTable dataTable) { foreach (Match rowMatch in rowMatches) { // Chỉ sử dụng các hàng không phải tiêu đề bảng if (!rowMatch.Value.Contains(" /// Chuỗi có chứa một bảng HTML, phân tích các tiêu đề tạo ra các DataColumns của một DataTable. /// /// Một chuỗi HTML có chứa một bảng HTML /// Các DataColumns của một DataTable private DataColumn[] ParseColumns(string tableHtml) { MatchCollection headerMatches = Regex.Matches( tableHtml, HeaderPattern, ExpressionOptions); return (from Match headerMatch in headerMatches select new DataColumn(headerMatch.Groups[1].ToString())).ToArray(); } /// /// Phân tích dữ liệu không phải tiêu đề đưa vào các Columns /// /// Các hàng trong bảng HTML chúng ta tạo ra các cột /// Tập hợp các DataColumns dựa trên số lượng celss trong hàng đầu tiên của bảng đầu vào HTML private DataColumn[] GenerateColumns(MatchCollection rowMatches) { int columnCount = Regex.Matches( rowMatches[0].ToString(), CellPattern, ExpressionOptions).Count; return (from index in Enumerable.Range(0, columnCount) select new DataColumn("Column " + Convert.ToString(index))).ToArray(); } public HtmlTableParser() { // // TODO: Add constructor logic here // } }

Cắt n ký tự đầu tiên của một chuỗi với C#

 public static string CatChuoi(this string s, int length)
    {
        if (String.IsNullOrEmpty(s))
            throw new ArgumentNullException(s);
        var words = s.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
        if (words[0].Length > length)
            throw new ArgumentException("Từ đầu tiên dài hơn chuỗi cần cắt");
        var sb = new StringBuilder();
        foreach (var word in words)
        {
            if ((sb + word).Length > length)
                return string.Format("{0}...", sb.ToString().TrimEnd(' '));
            sb.Append(word + " ");
        }
        return string.Format("{0}...", sb.ToString().TrimEnd(' '));
    }

Giải pháp Session timeout trong ASP.NET

Session timeout Là khoảng thời gian lớn nhất có thể giữa hai lần user request lên server mà session của user chưa bị hủy. Vấn đề thường gặp là Session hay bị mất khi đang xử lý thông tin trước khi Submit form. Bài viết này xin giới thiệu một giải pháp cho vấn đề session timeout trong asp.net

1. Session timeout là gì?

Là khoảng thời gian lớn nhất có thể giữa hai lần user request lên server mà session của user chưa bị hủy. Nói một cách đơn giản hơn, giả sử giá trị timeout này là 30′, thì cứ trong 30′, nếu user không gửi một request nào lên server thì session của user đó sẽ không còn hiệu lực.
Trong ASP.NET, session timeout mặc định là 20′. Có nhiều cách để thay đổi giá trị này, đơn giản nhất là thêm một dòng trong web.config




2. Đặt timeout bao nhiêu là hợp lý?

Giá trị mặc định của nó là 20′, tuy nhiên trong một số trường hợp bạn muốn session tồn tại lâu hơn. Ví dụ một ứng dụng web cho phép người dùng soạn thảo nội dung trực tiếp trên trình duyệt. Bạn không muốn session kết thúc trước khi người dùng soạn thảo xong văn bản, vì thế bạn thiết lập timeout bằng một số rất lớn. Điều này không thực sự ổn vì nó sẽ tốn rất nhiều bộ nhớ của server dành cho session của những người dùng không còn trên website của bạn.

3. Heart beat pattern

Có một giải pháp cho vấn đề này: Thiết lập một giá trị session timeout nhỏ. Đồng thời, phía client sẽ “âm thầm” gửi các request nhỏ, thường xuyên đến server để báo cho server biết nó vẫn còn “sống”. Do đó bạn sẽ không bị tốn bộ nhớ một cách vô ích cho session của những người dùng không còn trên trang. Phương pháp này được biết dưới cái tên Heartbeat design pattern.
Tôi thực hiện điều này trong ASP.NET một cách đơn giản như sau:
+ Thiết lập một giá trị nhỏ cho session timeout (giả sử là 5′)
+ Tạo trang KeepAlive.ashx để nhận request thường xuyên từ client. Trang này không cần làm gì cũng được.
+ Thêm đoạn code javascript sau vào trang bạn muốn thực hiện. Tốt nhất là đặt chúng trong các trang master page

function heartBeat() {
    $.get("KeepAlive.ashx?", function (data) {});
}
$(function () {
    setInterval("heartBeat()", 1000 * 30); // 30s gửi request một lần
});