Trích xuất danh sách bài hát Karaoke 5 số bằng PHP

trong danh mục Miscellaneous, PHP, Web Programming

karaoke-songlist-banner

Tối qua tự nhiên có hứng thú làm cái công việc trích xuất danh sách bài hát Karaoke 5 số để lưu trữ nhằm phục vụ vào mục đích khác.
Nếu bạn nào có đi hát Karaoke (mình cũng khoái dzụ này lắm) thì cũng biết hiện nay các đầu Karaoke thường là của Arirang 5 số. Và vô đó muốn hát thì chọn số từ mấy cuốn songlist.

Tự nhiên thèm có 1 website để tra cứu cho nhanh hoặc tốt nhất là có hẳn 1 cái Database để tự mình triển khai, có thể dùng cho web, software cho máy tính, di động..đồng thời không muốn lệ thuộc vào các software khác (nghe nói cũng có cái soft nào đó rồi và có cả iphone app) nên đành nghiên cứu thử xem có thể “tự thân vận động” không!

Thế là sau 2 tiếng ngáp lên ngáp xuống (1h-3h sáng) vừa nghiên cứu vừa code thì cũng đã được như ý. Mình đã lấy được danh sách bài hát 5 số của Arirang, gồm có Danh sách tiếng việt (tới Vol 37) và tiếng anh. Nội dung bài viết này mình sẽ hướng dẫn các bạn(Programmer) làm sao có thể trích xuất được danh sách bài hát ra định dạng mà mình muốn, đồng thời cũng chia sẽ tới các bạn luôn Database MySQL mà mình đã trích xuất được coi như 1 món quà đầu năm dành cho các Programmer.

Nếu muốn download thì có thể bỏ qua phần hướng dẫn này và kéo xuống phần download để tải về Database (MySQL)file HTML (chứa danh sách bài hát tiếng Việt + tiếng Anh) để dùng trình duyệt tra cứu cũng được ^^. Còn nếu ai muốn export dạng nào khác thì có thể nói mình, giúp được mình sẽ giúp. Khi sử dụng Database thì các bạn có thể ghi chút nguồn gốc là từ bloghoctap thì mình vui rồi.

A.Hướng dẫn trích xuất danh sách bài hát Karaoke 5 số

Không dành cho người yếu tim và người mới bắt đầu code :D!

Mình sẽ hướng dẫn các bạn 1 số bước quan trong mà mình đã thực hiện để trích xuất được danh sách bài hát Karaoke 5 số. Nói đến quá trình này trước tiên cũng nhắc cho các bạn biến là đối với danh sách tiếng Việt và tiếng Anh thì mình sẽ làm hầu như là khác nhau. Cách Convert, Export, Viết Script PHP. Ở đây mình tất nhiên sẽ không hướng dẫn chi tiết các đoạn script PHP của mình mà mình chỉ share một số đoạn quan trọng mà thôi, hy vọng các bạn làm theo các bước mình chỉ để thực tập. Và cũng nói với các bạn biết là bước code PHP rất đơn giản, khó là công đoạn đầu chuẩn bị đầu vào cho file PHP xử lý thôi. Nào bắt đầu!

Đầu tiên bạn phải cần có File chứa danh sách bài hát để bắt đầu “thực tập”, vì nó ở định dạng PDF nên mình mới phải vất vả tùm lum việc để extract nó ra Database thành công. Bạn chỉ cần vào địa chỉ http://arirang.com.vn/?page=static_pages&view=99&l=2 để tải về file PDF mà mình cần tiến hành export. Vì thực tế mình biết là chúng ta chỉ cần quan tâm List nhạc ViệtList nhạc tiếng Anh (Chỉ cần file phần “Danh mục bài hát tiếng Anh dành cho 3600 HI“, mấy cái khác hình như không phải vì không phải bắt đầu bằng số 4 ^^). Download về và tiếp tục nhé.

karaoke-songlist-download

Cái khó nhất của project này là làm sao bạn convert file PDF sang một định dạng nào đó mà có pattern (có khuôn mẫu giống nhau đối với các bài hát) để từ đó các bạn có thể dùng các ngôn ngữ lập trình mà các bạn thông thạo (đối với mình là PHP) tiến hành đọc chuỗi, tách và tìm đúng thông tin cần extract là sẽ thành công.

