Ứng dụng Python

Scrapy - Công cụ bóc tách dữ liệu siêu mạnh

Đăng bởi - Ngày 1-06-2018

Bài viết hôm nay mình giới thiệu với các bạn về package scrapy, một công cụ tạo web spider cực mạnh. Rất nhiều dự án và ứng dụng mình sử dụng scrapy, ví dụ như lấy toàn bộ hình ảnh của một website, các bài viết theo danh mục và theo chủ đề, tạo bot lấy dữ liệu nguời dùng như số điện thoại và email trên facebook.. hoặc đơn giản hơn là lấy kết quả sổ xố kiến thiết ...

Nghe cũng hấp dẫn ấy chứ, chỉ vài dòng code bạn sẽ có ngay một thằng làm thuê siêng năng không biết than thở là gì :d. Để chuẩn bị cho scrapy chúng ta cần cài đặt những package sau

Cài đặt

pip install scrapy

Bắt đầu project

Trong bài viết này mình sẽ sử dụng scrapy để lấy dữ liệu kết quả sổ xố từ website http://xskt.com.vn, bạn nào muốn tạo trang web mở đại lý có thể sử dụng source này :d. Trên virtual environment command line. Bạn hãy chạy dòng sau

scrapy startproject xskt

Scrapy sẽ tạo một folder và các file như sau

folder - files sxkt

  • scrapy.cfg: file config project scrapy
  • settings.py: file chứa settings cho spiders
  • middlewares.py: file chứa spider middlewares, là những framework được hook vào scrapy processing.
  • items.py: file chứa cấu trúc của item mà bạn sẽ tách dữ liệu. Nói đơn giản thì nó là một cái khung, sau khi chúng ta lấy được dữ liệu từ spiders, chúng ta sẽ đặt dữ liệu vào đây và xử lý
  • pipelines.py: sau khi chúng ta đặt dữ liệu vào cho items.py, chúng ta sẽ xử lý ở function process_items trong pipeline. Bạn có thể save vào database, hoặc chỉ trả về item đó
  • folder spiders: là nơi chúng ta tạo file spider để chạy dữ liệu.

Phần giới thiệu các file cơ bản của scrapy đã xong. Bây giờ quay lại project của chúng ta, bạn cần nhớ rằng khi muốn lấy dữ liệu của một site nào đó, thì điều quan trọng là phân tích cấu trúc website. những dữ liệu nào trên site đó ta cần lấy, có những link nào trên site đó hỗ trợ ta lấy dữ liệu dễ dàng... Bây giờ tổng hợp lại những điều mình đã nêu ra, ta sẽ phân tích site http://xskt.com.vn

Kết quả xổ số được chia làm 3 miền, mình sẽ lấy miền nam làm ví dụ, các bạn làm tương tự cho các miền còn lại nha. Khi bạn vào site, kéo xuống chút sẽ thấy "Kết quả sổ xố toàn quốc". Tại đây chúng ta sẽ click vào miền nam

xs miền nam

browser sẽ đưa chúng ta xuống phần "KQXS Miền Nam". Ở mục này sẽ có 3 link dẫn đến mục kết quả sổ xố: "KQXS Miền Nam" sẽ đưa bạn đến trang chứa kết quả mới nhất toàn miền nam, "Ngày 01/6" đưa đến trang chứa kết quả theo ngày, "Thứ Năm" sẽ đưa đến kết quả sổ xố ngày thứ năm. Để dễ dàng lấy dữ liệu từ tất cả các ngày trong ngày, tháng năm ta sẽ chọn link từ "Ngày 01/6" và lấy tiếp link từ "Ngày 01-6-2018"

xổ số mn 3 link

Link sẽ có dạng là http://xskt.com.vn/ket-qua-xo-so-theo-ngay/mien-nam-xsmn/01-6-2018.html . Bạn hãy thay đổi ngày tháng của link này xem thử kết quả có như yêu cầu của project ta đang cần không.

Coding

Bây giờ quay lại phần coding nha, bạn hãy mở file items.py lên và chỉnh sửa như sau:

# -*- coding: utf-8 -*-

# Define here the models for your scraped items
#
# See documentation in:
# http://doc.scrapy.org/en/latest/topics/items.html

import scrapy


class XsktItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    xs_info = scrapy.Field()
    xs_data = scrapy.Field()

Ta tạo 2 item cho xskt là xs_info và xs_data. xs_info dùng lưu trữ thứ ngày tháng của bảng xổ số, xs_data dùng lưu trữ kết quả xổ số các tỉnh miền nam

Mở file settings.py lên và bạn hãy thêm FEED_FORMAT ở cuối file

FEED_FORMAT = 'json'

FEED_FORMAT cho phép bạn định dạng dữ liệu xuất ra theo dạng nào, mình sẽ xuất ra ở dạng json trong ví dụ này

Tiếp theo bạn hãy tạo file xosokienthiet.py trong folder xskt/xskt/spiders

import scrapy
import calendar
import datetime

from scrapy.spiders import CrawlSpider
from ..items import XsktItem #1

def get_total_date_month(year, month): #2
    now = datetime.datetime.now()
    total_date = calendar.monthrange(year, month)[1]

    if year == now.year and month == now.month and now.day < total_date:
        return now.day

    return total_date
  1. Ta import XsktItem vào spider để chuẩn bị đổ dữ liệu lấy được vào item
  2. Function get_total_date_month sẽ tính toán xem có bao nhiêu ngày trong tháng mà chúng ta đưa vào. Nếu cùng năm và cùng tháng thì ta chỉ lấy tới ngày hiện tại

Tiếp tục ta sẽ tạo class SoxokienthietSpider để lấy dữ liệu từ site xskt.com.vn