1. Trích xuất bài hát tiếng Việt:

Tới thời điểm bài viết này thì đã có tới Vol 37 (Vol này chả biết hát bài nào hết trơn ^^) nên nhiệm vụ của chúng ta sẽ là extract được tất cả bài hát từ Vol 1 – 37.
Bước 1:Convert từ PDF –> TXT
Vì định dạng ban đầu là PDF nên không cách chi PHP đọc được vì nó không có pattern nên phải tiến hành biến nó thành file text để PHP có thể đọc được. Lúc đầu tưởng công việc cực khổ lắm ai dè giải quyết rất đơn giản ^^. Nếu bạn đang sử dụng Adobe Reader 9 thì có thể vào File >> Save as text là đã có file TXT có pattern rồi.
karaoke-songlist-pdf-to-text

Sau khi convert bạn sẽ có File TXT có nội dung giống như sau:
karaoke-songlist-pdf-to-text-result

Bạn sẽ thực hiện bước export ra text đối với các file PDF chứa vol 1-35, vol36,vol37, sau đó copy tất cả vào 1 file để dễ làm việc. Như vậy là bạn đã có toàn bộ bài hát từ Vol1-37 ở định dạng text.

Bước 2: Như bạn thấy thì file mình convert ra sẽ bị lỗi dấu tiếng việt bởi vì nó đang được encoding VNI. Bạn cần phải chuyển nó sang Unicode trước khi chuyển giao qua bước cuối cùng. Để chuyển thì cực kỳ đơn giản, sử dụng công cụ convert của Unikey chỉ vài giây là xong. Mở file text ở bước 1 bằng Notepad, đầu tiên bạn Cut toàn bộ nội dung text, sử dụng Unikey Toolkit(nằm ở menu công cụ của Unikey) và thiết lập như hình mình chụp dưới đây, sau đó nhấn chuyển mã và chương trình sẽ báo thành công. Bạn quay lại Notepad và Paste vô thì sẽ thấy tiếng Việt thôi. Sau đó Save as với định dạng Unicode nha.
karaoke-songlist-convert-unicode-toolkit

karaoke-songlist-convert-unicode-notepad

Bước 3: tới đây coi như bạn đã có File text có tiếng việt và có pattern để có thể sử dụng ngôn ngữ lập trình mà mình quen thuộc và đọc ra thôi. Mình cũng chia sẽ với ai dự định Coding. Nếu các bạn để ý, File của chúng ta sẽ có dạng mỗi thông tin nằm trên 1 hàng, và một bài hát bắt đầu bằng hàng có 5 chữ số, hàng tiếp theo là tên bài hát, hàng tiếp theo nữa là 1 đoạn lyric và có thể 1,2..hàng tiếp theo là tác giả. Biết được Pattern thì các bạn có thể coding để lấy thông tin mà mình muốn nhé. Sau khi đọc được thì các bạn có thể lưu vào database hay làm gì đó thì tùy.Vậy là xong tiếng Việt.
Dưới đây là 1 phần trong đoạn script của mình đã viết, nhiệm vụ của nó là parse 1 bài hát và lấy các thông tin từ bài hát đó (code,title,lyric,composer).

/**
* Ham parsing data tu 1 bai hat
* 
* @param string $song
*/
function parseSong($song)
{
	$songData = array('code' => '', 'title' => '', 'lyric' => '', 'composer' => '');
	
	$songPart = split("\n", trim($song));
	$songRawData = array();
	foreach($songPart as $part)
	{
		$part = trim($part);
		if(strlen($part) > 0)
			$songRawData[] = $part;
	}
	
	if(is_numeric($songRawData[0]) && strlen($songRawData[0]) == 5)
	{
		$songData['code'] = $songRawData[0];
		$songData['title'] = $songRawData[1];
		$songData['lyric'] = $songRawData[2];
		
		for($i = 3; $i < count($songRawData); $i++)
		{
			if(strlen($songRawData[$i]) > 5 && strpos($songRawData[$i], 'www') === false && $songRawData[$i] != $songRawData[$i-1])
				$songData['composer'] .= $songRawData[$i] . "\n";
			else
				break;
		}
		$songData['composer'] = trim($songData['composer']);
	}
	return $songData;
}

2. Trích xuất bài hát tiếng Anh:

Bước 1:Thật sự lúc đầu tưởng làm xong tiếng Việt thì tiếng Anh cũng dễ vì cứ nghĩ nó giống nhau, nhưng mình đã sai lầm. Mọi người đi hát Karaoke cũng thấy cái songlist của tiếng anh nó khác mà đúng không, mình thử lập lại bước 1 ở trên bằng cách dùng Adobe Reader 9 để export ra txt nhưng kết quả đã khiến mình thất vọng.
karaoke-songlist-pdf-to-text-result-english

Nhìn cái file TXT mà đau cả lòng vì nó không có pattern để parsing bài hát, chỉ biết là mỗi bài trên 1 dòng, nhưng trong 1 dòng thì lại khó mà biết đâu là Title, đâu là Singer :(. Thế là tìm giải pháp khác.

Mình nghĩ tới phải export cái này qua excel thì may ra vì excel gần với PHP hơn. Search thử thì ra software “PDF to Excel Converter 2.2”, hy vọng nó giúp mình. Đây là 1 shareware, tuy nhiên xài thử thì nó export ra được đầy đủ file XLS, vậy là xong bước 1.
PDF to Excel Converter screenshot

karaoke-songlist-english-xls

Bước 2: Sau khi có file XLS mở ra và xóa các dòng và cột không cần thiết đi và export sang CSV (PHP parsing CSV sướng hơn chứ ^^) thì thấy có pattern rồi thế là tha hồ lấy PHP mà parsing. Nhưng…:D, cái bạn export từ file excel ra CSV chỉ là export mới có 1 sheet, nhưng file excel của mình có tới 74 Sheet(do file PDF có 74 trang), thế là lại bắt đầu 1 bài toán mới, bài toán làm sao merge tất cả sheet và export ra 1 file duy nhất. Để giải quyết bài toán nan giải này có 2 cách:
+ Cách đầu tiên nhanh lẹ gọn là sử dụng 1 cái software tên là “Merge Excel Sheets v2.9“, cái này phải mua mới xài được, còn bạn nào giỏi thì có thể xài “thuốc”, không lẽ nào mình lại đưa “thuốc” lên đây, như thế không tốt. Dùng software này nó sẽ merge 1 file có nhiều worksheet lại thành 1 file chỉ có 1 worksheet và chứa toàn bộ các worksheet của file excel gốc. Sau khi có file mới này rồi thì có thể export ra CSV bình thường như đầu tiên thì sẽ có tất cả dữ liệu rồi.
+ Cách này sử dụng hơi “technical” một tý nhưng được cái học hỏi được nhiều mà lại miễn phí, đó là sử dụng cơ chế Macro của Excel để hỗ trợ mình. Bạn cần tạo 2 Macro, 1 Macro cho phép export tất cả worksheet thành mỗi file CSV riêng và đặt ở đâu đó (mình mặc định là ở ổ C, bạn có thể nghiên cứu Macro để thiết đặt lại) và 1 Macro cho Merge tất cả file CSV vừa export ra thành 1 file CSV duy nhất. Mình chỉ sơ qua cách tạo 1 Macro: Nhấn Alt+F11 nó sẽ mở cửa sổ Visual Basic, vào Insert >> Module và copy nội dung của Macro. Bạn thực hiện việc tạo này cho 2 Macro có nội dung dưới đây:

.Macro (ExportSheetToCSV) export các worksheet của Excel thành các file CSV tương ứng:

Option Explicit
Sub ExportSheetToCSV()

Dim newWks As Worksheet
Dim wks As Worksheet

For Each wks In ActiveWorkbook.Worksheets
wks.Copy 'to a new workbook
Set newWks = ActiveSheet
With newWks
.SaveAs Filename:="C:\" & wks.Name, FileFormat:=xlCSV
.Parent.Close savechanges:=False
End With
Next wks

MsgBox "done with: " & ActiveWorkbook.Name

End Sub

.Macro (Merge_CSV_Files) merge tất cả file CSV trong 1 thư mục (chương trình sẽ hỏi bạn thư mục nào) thành 1 file CSV và đặt vào My Document

Declare Function OpenProcess Lib "kernel32" _
                             (ByVal dwDesiredAccess As Long, _
                              ByVal bInheritHandle As Long, _
                              ByVal dwProcessId As Long) As Long

Declare Function GetExitCodeProcess Lib "kernel32" _
                                    (ByVal hProcess As Long, _
                                     lpExitCode As Long) As Long

Public Const PROCESS_QUERY_INFORMATION = &H400
Public Const STILL_ACTIVE = &H103


Public Sub ShellAndWait(ByVal PathName As String, Optional WindowState)
    Dim hProg As Long
    Dim hProcess As Long, ExitCode As Long
    'fill in the missing parameter and execute the program
    If IsMissing(WindowState) Then WindowState = 1
    hProg = Shell(PathName, WindowState)
    'hProg is a "process ID under Win32. To get the process handle:
    hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, False, hProg)
    Do
        'populate Exitcode variable
        GetExitCodeProcess hProcess, ExitCode
        DoEvents
    Loop While ExitCode = STILL_ACTIVE