class SoxokienthietSpider(CrawlSpider):
    name = 'xosokienthiet'
    allowed_domains = ['xskt.com.vn'] #1

    start_urls = []

    month_to_scrap = 5
    year_to_scrap = 2018
    total_date = get_total_date_month(year_to_scrap, month_to_scrap)

    for i in range(1, total_date):
        start_urls.append('http://xskt.com.vn/ket-qua-xo-so-theo-ngay/mien-nam-xsmn/'
                          '{0}-{1}-{2}.html'.format(i, month_to_scrap, year_to_scrap)) #2

    def parse(self, response): #3
        xs_item = XsktItem()
        tmp_data = {}
        data_resp = scrapy.Selector(response)

        xs_item['xs_info'] = [
            # Thứ
            data_resp.xpath("//table[@id='MN0']/tr/th[1]/a/text()").extract_first(),
            # Ngày tháng
            data_resp.xpath("//table[@id='MN0']/tr/th[1]/text()").extract_first()
        ] #4

        for i in range(2, 5):
            # Các tỉnh trong bảng xổ số
            tmp_location = data_resp.xpath("//table[@id='MN0']/tr/th[{0}]/a/text()".format(i)).extract_first()
            tmp_data[tmp_location] = {}

            for j in range(2, 11):
                # Cột các giải từ giải 8 đến giải đặc biệt
                tmp_giai = data_resp.xpath("//table[@id='MN0']/tr[{0}]/td[1]/text()".format(j)).extract_first()
                # Các số trúng thưởng trong cột theo tỉnh
                tmp_number = data_resp.xpath("//table[@id='MN0']/tr[{0}]/td[{1}]//text()".format(j, i)).extract()
                tmp_data[tmp_location][tmp_giai] = ", ".join(tmp_number)

        xs_item['xs_data'] = tmp_data #5

        yield xs_item #6
  1. Scrapy cho phép chúng ta quản lý link theo domain để lấy dữ liệu, những domain ngoài allowed_domain scrapy sẽ bỏ qua
  2. Ta lấy số ngày từ function get_total_date_month sau đó đưa vào vòng lặp for. Bạn còn nhớ link (http://xskt.com.vn/ket-qua-xo-so-theo-ngay/mien-nam-xsmn/01-6-2018.html) mà ta phân tích lúc trước chứ. Chúng ta sẽ đưa các giá trị như ngày, tháng, năm vào để tạo một list cho scrapy chạy lấy dữ liệu.
  3. parse là function kế thừa từ class CrawlSpider. Function này sẽ parse respone lấy được của từng link trong danh sách trên
  4. Ta đưa thứ ngày tháng được phân tích từ xpath vào xs_info. extract_first() sẽ trả về trực tiếp giá trị là string. Mình sẽ trình bày tại sao có được xpath này ở phần dưới
  5. Tương tự cho xs_data, ta đưa số các giải vào.
  6. Yield tương tự như return, nhưng điểm khác biệt là nó sẽ lưu lại dữ liệu được yield, sau đó khi kết thúc nó sẽ trả về toàn bộ dữ liệu mà chương trình đã chạy. Bạn cần lưu ý là yield không lưu ở memory, mà được tạo ra và dùng trực tiếp. Tham khảo thêm tại đây

Code file xosokienthiet.py sẽ như sau

import scrapy
import calendar
import datetime

from scrapy.spiders import CrawlSpider
from ..items import XsktItem

def get_total_date_month(year, month):
    now = datetime.datetime.now()
    total_date = calendar.monthrange(year, month)[1]

    if year == now.year and month == now.month and now.day < total_date:
        return now.day

    return total_date

class SoxokienthietSpider(CrawlSpider):
    name = 'xosokienthiet'
    allowed_domains = ['xskt.com.vn']

    start_urls = []

    month_to_scrap = 5
    year_to_scrap = 2018
    total_date = get_total_date_month(year_to_scrap, month_to_scrap)

    for i in range(1, total_date):
        start_urls.append('http://xskt.com.vn/ket-qua-xo-so-theo-ngay/mien-nam-xsmn/'
                          '{0}-{1}-{2}.html'.format(i, month_to_scrap, year_to_scrap))

    def parse(self, response):
        xs_item = XsktItem()
        tmp_data = {}
        data_resp = scrapy.Selector(response)

        xs_item['xs_info'] = [
            # Thứ
            data_resp.xpath("//table[@id='MN0']/tr/th[1]/a/text()").extract_first(),
            # Ngày tháng
            data_resp.xpath("//table[@id='MN0']/tr/th[1]/text()").extract_first(),
            self.year_to_scrap
        ]

        for i in range(2, 5):
            # Các tỉnh trong bảng xổ số
            tmp_location = data_resp.xpath("//table[@id='MN0']/tr/th[{0}]/a/text()".format(i)).extract_first()
            tmp_data[tmp_location] = {}

            for j in range(2, 11):
                # Cột các giải từ giải 8 đến giải đặc biệt
                tmp_giai = data_resp.xpath("//table[@id='MN0']/tr[{0}]/td[1]/text()".format(j)).extract_first()
                # Các số trúng thưởng trong cột theo tỉnh
                tmp_number = data_resp.xpath("//table[@id='MN0']/tr[{0}]/td[{1}]//text()".format(j, i)).extract()
                tmp_data[tmp_location][tmp_giai] = ", ".join(tmp_number)

        xs_item['xs_data'] = tmp_data

        yield xs_item

Đoạn code trong bài viết này sẽ lấy toàn bộ kết quả xổ số miền nam trong tháng 5 / 2018. Bạn có thể chạy thử và export ra file json như sau

scrapy crawl xosokienthiet -o items.json

Kết quả file json xuất ra:

[
  {
    "xs_info": [
      "Th\u1ee9 3",
      "01/05",
      2018
    ],
    "xs_data": {
      "B\u1ea1c Li\u00eau": {
        "G.8": "16",
        "G.7": "353",
        "G.6": "1283, 2497, 2084",
        "G.5": "9561",
        "G.4": "67934, 79609, 63270, 27150, 04251, 51261, 61775",
        "G.3": "45793, 07406",
        "G.2": "26212",
        "G.1": "15768",
        "\u0110B": "438860"
      },
      "B\u1ebfn Tre": {
        "G.8": "15",
        "G.7": "483",
        "G.6": "0154, 8968, 3085",
        "G.5": "5863",
        "G.4": "17874, 34119, 64424, 88845, 68378, 11636, 93548",
        "G.3": "20315, 31614",
        "G.2": "41506",
        "G.1": "05130",
        "\u0110B": "681123"
      },
      "V\u0169ng T\u00e0u": {
        "G.8": "86",
        "G.7": "673",
        "G.6": "7176, 1084, 3496",
        "G.5": "0710",
        "G.4": "51255, 57251, 41723, 97928, 71170, 78012, 22896",
        "G.3": "65829, 98669",
        "G.2": "94047",
        "G.1": "51282",
        "\u0110B": "822257"
      }
    }
  },
  {
    "xs_info": [
      "Th\u1ee9 6",
      "04/05",
      2018
    ],
    "xs_data": {
      "B\u00ecnh D\u01b0\u01a1ng": {
        "G.8": "60",
        "G.7": "452",
        "G.6": "9257, 7863, 0383",
        "G.5": "5972",
        "G.4": "59619, 27706, 50746, 14303, 91998, 28277, 49387",
        "G.3": "20633, 33908",
        "G.2": "79568",
        "G.1": "90491",
        "\u0110B": "885468"
      },
      "Tr\u00e0 Vinh": {
        "G.8": "38",
        "G.7": "816",
        "G.6": "4893, 4984, 5266",
        "G.5": "5251",
        "G.4": "16058, 86081, 49414, 36669, 85123, 24924, 33079",
        "G.3": "51178, 49533",
        "G.2": "42977",
        "G.1": "67217",
        "\u0110B": "923726"
      },
      "V\u0129nh Long": {
        "G.8": "84",
        "G.7": "713",
        "G.6": "8785, 3400, 0110",
        "G.5": "9740",
        "G.4": "82151, 99334, 34642, 61157, 96000, 11589, 23801",
        "G.3": "81525, 22977",
        "G.2": "69329",
        "G.1": "25485",
        "\u0110B": "344846"
      }
    }
  },
  {
    "xs_info": [
      "CN",
      "06/05",
      2018
    ],
    "xs_data": {
      "\u0110\u00e0 L\u1ea1t": {
        "G.8": "69",
        "G.7": "105",
        "G.6": "4878, 0887, 3578",
        "G.5": "5121",
        "G.4": "79478, 49198, 20002, 95410, 18068, 03992, 60777",
        "G.3": "87406, 07032",
        "G.2": "88076",
        "G.1": "42492",
        "\u0110B": "620989"
      },
      "Ki\u00ean Giang": {
        "G.8": "14",
        "G.7": "106",
        "G.6": "3550, 9384, 9957",
        "G.5": "1671",
        "G.4": "31918, 70479, 27675, 59528, 10239, 78092, 21698",
        "G.3": "38876, 19127",
        "G.2": "65845",
        "G.1": "31073",
        "\u0110B": "949938"
      },
      "Ti\u1ec1n Giang": {
        "G.8": "37",
        "G.7": "386",
        "G.6": "9605, 6995, 2270",
        "G.5": "1684",
        "G.4": "54380, 82874, 67586, 63497, 32057, 13779, 46003",
        "G.3": "24278, 74885",
        "G.2": "25270",
        "G.1": "51333",
        "\u0110B": "192854"
      }
    }
  },
  {
    "xs_info": [
      "Th\u1ee9 5",
      "03/05",
      2018
    ],
    "xs_data": {
      "An Giang": {
        "G.8": "94",
        "G.7": "794",
        "G.6": "0187, 4573, 3878",
        "G.5": "3312",
        "G.4": "20138, 93334, 90095, 35491, 35696, 02050, 03079",
        "G.3": "34572, 72987",
        "G.2": "37368",
        "G.1": "12953",
        "\u0110B": "005462"
      },
      "B\u00ecnh Thu\u1eadn": {
        "G.8": "27",
        "G.7": "663",
        "G.6": "3645, 3468, 2176",
        "G.5": "7737",
        "G.4": "62771, 04263, 36750, 69320, 62382, 73465, 65376",
        "G.3": "59577, 32743",
        "G.2": "52100",
        "G.1": "47715",
        "\u0110B": "824830"
      },
      "T\u00e2y Ninh": {
        "G.8": "83",
        "G.7": "767",
        "G.6": "4239, 3652, 9645",
        "G.5": "5423",
        "G.4": "31471, 50394, 77260, 02009, 22903, 97308, 89899",
        "G.3": "32127, 39143",
        "G.2": "82382",
        "G.1": "23176",
        "\u0110B": "281533"
      }
    }
  },
  {
    "xs_info": [
      "Th\u1ee9 7",
      "05/05",
      2018
    ],
    "xs_data": {
      "B\u00ecnh Ph\u01b0\u1edbc": {
        "G.8": "67",
        "G.7": "965",
        "G.6": "1695, 9928, 8916",
        "G.5": "7285",
        "G.4": "84710, 05606, 78237, 97939, 99657, 89430, 71291",
        "G.3": "50955, 41193",
        "G.2": "87111",
        "G.1": "79999",
        "\u0110B": "664905"
      },
      "TP.HCM": {
        "G.8": "13",
        "G.7": "763",
        "G.6": "5735, 2650, 9395",
        "G.5": "3853",
        "G.4": "13106, 23340, 90176, 15614, 23642, 87545, 32097",
        "G.3": "12392, 79917",
        "G.2": "43408",
        "G.1": "22796",
        "\u0110B": "863955"
      },
      "H\u1eadu Giang": {
        "G.8": "33",
        "G.7": "088",
        "G.6": "9982, 3416, 4420",
        "G.5": "6240",
        "G.4": "59187, 71216, 38613, 75620, 40299, 89214, 63035",
        "G.3": "57508, 95761",
        "G.2": "91377",
        "G.1": "41359",
        "\u0110B": "275874"
      }
    }
  },
  {
    "xs_info": [
      "Th\u1ee9 4",
      "02/05",
      2018
    ],
    "xs_data": {
      "C\u1ea7n Th\u01a1": {
        "G.8": "29",
        "G.7": "415",
        "G.6": "4349, 3660, 7518",
        "G.5": "0664",
        "G.4": "57233, 18537, 63657, 80663, 98840, 11854, 96175",
        "G.3": "52599, 17432",
        "G.2": "60654",
        "G.1": "65835",
        "\u0110B": "404049"
      },
      "\u0110\u1ed3ng Nai": {
        "G.8": "69",
        "G.7": "741",
        "G.6": "2933, 4759, 3205",
        "G.5": "0888",
        "G.4": "20376, 44093, 59339, 48904, 27532, 63456, 50913",
        "G.3": "58367, 72465",
        "G.2": "43852",
        "G.1": "76663",
        "\u0110B": "533867"
      },
      "S\u00f3c Tr\u0103ng": {
        "G.8": "84",
        "G.7": "654",
        "G.6": "4998, 3841, 8098",
        "G.5": "9041",
        "G.4": "80284, 15544, 50263, 16830, 73421, 28479, 49643",
        "G.3": "67012, 17594",
        "G.2": "25363",
        "G.1": "11726",
        "\u0110B": "920992"
      }
    }
  },
  {
    "xs_info": [
      "Th\u1ee9 5",
      "10/05",
      2018
    ],
    "xs_data": {
      "An Giang": {
        "G.8": "52",
        "G.7": "932",
        "G.6": "3623, 4593, 4384",
        "G.5": "2262",
        "G.4": "45457, 15597, 79475, 32808, 44451, 07640, 06155",
        "G.3": "09383, 08366",
        "G.2": "31879",
        "G.1": "23741",
        "\u0110B": "450580"
      },
      "B\u00ecnh Thu\u1eadn": {
        "G.8": "65",
        "G.7": "418",
        "G.6": "0312, 9128, 3209",
        "G.5": "1971",
        "G.4": "47031, 34801, 63126, 75945, 39134, 06160, 57141",
        "G.3": "75258, 12882",
        "G.2": "38951",
        "G.1": "29188",
        "\u0110B": "172096"
      },
      "T\u00e2y Ninh": {
        "G.8": "64",
        "G.7": "688",
        "G.6": "6407, 3101, 6357",
        "G.5": "2315",
        "G.4": "92331, 12204, 09469, 18618, 41193, 16730, 75205",
        "G.3": "10671, 61843",
        "G.2": "90852",
        "G.1": "79720",
        "\u0110B": "535419"
      }
    }
  },
  {
    "xs_info": [
      "CN",
      "13/05",
      2018
    ],
    "xs_data": {
      "\u0110\u00e0 L\u1ea1t": {
        "G.8": "14",
        "G.7": "724",
        "G.6": "0981, 2263, 6944",
        "G.5": "8656",
        "G.4": "96994, 23915, 63782, 08057, 50918, 16647, 78389",
        "G.3": "83976, 83047",
        "G.2": "89079",
        "G.1": "70743",
        "\u0110B": "002603"
      },
      "Ki\u00ean Giang": {
        "G.8": "83",
        "G.7": "852",
        "G.6": "3985, 1752, 0070",
        "G.5": "6099",
        "G.4": "19349, 08761, 65055, 53976, 78993, 80259, 53912",
        "G.3": "67207, 24247",
        "G.2": "25263",
        "G.1": "59241",
        "\u0110B": "335122"
      },
      "Ti\u1ec1n Giang": {
        "G.8": "19",
        "G.7": "696",
        "G.6": "5313, 0922, 1814",
        "G.5": "5018",
        "G.4": "32428, 56233, 29224, 70849, 20669, 17458, 89764",
        "G.3": "07611, 16460",
        "G.2": "71609",
        "G.1": "34096",
        "\u0110B": "372540"
      }
    }
  },
  {
    "xs_info": [
      "Th\u1ee9 5",
      "10/05",
      2018
    ],
    "xs_data": {
      "An Giang": {
        "G.8": "52",
        "G.7": "932",
        "G.6": "3623, 4593, 4384",
        "G.5": "2262",
        "G.4": "45457, 15597, 79475, 32808, 44451, 07640, 06155",
        "G.3": "09383, 08366",
        "G.2": "31879",
        "G.1": "23741",
        "\u0110B": "450580"
      },
      "B\u00ecnh Thu\u1eadn": {
        "G.8": "65",
        "G.7": "418",
        "G.6": "0312, 9128, 3209",
        "G.5": "1971",
        "G.4": "47031, 34801, 63126, 75945, 39134, 06160, 57141",
        "G.3": "75258, 12882",
        "G.2": "38951",
        "G.1": "29188",
        "\u0110B": "172096"
      },
      "T\u00e2y Ninh": {
        "G.8": "64",
        "G.7": "688",
        "G.6": "6407, 3101, 6357",
        "G.5": "2315",
        "G.4": "92331, 12204, 09469, 18618, 41193, 16730, 75205",
        "G.3": "10671, 61843",
        "G.2": "90852",
        "G.1": "79720",
        "\u0110B": "535419"
      }
    }
  },
  {
    "xs_info": [
      "Th\u1ee9 2",
      "14/05",
      2018
    ],
    "xs_data": {
      "C\u00e0 Mau": {
        "G.8": "50",
        "G.7": "062",
        "G.6": "7829, 7241, 2292",
        "G.5": "2879",
        "G.4": "71148, 83336, 85846, 33476, 78844, 09520, 96175",
        "G.3": "68542, 98264",
        "G.2": "51031",
        "G.1": "44839",
        "\u0110B": "886930"
      },
      "\u0110\u1ed3ng Th\u00e1p": {
        "G.8": "83",
        "G.7": "687",
        "G.6": "8322, 7707, 0439",
        "G.5": "4953",
        "G.4": "56354, 90245, 87152, 08383, 70004, 21246, 44655",
        "G.3": "90339, 33914",
        "G.2": "63369",
        "G.1": "20810",
        "\u0110B": "681146"
      },
      "TP.HCM": {
        "G.8": "91",
        "G.7": "832",
        "G.6": "5246, 0202, 1223",
        "G.5": "6334",
        "G.4": "86302, 45657, 46403, 30653, 58588, 61869, 58876",
        "G.3": "77792, 29748",
        "G.2": "63626",
        "G.1": "57976",
        "\u0110B": "891481"
      }
    }
  },
  {
    "xs_info": [
      "Th\u1ee9 6",
      "11/05",
      2018
    ],
    "xs_data": {
      "B\u00ecnh D\u01b0\u01a1ng": {
        "G.8": "00",
        "G.7": "581",
        "G.6": "9814, 2826, 3228",
        "G.5": "1346",
        "G.4": "55991, 73399, 79308, 32271, 61524, 13497, 99399",
        "G.3": "52502, 05619",
        "G.2": "84193",
        "G.1": "79797",
        "\u0110B": "027386"
      },
      "Tr\u00e0 Vinh": {
        "G.8": "56",
        "G.7": "409",
        "G.6": "2533, 5208, 0365",
        "G.5": "0001",
        "G.4": "16617, 64534, 30356, 46688, 17038, 75826, 08697",
        "G.3": "68794, 07939",
        "G.2": "23420",
        "G.1": "78858",
        "\u0110B": "822105"
      },
      "V\u0129nh Long": {
        "G.8": "85",
        "G.7": "033",
        "G.6": "3620, 1082, 1862",
        "G.5": "3696",
        "G.4": "26075, 88528, 64495, 11137, 64648, 67412, 46023",
        "G.3": "12039, 44360",
        "G.2": "46047",
        "G.1": "81352",
        "\u0110B": "895054"
      }
    }
  },
  {
    "xs_info": [
      "Th\u1ee9 3",
      "15/05",
      2018
    ],
    "xs_data": {
      "B\u1ea1c Li\u00eau": {
        "G.8": "66",
        "G.7": "000",
        "G.6": "0090, 1091, 2879",
        "G.5": "8770",
        "G.4": "06751, 32335, 27980, 27472, 35808, 12066, 82838",
        "G.3": "52210, 82044",
        "G.2": "20959",
        "G.1": "41630",
        "\u0110B": "870719"
      },
      "B\u1ebfn Tre": {
        "G.8": "19",
        "G.7": "456",
        "G.6": "0993, 8004, 3803",
        "G.5": "9769",
        "G.4": "03154, 19514, 54967, 00214, 50462, 20751, 18357",
        "G.3": "81474, 44403",
        "G.2": "29612",
        "G.1": "44784",
        "\u0110B": "712739"
      },
      "V\u0169ng T\u00e0u": {
        "G.8": "98",
        "G.7": "006",
        "G.6": "1658, 8555, 9396",
        "G.5": "7514",
        "G.4": "52543, 35456, 18575, 17145, 64830, 31446, 24205",
        "G.3": "57273, 42422",
        "G.2": "83413",
        "G.1": "32578",
        "\u0110B": "067898"
      }
    }
  },
  {
    "xs_info": [
      "Th\u1ee9 7",
      "12/05",
      2018
    ],
    "xs_data": {
      "B\u00ecnh Ph\u01b0\u1edbc": {
        "G.8": "70",
        "G.7": "861",
        "G.6": "2401, 3299, 1381",
        "G.5": "5459",
        "G.4": "65942, 07862, 08658, 95400, 44921, 86284, 85659",
        "G.3": "05372, 72401",
        "G.2": "30070",
        "G.1": "50886",
        "\u0110B": "260083"
      },
      "TP.HCM": {
        "G.8": "44",
        "G.7": "714",
        "G.6": "4804, 7269, 6115",
        "G.5": "4468",
        "G.4": "15752, 91761, 14370, 01574, 10493, 60161, 35972",
        "G.3": "28954, 61737",
        "G.2": "06914",
        "G.1": "77743",
        "\u0110B": "063815"
      },
      "H\u1eadu Giang": {
        "G.8": "51",
        "G.7": "149",
        "G.6": "6513, 1728, 3611",
        "G.5": "9673",
        "G.4": "08006, 64012, 96163, 31589, 02607, 83270, 86758",
        "G.3": "90875, 65820",
        "G.2": "95155",
        "G.1": "30506",
        "\u0110B": "377118"
      }
    }
  },
  {
    "xs_info": [
      "Th\u1ee9 4",
      "16/05",
      2018
    ],
    "xs_data": {
      "C\u1ea7n Th\u01a1": {
        "G.8": "40",
        "G.7": "544",
        "G.6": "1768, 2173, 2902",
        "G.5": "5969",
        "G.4": "18672, 39484, 98138, 31078, 61683, 76635, 92603",
        "G.3": "06110, 91619",
        "G.2": "06506",
        "G.1": "29596",
        "\u0110B": "815161"
      },
      "\u0110\u1ed3ng Nai": {
        "G.8": "85",
        "G.7": "467",
        "G.6": "3413, 0425, 7125",
        "G.5": "3939",
        "G.4": "91987, 06549, 46514, 30528, 08769, 98142, 27266",
        "G.3": "74485, 78765",
        "G.2": "79011",
        "G.1": "30890",
        "\u0110B": "719280"
      },
      "S\u00f3c Tr\u0103ng": {
        "G.8": "65",
        "G.7": "792",
        "G.6": "2213, 7877, 9988",
        "G.5": "5595",
        "G.4": "50098, 05036, 29895, 43900, 72992, 41950, 69852",
        "G.3": "46641, 37440",
        "G.2": "58106",
        "G.1": "80428",
        "\u0110B": "588943"
      }
    }
  },
  {
    "xs_info": [
      "Th\u1ee9 5",
      "17/05",
      2018
    ],
    "xs_data": {
      "An Giang": {
        "G.8": "74",
        "G.7": "869",
        "G.6": "1044, 7984, 2942",
        "G.5": "7802",
        "G.4": "47435, 82120, 74793, 58931, 38300, 68963, 42988",
        "G.3": "91186, 99520",
        "G.2": "32990",
        "G.1": "04955",
        "\u0110B": "046984"
      },
      "B\u00ecnh Thu\u1eadn": {
        "G.8": "57",
        "G.7": "153",
        "G.6": "2010, 6583, 1173",
        "G.5": "0059",
        "G.4": "49118, 93962, 39111, 43927, 64837, 42950, 92552",
        "G.3": "33427, 15263",
        "G.2": "11703",
        "G.1": "39283",
        "\u0110B": "641919"
      },
      "T\u00e2y Ninh": {
        "G.8": "88",
        "G.7": "967",
        "G.6": "3518, 0591, 6093",
        "G.5": "3379",
        "G.4": "69375, 10092, 59277, 86682, 56008, 38743, 96116",
        "G.3": "23103, 72148",
        "G.2": "31074",
        "G.1": "27535",
        "\u0110B": "268378"
      }
    }
  },
  {
    "xs_info": [
      "Th\u1ee9 6",
      "18/05",
      2018
    ],
    "xs_data": {
      "B\u00ecnh D\u01b0\u01a1ng": {
        "G.8": "45",
        "G.7": "454",
        "G.6": "9434, 5294, 7199",
        "G.5": "6113",
        "G.4": "76230, 15907, 91024, 16331, 20848, 39279, 43377",
        "G.3": "37186, 13053",
        "G.2": "97007",
        "G.1": "15801",
        "\u0110B": "338337"
      },
      "Tr\u00e0 Vinh": {
        "G.8": "59",
        "G.7": "965",
        "G.6": "3226, 3244, 3813",
        "G.5": "5866",
        "G.4": "42235, 40800, 96581, 15130, 46169, 44271, 26175",
        "G.3": "89387, 72525",
        "G.2": "11408",
        "G.1": "20797",
        "\u0110B": "820545"
      },
      "V\u0129nh Long": {
        "G.8": "36",
        "G.7": "165",
        "G.6": "4776, 4761, 1075",
        "G.5": "8955",
        "G.4": "33667, 88817, 12891, 10869, 53596, 73419, 43164",
        "G.3": "70861, 88032",
        "G.2": "94950",
        "G.1": "37427",
        "\u0110B": "014217"
      }
    }
  },
  {
    "xs_info": [
      "CN",
      "20/05",
      2018
    ],
    "xs_data": {
      "\u0110\u00e0 L\u1ea1t": {
        "G.8": "72",
        "G.7": "039",
        "G.6": "9979, 1767, 4766",
        "G.5": "3537",
        "G.4": "44987, 74228, 96852, 83325, 94751, 67100, 05293",
        "G.3": "91699, 31240",
        "G.2": "48851",
        "G.1": "43269",
        "\u0110B": "044063"
      },
      "Ki\u00ean Giang": {
        "G.8": "34",
        "G.7": "861",
        "G.6": "4819, 5443, 2039",
        "G.5": "2015",
        "G.4": "26106, 80759, 53526, 19180, 44852, 94250, 21065",
        "G.3": "28094, 23312",
        "G.2": "16303",
        "G.1": "66229",
        "\u0110B": "056954"
      },
      "Ti\u1ec1n Giang": {
        "G.8": "05",
        "G.7": "058",
        "G.6": "7060, 8984, 3634",
        "G.5": "6068",
        "G.4": "23283, 63168, 13983, 12925, 97812, 10431, 81082",
        "G.3": "88846, 95940",
        "G.2": "07232",
        "G.1": "81944",
        "\u0110B": "104825"
      }
    }
  },
  {
    "xs_info": [
      "Th\u1ee9 7",
      "19/05",
      2018
    ],
    "xs_data": {
      "B\u00ecnh Ph\u01b0\u1edbc": {
        "G.8": "73",
        "G.7": "543",
        "G.6": "2792, 7334, 7512",
        "G.5": "1333",
        "G.4": "73979, 68517, 13135, 65355, 44527, 87510, 40813",
        "G.3": "95763, 39098",
        "G.2": "40793",
        "G.1": "62785",
        "\u0110B": "055443"
      },
      "TP.HCM": {
        "G.8": "17",
        "G.7": "732",
        "G.6": "8526, 7505, 4115",
        "G.5": "3353",
        "G.4": "57730, 80757, 89799, 88783, 91112, 63303, 07912",
        "G.3": "63236, 90396",
        "G.2": "85013",
        "G.1": "94177",
        "\u0110B": "516387"
      },
      "H\u1eadu Giang": {
        "G.8": "66",
        "G.7": "048",
        "G.6": "1624, 0900, 0505",
        "G.5": "4476",
        "G.4": "23027, 41434, 18215, 30378, 15191, 17212, 80807",
        "G.3": "14303, 14958",
        "G.2": "95601",
        "G.1": "65749",
        "\u0110B": "806861"
      }
    }
  },
  {
    "xs_info": [
      "Th\u1ee9 3",
      "22/05",
      2018
    ],
    "xs_data": {
      "B\u1ea1c Li\u00eau": {
        "G.8": "39",
        "G.7": "357",
        "G.6": "5218, 3191, 7013",
        "G.5": "4813",
        "G.4": "38567, 43365, 52398, 18351, 58634, 61965, 54313",
        "G.3": "72461, 18327",
        "G.2": "44504",
        "G.1": "08742",
        "\u0110B": "946382"
      },
      "B\u1ebfn Tre": {
        "G.8": "90",
        "G.7": "583",
        "G.6": "6649, 5307, 9536",
        "G.5": "8653",
        "G.4": "80349, 89569, 94674, 29193, 59650, 34183, 96613",
        "G.3": "68333, 96747",
        "G.2": "55911",
        "G.1": "93965",
        "\u0110B": "835548"
      },
      "V\u0169ng T\u00e0u": {
        "G.8": "44",
        "G.7": "505",
        "G.6": "9521, 1149, 7662",
        "G.5": "1167",
        "G.4": "79007, 63331, 34122, 78615, 84404, 59515, 60905",
        "G.3": "00481, 77479",
        "G.2": "39346",
        "G.1": "01123",
        "\u0110B": "785018"
      }
    }
  },
  {
    "xs_info": [
      "Th\u1ee9 2",
      "21/05",
      2018
    ],
    "xs_data": {
      "C\u00e0 Mau": {
        "G.8": "36",
        "G.7": "759",
        "G.6": "9940, 3566, 1586",
        "G.5": "7621",
        "G.4": "41671, 47806, 76284, 88755, 96178, 80638, 37923",
        "G.3": "67670, 49788",
        "G.2": "98617",
        "G.1": "85543",
        "\u0110B": "496531"
      },
      "\u0110\u1ed3ng Th\u00e1p": {
        "G.8": "04",
        "G.7": "919",
        "G.6": "2265, 8000, 2095",
        "G.5": "5631",
        "G.4": "49618, 15768, 54250, 93495, 65639, 81435, 68721",
        "G.3": "60252, 26651",
        "G.2": "80621",
        "G.1": "79590",
        "\u0110B": "955252"
      },
      "TP.HCM": {
        "G.8": "67",
        "G.7": "681",
        "G.6": "8465, 7091, 5032",
        "G.5": "6329",
        "G.4": "84819, 58924, 38198, 63449, 26315, 75972, 30626",
        "G.3": "79670, 00612",
        "G.2": "00903",
        "G.1": "96365",
        "\u0110B": "058352"
      }
    }
  },
  {
    "xs_info": [
      "Th\u1ee9 7",
      "26/05",
      2018
    ],
    "xs_data": {
      "B\u00ecnh Ph\u01b0\u1edbc": {
        "G.8": "20",
        "G.7": "878",
        "G.6": "6687, 0387, 5796",
        "G.5": "7882",
        "G.4": "39378, 43576, 87635, 00406, 60658, 71665, 83310",
        "G.3": "00111, 06782",
        "G.2": "90474",
        "G.1": "52522",
        "\u0110B": "907183"
      },
      "TP.HCM": {
        "G.8": "54",
        "G.7": "951",
        "G.6": "4015, 5744, 1451",
        "G.5": "6098",
        "G.4": "51848, 20493, 59247, 76987, 96192, 83293, 94301",
        "G.3": "21853, 47038",
        "G.2": "24064",
        "G.1": "66049",
        "\u0110B": "122345"
      },
      "H\u1eadu Giang": {
        "G.8": "20",
        "G.7": "792",
        "G.6": "1923, 1621, 3319",
        "G.5": "9753",
        "G.4": "76528, 64769, 44012, 77147, 28947, 65805, 18806",
        "G.3": "49068, 23065",
        "G.2": "15731",
        "G.1": "69743",
        "\u0110B": "820456"
      }
    }
  },
  {
    "xs_info": [
      "CN",
      "27/05",
      2018
    ],
    "xs_data": {
      "\u0110\u00e0 L\u1ea1t": {
        "G.8": "69",
        "G.7": "982",
        "G.6": "9851, 9642, 9521",
        "G.5": "7972",
        "G.4": "31215, 82451, 99299, 86296, 09659, 83301, 42201",
        "G.3": "99146, 24034",
        "G.2": "16114",
        "G.1": "46406",
        "\u0110B": "014287"
      },
      "Ki\u00ean Giang": {
        "G.8": "10",
        "G.7": "447",
        "G.6": "1603, 3796, 1095",
        "G.5": "9918",
        "G.4": "65947, 11195, 49669, 87857, 27333, 48558, 42031",
        "G.3": "24349, 48603",
        "G.2": "24341",
        "G.1": "16086",
        "\u0110B": "179516"
      },
      "Ti\u1ec1n Giang": {
        "G.8": "53",
        "G.7": "997",
        "G.6": "2357, 4759, 5377",
        "G.5": "1624",
        "G.4": "89160, 68442, 72256, 14522, 73416, 52382, 12042",
        "G.3": "97760, 51079",
        "G.2": "33967",
        "G.1": "46245",
        "\u0110B": "799397"
      }
    }
  },
  {
    "xs_info": [
      "Th\u1ee9 5",
      "24/05",
      2018
    ],
    "xs_data": {
      "An Giang": {
        "G.8": "69",
        "G.7": "665",
        "G.6": "5140, 3308, 1360",
        "G.5": "0271",
        "G.4": "27734, 70204, 36634, 24802, 69670, 29777, 57372",
        "G.3": "27754, 02149",
        "G.2": "93033",
        "G.1": "43389",
        "\u0110B": "245787"
      },
      "B\u00ecnh Thu\u1eadn": {
        "G.8": "71",
        "G.7": "100",
        "G.6": "4348, 9392, 3964",
        "G.5": "6157",
        "G.4": "88682, 49218, 45941, 16929, 34583, 57601, 15960",
        "G.3": "85513, 05662",
        "G.2": "72926",
        "G.1": "35416",
        "\u0110B": "158020"
      },
      "T\u00e2y Ninh": {
        "G.8": "60",
        "G.7": "586",
        "G.6": "8908, 6583, 8954",
        "G.5": "3702",
        "G.4": "15934, 29619, 04654, 96746, 41170, 98994, 89288",
        "G.3": "38847, 18065",
        "G.2": "47429",
        "G.1": "85282",
        "\u0110B": "598291"
      }
    }
  },
  {
    "xs_info": [
      "Th\u1ee9 5",
      "24/05",
      2018
    ],
    "xs_data": {
      "An Giang": {
        "G.8": "69",
        "G.7": "665",
        "G.6": "5140, 3308, 1360",
        "G.5": "0271",
        "G.4": "27734, 70204, 36634, 24802, 69670, 29777, 57372",
        "G.3": "27754, 02149",
        "G.2": "93033",
        "G.1": "43389",
        "\u0110B": "245787"
      },
      "B\u00ecnh Thu\u1eadn": {
        "G.8": "71",
        "G.7": "100",
        "G.6": "4348, 9392, 3964",
        "G.5": "6157",
        "G.4": "88682, 49218, 45941, 16929, 34583, 57601, 15960",
        "G.3": "85513, 05662",
        "G.2": "72926",
        "G.1": "35416",
        "\u0110B": "158020"
      },
      "T\u00e2y Ninh": {
        "G.8": "60",
        "G.7": "586",
        "G.6": "8908, 6583, 8954",
        "G.5": "3702",
        "G.4": "15934, 29619, 04654, 96746, 41170, 98994, 89288",
        "G.3": "38847, 18065",
        "G.2": "47429",
        "G.1": "85282",
        "\u0110B": "598291"
      }
    }
  },
  {
    "xs_info": [
      "Th\u1ee9 6",
      "25/05",
      2018
    ],
    "xs_data": {
      "B\u00ecnh D\u01b0\u01a1ng": {
        "G.8": "01",
        "G.7": "968",
        "G.6": "7425, 2535, 0782",
        "G.5": "6232",
        "G.4": "69076, 95402, 96005, 80486, 54500, 28140, 65060",
        "G.3": "71574, 29344",
        "G.2": "20571",
        "G.1": "03635",
        "\u0110B": "610660"
      },
      "Tr\u00e0 Vinh": {
        "G.8": "15",
        "G.7": "024",
        "G.6": "6133, 9816, 4274",
        "G.5": "8228",
        "G.4": "15207, 38079, 95421, 44928, 39125, 01437, 74905",
        "G.3": "03808, 43454",
        "G.2": "54319",
        "G.1": "27914",
        "\u0110B": "277784"
      },
      "V\u0129nh Long": {
        "G.8": "07",
        "G.7": "750",
        "G.6": "3780, 7858, 3640",
        "G.5": "5939",
        "G.4": "66763, 80974, 89550, 80172, 61695, 95040, 80192",
        "G.3": "11263, 58077",
        "G.2": "10917",
        "G.1": "94594",
        "\u0110B": "934328"
      }
    }
  },
  {
    "xs_info": [
      "Th\u1ee9 4",
      "23/05",
      2018
    ],
    "xs_data": {
      "C\u1ea7n Th\u01a1": {
        "G.8": "29",
        "G.7": "482",
        "G.6": "9867, 9416, 2625",
        "G.5": "3654",
        "G.4": "88757, 83187, 37175, 86074, 76987, 30384, 07811",
        "G.3": "05749, 97268",
        "G.2": "29494",
        "G.1": "17878",
        "\u0110B": "811998"
      },
      "\u0110\u1ed3ng Nai": {
        "G.8": "13",
        "G.7": "770",
        "G.6": "1227, 5479, 7059",
        "G.5": "0749",
        "G.4": "40644, 78756, 60762, 34042, 31113, 72578, 70204",
        "G.3": "11922, 40869",
        "G.2": "29119",
        "G.1": "89808",
        "\u0110B": "895992"
      },
      "S\u00f3c Tr\u0103ng": {
        "G.8": "95",
        "G.7": "480",
        "G.6": "4678, 1568, 4840",
        "G.5": "8792",
        "G.4": "88753, 41858, 10187, 63942, 35530, 04361, 93835",
        "G.3": "57902, 66294",
        "G.2": "32106",
        "G.1": "65544",
        "\u0110B": "010629"
      }
    }
  },
  {
    "xs_info": [
      "Th\u1ee9 6",
      "25/05",
      2018
    ],
    "xs_data": {
      "B\u00ecnh D\u01b0\u01a1ng": {
        "G.8": "01",
        "G.7": "968",
        "G.6": "7425, 2535, 0782",
        "G.5": "6232",
        "G.4": "69076, 95402, 96005, 80486, 54500, 28140, 65060",
        "G.3": "71574, 29344",
        "G.2": "20571",
        "G.1": "03635",
        "\u0110B": "610660"
      },
      "Tr\u00e0 Vinh": {
        "G.8": "15",
        "G.7": "024",
        "G.6": "6133, 9816, 4274",
        "G.5": "8228",
        "G.4": "15207, 38079, 95421, 44928, 39125, 01437, 74905",
        "G.3": "03808, 43454",
        "G.2": "54319",
        "G.1": "27914",
        "\u0110B": "277784"
      },
      "V\u0129nh Long": {
        "G.8": "07",
        "G.7": "750",
        "G.6": "3780, 7858, 3640",
        "G.5": "5939",
        "G.4": "66763, 80974, 89550, 80172, 61695, 95040, 80192",
        "G.3": "11263, 58077",
        "G.2": "10917",
        "G.1": "94594",
        "\u0110B": "934328"
      }
    }
  },
  {
    "xs_info": [
      "Th\u1ee9 4",
      "30/05",
      2018
    ],
    "xs_data": {
      "C\u1ea7n Th\u01a1": {
        "G.8": "75",
        "G.7": "039",
        "G.6": "7177, 9837, 3440",
        "G.5": "5498",
        "G.4": "20745, 43337, 83306, 45019, 25140, 46648, 81118",
        "G.3": "61182, 01711",
        "G.2": "35737",
        "G.1": "93596",
        "\u0110B": "167473"
      },
      "\u0110\u1ed3ng Nai": {
        "G.8": "60",
        "G.7": "278",
        "G.6": "2268, 8312, 2377",
        "G.5": "1802",
        "G.4": "53848, 56462, 98202, 57696, 69935, 87180, 82637",
        "G.3": "59868, 27844",
        "G.2": "84448",
        "G.1": "25309",
        "\u0110B": "580647"
      },
      "S\u00f3c Tr\u0103ng": {
        "G.8": "52",
        "G.7": "715",
        "G.6": "8793, 8260, 8794",
        "G.5": "1216",
        "G.4": "05305, 57986, 16308, 23942, 71828, 95079, 88159",
        "G.3": "79918, 65304",
        "G.2": "64523",
        "G.1": "53567",
        "\u0110B": "761141"
      }
    }
  },
  {
    "xs_info": [
      "Th\u1ee9 2",
      "07/05",
      2018
    ],
    "xs_data": {
      "C\u00e0 Mau": {
        "G.8": "94",
        "G.7": "652",
        "G.6": "2907, 2337, 5948",
        "G.5": "8170",
        "G.4": "13885, 56888, 58359, 89414, 98428, 00378, 53725",
        "G.3": "08025, 47033",
        "G.2": "69301",
        "G.1": "46213",
        "\u0110B": "895478"
      },
      "\u0110\u1ed3ng Th\u00e1p": {
        "G.8": "80",
        "G.7": "504",
        "G.6": "5777, 8074, 8228",
        "G.5": "0699",
        "G.4": "29682, 28851, 07260, 91185, 51636, 94494, 65145",
        "G.3": "28169, 32168",
        "G.2": "55596",
        "G.1": "05483",
        "\u0110B": "493447"
      },
      "TP.HCM": {
        "G.8": "62",
        "G.7": "251",
        "G.6": "4067, 4810, 7087",
        "G.5": "3912",
        "G.4": "86233, 53989, 93622, 34544, 23840, 18770, 70994",
        "G.3": "33598, 09021",
        "G.2": "14893",
        "G.1": "12096",
        "\u0110B": "236959"
      }
    }
  },
  {
    "xs_info": [
      "Th\u1ee9 3",
      "08/05",
      2018
    ],
    "xs_data": {
      "B\u1ea1c Li\u00eau": {
        "G.8": "44",
        "G.7": "488",
        "G.6": "3643, 9439, 4043",
        "G.5": "1597",
        "G.4": "41892, 86239, 46011, 25661, 87280, 38105, 27863",
        "G.3": "16120, 29956",
        "G.2": "04732",
        "G.1": "85851",
        "\u0110B": "921072"
      },
      "B\u1ebfn Tre": {
        "G.8": "04",
        "G.7": "236",
        "G.6": "3071, 1354, 0910",
        "G.5": "3234",
        "G.4": "76649, 60435, 31076, 97175, 08419, 65465, 38763",
        "G.3": "78410, 77712",
        "G.2": "60082",
        "G.1": "21332",
        "\u0110B": "348921"
      },
      "V\u0169ng T\u00e0u": {
        "G.8": "33",
        "G.7": "190",
        "G.6": "9517, 1422, 0304",
        "G.5": "2155",
        "G.4": "17700, 20398, 89251, 41507, 77627, 69396, 38502",
        "G.3": "03188, 66896",
        "G.2": "28589",
        "G.1": "96082",
        "\u0110B": "493208"
      }
    }
  }
]

Nếu bạn muốn lưu kết quả vào database, bạn phải kích hoạt pipeline. Mình sẽ dùng sqlite3 trong ví dụ này. Bạn mở file settings.py vào tìm ITEM_PIPELINE ra và uncomment

 ITEM_PIPELINES = {
    'xskt.pipelines.XsktPipeline': 300,
 }

Bây giờ bạn hãy mở file pipelines.py và chỉnh sửa như sau

# -*- coding: utf-8 -*-

# Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: http://doc.scrapy.org/en/latest/topics/item-pipeline.html
from sqlite3 import dbapi2 as sqlite

class XsktPipeline(object):
    def __init__(self):
        self.connection = sqlite.connect('./xs_database.db')
        self.cursor = self.connection.cursor()
        self.cursor.execute('CREATE TABLE IF NOT EXISTS kq_xs '
                            '(id INTEGER PRIMARY KEY, xs_thu VARCHAR(80),'
                            'xs_ngay_thang VARCHAR(80), xs_nam VARCHAR(80), xs_data TEXT)')

    def process_item(self, item, spider):
        self.cursor.execute("select * from kq_xs where xs_thu=? and xs_ngay_thang=? and xs_nam=?", (item['xs_info'][0], item['xs_info'][1], item['xs_info'][2]))

        result = self.cursor.fetchone()
        if not result:
            self.cursor.execute(
                "insert into kq_xs (xs_thu, xs_ngay_thang, xs_nam, xs_data) values (?, ?, ?, ?)",
                (item['xs_info'][0], item['xs_info'][1], item['xs_info'][2], str(item['xs_data'])))

            self.connection.commit()

        return item

Sau đó bạn chạy command

scrapy crawl xosokienthiet

Kết quả sau khi chạy scrapy

Hướng dẫn phân tích site để lấy xpath

Đầu tiên ta cần vào site lấy dữ liệu http://xskt.com.vn/ket-qua-xo-so-theo-ngay/mien-nam-xsmn/01-6-2018.html

Để lấy thứ ta cần biết là table chứa bảng số này có class hay id gì khác biệt không. Bạn hãy dùng Inspector (nhấn F12 hoặc click phải lên Thứ 6) để xem

Theo hình trên table này có cả Id và class để chúng ta khai thác. Nhưng vì class sẽ có thể dễ bị trùng với các element khác, nên chúng ta sẽ sử dụng id. Bạn hãy ghi lại MN0.

Tiếp theo ta sẽ xem tới "Thứ 6", ta thấy "Thứ 6" nằm trong table (id = MN0) > tr > th[1] > a (text). th[1] chỉ định th đầu tiên trong table

data_resp.xpath("//table[@id='MN0']/tr/th[1]/a/text()").extract_first()

Tương tự cho ngày tháng sẽ là table (id = MN0) > tr > th[1]  (text)

data_resp.xpath("//table[@id='MN0']/tr/th[1]/text()").extract_first()

Các element khác bạn cũng làm tương tự như vậy. Bạn hãy thử tự phân tích xem sao.

Bài viết hướng dẫn scrapy - công cụ bóc tách dữ đến đây là kết thúc. Mọi ý kiến góp ý của các bạn mình rất hoan nghênh. Các bạn thắc mắc có thể hỏi mình bằng cách comment tại bài viết này hoặc trên group Python Community Viet Nam. Chúc các bạn tự học python thành công.

Link github: https://github.com/kikyo2006/scrapy-demo-xskt

Các thẻ
Bài viết liên quan
15 nhận xét
  1. Trả lời

    hai nam ngo

    26 Tháng 8, 2018

    scrapy mình cài bị lỗi : Could not install packages due to an EnvironmentError: [Errno 13] Permission denied: '/usr/local/lib/python2.7/dist-packages/queuelib-1.5.0.dist-info'
    Consider using the `--user` option or check the permissions.
    admin có cách nào khắc phục không

    • Trả lời

      Anh Vũ Từ

      27 Tháng 8, 2018

      Chào bạn, hình như bạn đang cài scrapy trực tiếp vào system.
      Bạn thử với command: sudo pip install scrapy
      để cài đặt scrapy với quyền admin, hoặc bạn có thể tạo virtualenv để cài đặt với command:
      pip install scrapy

  2. Trả lời

    Trần Cương

    21 Tháng 10, 2018

    Một fan của python. Rất rất cảm ơn anh đã tạo ra một trang web rất bổ ích. Mong anh ra nhiều bài hay nữa nhé.

  3. Trả lời

    To Cun

    20 Tháng 12, 2018

    Ad cho mình hỏi Khi chạy lệnh scrapy crawl xosokienthiet -o items.json thì bị lỗi
    KeyError: 'XsktItem does not support field: xs_info'
    Lỗi này là bị làm sao ah?

    • Trả lời

      Anh Vũ Từ

      09 Tháng 1, 2019

      Chào bạn, bạn đã tạo các field cho XsktItem chưa?

      class XsktItem(scrapy.Item):
      # define the fields for your item here like:
      # name = scrapy.Field()
      sx_info = scrapy.Field()
      sx_data = scrapy.Field()

    • Trả lời

      Nguyễn Trần Tuấn Anh

      28 Tháng 3, 2019

      sx_info = scrapy.Field()
      sx_data = scrapy.Field()
      Sửa thành
      xs_info = scrapy.Field()
      xs_data = scrapy.Field()
      nha

      • Trả lời

        Anh Vũ Từ

        28 Tháng 3, 2019

        Cám ơn bạn đã nhắc, lỗi do mình type lại khi viết bài chứ không copy, trên source github vẫn đúng. Mình đã cập nhật lại bài

  4. Trả lời

    Tai Pham

    22 Tháng 1, 2019

    Mình đã tạo các field cho XsktItem rồi, nhưng khi chạy lệnh
    scrapy crawl xosokienthiet -o items.json
    vẫn bị lỗi ấy, mong ad giúp mình với


    2019-01-22 11:38:51 [scrapy.core.scraper] ERROR: Spider error processing <GET https://xskt.com.vn/ket-qua-xo-so-theo-ngay/mien-nam-xsmn/29-5-2018.html> (referer: None)
    Traceback (most recent call last):
    File "/usr/local/lib/python3.7/site-packages/scrapy/utils/defer.py", line 102, in iter_errback
    yield next(it)
    File "/usr/local/lib/python3.7/site-packages/scrapy/spidermiddlewares/offsite.py", line 30, in process_spider_output
    for x in result:
    File "/usr/local/lib/python3.7/site-packages/scrapy/spidermiddlewares/referer.py", line 339, in <genexpr>
    return (_set_referer(r) for r in result or ())
    File "/usr/local/lib/python3.7/site-packages/scrapy/spidermiddlewares/urllength.py", line 37, in <genexpr>
    return (r for r in result or () if _filter(r))
    File "/usr/local/lib/python3.7/site-packages/scrapy/spidermiddlewares/depth.py", line 58, in <genexpr>
    return (r for r in result or () if _filter(r))
    File "/Users/taipham/xskt/xskt/spiders/xosokienthiet.py", line 41, in parse
    self.year_to_scrap
    File "/usr/local/lib/python3.7/site-packages/scrapy/item.py", line 66, in __setitem__
    (self.__class__.__name__, key))
    KeyError: 'XsktItem does not support field: xs_info'

    • Trả lời

      Anh Vũ Từ

      22 Tháng 1, 2019

      Có thể do bạn đang dùng python 3.7, bạn downgrade xuống 3.6 test lại nha.

    • Trả lời

      Anh Vũ Từ

      28 Tháng 3, 2019

      Do mình đánh sai khi viết bài bạn sửa lại theo cách của bạn Nguyễn Trần Tuấn Anh nha

      Bạn mở file items.py lên và sửa như sau:
      sx_info = scrapy.Field()
      sx_data = scrapy.Field()
      Sửa thành
      xs_info = scrapy.Field()
      xs_data = scrapy.Field()

  5. Trả lời

    Nam

    15 Tháng 2, 2019

    Anh ơi, file items.py có phải là xs_info và xs_data phải không ạ?

  6. Trả lời

    Kien

    09 Tháng 5, 2019

    nhờ anh giúp xem lỗi này đang xài python 3.7.2 trên visual studio code

    scrapy startproject xskt
    scrapy : The term 'scrapy' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was
    included, verify that the path is correct and try again.
    At line:1 char:1
    + scrapy startproject xskt
    + ~~~~~~
    + CategoryInfo : ObjectNotFound: (scrapy:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

    • Trả lời

      Anh Vũ Từ

      18 Tháng 5, 2019

      em check thử xem python đã được add vào environment path chưa

  7. Trả lời

    Anything

    31 Tháng 8, 2019

    Unknown command : crawl sửa thế nào anh ạ

Nhận xét mới

bắt buộc

yu.kusanagi
Từ Anh Vũ
Hồ Chí Minh, Việt Nam

Xin chào, tôi tên Từ Anh Vũ và là 1 free lancer developer và ngôn ngữ code yêu thích của tôi là Python và PHP. Công việc chủ yếu là viết các module cho magento, magento2, wordpress, django, flask và các framework khác
Nếu bạn muốn trao đổi với tôi hoặc muốn thuê tôi làm việc cho dự án của bạn, hãy liên hệ với tôi

ĐĂNG KÝ NHẬN BÀI MỚI

Tweets gần đây
Tác giả
Feeds
RSS / Atom
-->

Đăng ký nhận bài viết mới tại hocpython.com?

Hãy đăng ký nhận bài viết mới tại hocpython.com để:

  • Không bỏ lỡ các bài tutorials mới tại hocpython.com!
  • Cập nhật các công nghệ mới trong python!

Chỉ cần điền email và họ tên của bạn và nhấn Đăng ký nhận tin!