End Sub


Sub Merge_CSV_Files()
    Dim BatFileName As String
    Dim TXTFileName As String
    Dim XLSFileName As String
    Dim FileExtStr As String
    Dim FileFormatNum As Long
    Dim DefPath As String
    Dim Wb As Workbook
    Dim oApp As Object
    Dim oFolder
    Dim foldername

    'Create two temporary file names
    BatFileName = Environ("Temp") & _
            "\CollectCSVData" & Format(Now, "dd-mm-yy-h-mm-ss") & ".bat"
    TXTFileName = Environ("Temp") & _
            "\AllCSV" & Format(Now, "dd-mm-yy-h-mm-ss") & ".txt"

    'Folder where you want to save the Excel file
    DefPath = Application.DefaultFilePath
    If Right(DefPath, 1) <> "\" Then
        DefPath = DefPath & "\"
    End If

    'Set the extension and file format
    If Val(Application.Version) < 12 Then
        'You use Excel 97-2003
        FileExtStr = ".xls": FileFormatNum = -4143
    Else
        'You use Excel 2007
        FileExtStr = ".xlsx": FileFormatNum = 51
        'If you want to save as xls(97-2003 format) in 2007 use
        'FileExtStr = ".xls": FileFormatNum = 56
    End If

    'Name of the Excel file with a date/time stamp
    XLSFileName = DefPath & "MasterCSV " & _
    Format(Now, "dd-mmm-yyyy h-mm-ss") & FileExtStr

    'Browse to the folder with CSV files
    Set oApp = CreateObject("Shell.Application")
    Set oFolder = oApp.BrowseForFolder(0, "Select folder with CSV files", 512)
    If Not oFolder Is Nothing Then
        foldername = oFolder.Self.Path
        If Right(foldername, 1) <> "\" Then
            foldername = foldername & "\"
        End If

        'Create the bat file
        Open BatFileName For Output As #1
        Print #1, "Copy " & Chr(34) & foldername & "*.csv" _
        & Chr(34) & " " & TXTFileName
        Close #1

        'Run the Bat file to collect all data from the CSV files into a TXT file
        ShellAndWait BatFileName, 0
        If Dir(TXTFileName) = "" Then
            MsgBox "There are no csv files in this folder"
            Kill BatFileName
            Exit Sub
        End If

        'Open the TXT file in Excel
        Application.ScreenUpdating = False
        Workbooks.OpenText Filename:=TXTFileName, Origin:=xlWindows, StartRow _
        :=1, DataType:=xlDelimited, TextQualifier:=xlDoubleQuote, _
        ConsecutiveDelimiter:=False, Tab:=False, Semicolon:=False, Comma:=True, _
        Space:=False, Other:=False

        'Save text file as a Excel file
        Set Wb = ActiveWorkbook
        Application.DisplayAlerts = False
        Wb.SaveAs Filename:=XLSFileName, FileFormat:=FileFormatNum
        Application.DisplayAlerts = True

        Wb.Close savechanges:=False
        MsgBox "You find the Excel file here: " & vbNewLine & XLSFileName

        'Delete the bat and text file you temporary used
        Kill BatFileName
        Kill TXTFileName

        Application.ScreenUpdating = True
    End If
End Sub

Bạn chạy lần lượt 2 Macro này (Nhấn Alt+F8 để mở cửa sổ macro, sau đó chọn lần lượt từng macro và Run) thì sẽ có được 1 File CSV chứa toàn bộ dữ liệu rồi, tiếp tục bước 3

Bước 3: Có được File CSV, xóa các dòng và cột không cần thiết, chỉ giữ lại 3 cột chính là Code, Title, Singer là đủ rồi và các dòng không chứa data cũng nên xóa luôn. Tới đây thì dễ hơn là parsing của tiếng Việt vì một là mình đọc file CSV, có pattern rất rõ ràng và mỗi bài hát lại nằm 1 hàng và bài hát chỉ có 3 nội dung: Code, Title, Singer. Dưới đây là đoạn code parsing 1 bài hát tiếng anh.

/**
* Ham parsing data tu 1 bai hat
* 
* @param mixed $song
*/
function parseSong($song)
{
	$songData = array('code' => '', 'title' => '', 'singer' => '');
	
	$songRawData = split(",", trim($song));
	
	if(is_numeric($songRawData[0]) && strlen($songRawData[0]) == 5)
	{
		$songData['code'] = $songRawData[0];
		$songData['title'] = $songRawData[1];
		$songData['singer'] = strtolower($songRawData[2]);
	}
	
	return $songData;
}

—————————
Như vậy là các bạn đã biết cách mình làm sao extract được thông tin các bài hát karaoke và lưu vào cơ sở dữ liệu. Bây giờ các bạn có thể tự mình thực tập thử đi, chỉ là 1 ứng dụng nho nhỏ nhưng mình đã học được rất nhiều kiến thức sau vụ này ^^.

B.Download:

1.MySQL Dump File: File Database MySQL chứa danh sách hơn 8000 bài hát và mã bài hát mà mình đã trích xuất và lưu lại, các bạn có thể tự do dùng để import vào cơ sở dữ liệu của mình để tăng cường chức năng cho website của các bạn. Hãy nhớ, tất cả vì người dùng website!
karaoke-songlist.sql.zip

2.HTML File: Nếu bạn không phải Programmer, có thể download file ZIP này về. Trong đây có 1 file chứa danh sách bài hát tiếng Việt (từ vol 1 – 37) và danh sách bài hát tiếng Anh (hơn 4000 bài). Bạn có thể dễ dàng tra cứu vì mình đã xếp theo Alphabet.
karaoke-songlist.zip

Please Give Credit Where Credit is Due, Thank you!

P.S: Thông qua ứng dụng nho nhỏ này thì các bạn cũng biết học PHP không phải chỉ để làm web và thực tế là nó hỗ trợ rất nhiều cho mình trong việc xử lý 1 số thao tác nào đó mà cần đến lập trình (và chủ yếu là về text), vì ngoài PHP mình chẳng “biết” ngôn ngữ nào khác. Hãy sử dụng PHP như một vũ khí lợi hại nhé mọi người. Enjoying PHP!

25 bình luận

  1. huân says:

    cái này trình php cao nhắm mới hiểu dc nè… T..T

  2. Sơn says:

    Nếu đã xài đến VBA for Excel, bạn cũng làm được code tương tự, ko cần dùng đến PHP, mất công cài server.

    Dù sao bạn hướng dẫn cũng rất chi tiết và nhiệt tình. Voted!

  3. hien says:

    anh co thể cho em source để học hỏi dc ko?

    • admin says:

      Từ từ rồi sẽ tới lúc đó thôi, anh đã đưa lên 2 function có nồng độ cao nhất trong cái source rồi đó :D, cố lên!

  4. loan le says:

    rat cam on ban ve nhung thong tin website ma ban da cho minh … minh been looking for vol 36 song list tren website biet bao lau ma k dc …. thank you rat la nhieu

  5. kimxoa says:

    anh oi! e muon lam nguyen cai web karaoke , nhung e ko biet bat dau tu dau, anh giup e duoc ko?
    kimxoa@vnec.us
    maivianh140285@yahoo.com
    Cam on

    • admin says:

      Hihi, quan trọng là em đã biết được cái gì về web chưa, anh thì sure là không có thời gian để chỉ từ A tới Z rồi :D. Chúc em may mắn!

  6. says:

    Không hiểu thuật toán mấy, PHP chả biết tí gì, tính làm bằng ngôn ngữ JAVA mà ko hiểu thuật toán. Bạn có thể nói rõ thêm được ko ^^

    • admin says:

      Kỹ thuật chính chỉ đơn giản là phân tích và trích xuất dữ liệu mà thôi, không có thuật toán gì phức tạp cả. Chủ yếu là nhận dạng ra pattern rồi tách.

  7. Hang says:

    Thank you em nhieu nhe, hom ray chi loay hoay tim list nhac de khi hat bam so cho de ma mai den hom nay moi tim duoc website nay. Het xay!

  8. chieftain2t says:

    anh ơi bữa nào rảnh, anh làm 1 loạt bài về các design pattern, đặc biệt là MVC pattern được ko anh

  9. Lê Quang Tín says:

    bạn mến!
    Tôi có một số diã nhạc Karaoke của Paris By Night, U Sing Along và Asia nhưng không biết làm sao để làm thành cơ sở dữ liệu theo dạng Excel hoặc Access ?
    cám ơn bạn trước !
    Lê Qung Tín

    • Khoa Nguyen says:

      @Lê Quang Tín,

      Chào bạn, bạn có thể dùng phần mềm “total commander” để xuất ra danh sách các tên file có trong thư mục sang file text Hoặc dùng lệnh DOS để xuất ra cây thư mục. Sau đó import vào CSDL giống bài viết.

  10. Dag Dag says:

    Hix minh ko fai dan IT nen ko bt gi het,neu ban cho minh code luon de nho thang ban lam giup di chu no luoi wa’ ko chiu suy ngi, may Vol sau con biet duong ma update,minh co the dung Excel de tao dc list nhung chi la list tieng viet ko co dau thoi

  11. Loan says:

    Loan không biết nhiều về viết code và lập trình nhưng cũng lướt qua chiêm ngưỡng công trình của bạn như người ta ngắm vẻ đẹp của viên kim cương vậy. Thật đáng khen 1 tấm lòng biết nghĩ tới cộng đồng. Chúc bạn luôn hạnh phúc và thành công

  12. chauthanhduc says:

    Anh ơi Em muốn trích xuất bài hát có nhạc từ đĩa 5 số ra máy tính để hát tại nhà không cần đi ra ngoài mấy điểm karaoke.A chỉ cách giúp e với.trên trang Zinf star nhạc hay quá mà không tải về được.A có thể chỉ E tải nhạc Karaoke không lời được không Anh

  13. Hien says:

    Doc caj nay that su chag hju j nhug e rat kham fuc ah. E con chag bjet lam s de hat duoc bang tieg ah nua co.dj hat cu theo dah sach of ngta co j hat nay.kho de so

  14. vo thai son says:

    thank anh co the viet them cai seach nua duoc ko anh

  15. ntct says:

    Cam on ban rat nhieu

  16. Kế toán says:

    Quá hay, tôi đang đi học hát karaoke đây, có lẽ cái này hữu ích lắm đây nha

  17. minhtri3229 says:

    bạn ơi theo mình thấy các bài hát tiếng Anh toàn bắt đầu bằng số 3, còn trong list của bạn thì toàn bắt đầu bằng số 4, khi bấm thử thì toàn ra nhạc Hoa. Bạn có biết tại sao không?

  18. Huy says:

    Hổi trước mình cũng lấy kiểu này, mà mình dịch ra file WORD rồi dùng C# + thư viện COM của .NET để đọc file word rồi lưu vào CSDL SQLite luôn

  19. Hạnh says:

    Thông tin bài viết rất là chi tiết hướng dẫn rất tận tình

Gởi bình luận