Hướng dẫn Crawler Data trong WordPress

Trong lĩnh vực lập trình web, thuật ngữ Crawler Data đã không còn xa lạ. Tuy nhiên, để làm việc được với nó đòi hỏi bạn cần có kiến thức về lập trình.

Vậy Crawler Data là gì? Làm sao để Crawler Data trong WordPress? Bài viết này tôi sẽ chia sẻ chi tiết về vấn đề này.

Hình ảnh thuộc sở hữu của trang web qnet88.com
Hướng dẫn Crawler Data trong WordPress

Crawler Data là gì?

Crawler Data chính là thu thập dữ liệu từ một trang web bất kì, hoặc chỉ định trước rồi phân tích cú pháp mã nguồn HTML để đọc dữ liệu và bóc tách thông tin dữ liệu theo yêu cầu mà người dùng đặt ra.

Crawler Data bằng những cách nào?

Bạn có thể sử dụng bất kỳ ngôn ngữ lập trình nào để Crawler Data. Mỗi ngôn ngữ sẽ có ưu điểm và nhược điểm riêng. Bài viết này tôi đề cập đến WordPress nên tôi sẽ sử dụng PHP để thực hiện công việc Crawler.

Với ngôn ngữ lập trình PHP, có những cách sau:

  • Sử dụng thư viện Simple HTML Dom
  • Sử dụng CURL kết hợp với Regular Expression để bóc tách
  • Kết hợp CURL và Simple HTML Dom (Trong trường hợp Simple HTML Dom không lấy được nội dung hoặc Nội dung được Render bằng Ajax)

Việc bóc tách bằng Regular Expression (Biểu thức chính quy) khá phức tạp cho bạn nào chưa có kinh nghiệm viết biểu thức chính quy.

Crawler Data có cần sử dụng phần mềm không?

Nếu nội dung được Render bằng Ajax thì bạn phải tìm được Request Ajax (Sử dụng tab Network của Chrome), sau đó test Request đó bằng phần mềm Postman để xem Request đó có trả về nội dung cần lấy không?

Vậy bạn cần chuẩn bị phần mềm Postman để thực hiện công việc này: https://www.postman.com

Hướng dẫn sử dụng SIMPLE HTML DOM

Simple HTML Dom là một thư viện chuyên được sử dụng để bóc tách dữ liệu. Trang chủ thư viện: https://simplehtmldom.sourceforge.io

Các bước thực hiện:

Bước 01: Tải thư viện Simple HTML Dom và require vào dự án cần làm

Download thư viện tại đây: https://sourceforge.net/projects/simplehtmldom

Giải nén và require file simple_html_dom.php vào project cần làm thông qua hàm require_once

<?php
require_once 'simple_html_dom.php';

Bước 02: Xác định website cần lấy dữ liệu

Bạn cần xác định website cần lấy dữ liệu, sau đó xác định thành phần cần lấy trên website đó. Hãy trả lời các câu hỏi sau:

  • Bạn cần lấy một nội dung hay nhiều nội dung? (Nếu một nội dung thì copy cho nhanh)
  • Bạn cần lấy nhiều nội dung trong một chuyên mục hay nhiều chuyên mục?
  • Trong trường hợp chuyên mục có phân trang, bạn muốn lấy tất cả các trang hay chỉ lấy trang đầu tiên?
  • Bạn cần xử lý dữ liệu sau khi lấy về không? (Xoá ảnh, xoá liên kết, xoá thành phần không thiết)

Bước 03: Viết code bóc tách dữ liệu

Trước tiên, bạn hãy dùng ham file_get_html() để đọc nội dung trang cần lấy.

Giả sử tôi cần lấy tiêu đề, nội dung, link ảnh các bài viết trong chuyên mục WordPress trên website hoangan.net. Tôi sẽ viết như sau:

$html_content = file_get_html('https://hoangan.net/wordpress');

Tiếp theo, bạn thử echo biến $html_content xem có hiện nội dung chuyên mục của web gốc ra không? Nếu có hiện là bạn đã thành công bước đầu.

Tiếp theo, bạn cần phân tích thành phần HTML cần lấy. Trong trường hợp này tôi cần lấy ra link của tất cả bài viết chuyên mục, sau đó tôi sẽ đọc từng bài và lấy ra tiêu đềnội dung. Còn ảnh đại diện tôi sẽ lấy ở trang chuyên mục (Vì trong trang chi tiết không có ảnh đại diện)

Như vậy, tôi cần phải tìm được thành phần HTML lặp trong trang chuyên mục.

Hình ảnh thuộc sở hữu của trang web qnet88.com

Nhìn vào hình bạn sẽ thấy thẻ <div class="cm-col-lg-6 cm-col-md-6 cm-col-12"> đang lặp bao quanh từng bài viết.

Như vậy ta sẽ viết code như sau:

$list_post = $html_content->find('.list_entry .cm-col-lg-6');

Bạn sẽ thấy nó giống như Selector trong CSS. Tôi phải đưa .list_entry vào vì có thể trong trang sẽ có nhiều chỗ dùng .cm-col-lg-6

Bây giờ, bạn sử dụng vòng lặp để đọc từng bài viết, sau đó ta lại bóc tách từng bài.

if (!empty($list_post)){
  foreach ($list_post as $post){
     //Bóc tách từng post
   }
}

Hình ảnh thuộc sở hữu của trang web qnet88.com

Phân tích từng bài viết, bạn sẽ thấy link từng bài viết sẽ nằm trong cặp thẻ h2. Việc bây giờ tôi sẽ phải lấy nội dung của thuộc tính href

Code như sau:

if (!empty($list_post)){
  foreach ($list_post as $post){
    	$post_link = $post->find('.post_title h2 a', 0)->href;
   }
}

Bạn thấy phương thức find có 2 tham số:

  • Tham số đầu tiên: Selector (Giống như CSS)
  • Tham số thứ hai: Index (Số thứ tự cần lấy, bắt đầu từ 0). Kể cả chỉ có 1 HTML bạn cũng phải truyền index = 0

Các thuộc tính của phương thức find():

  • Các thuộc tính của thẻ HTML (Ví dụ: href, src, id, class)
  • plaintext: Lấy nội dung của một thẻ HTML (Chỉ lấy text)
  • innertext: Lấy nội dung của một thẻ HTML (Lấy cả HTML)
  • outertext: Lấy cả nội dung và thẻ đang Selector

Tiếp theo, tôi sẽ lấy link ảnh đại diện

Hình ảnh thuộc sở hữu của trang web qnet88.com

Đến đây, bạn đã biết cách lấy rồi đúng không? Tham khảo code của tôi nhé

if (!empty($list_post)){
  foreach ($list_post as $post){
    	$post_link = $post->find('.post_title h2 a', 0)->href;
    	$thumb = $post->find('.post_thumb img')->src;
   }
}

Tiếp theo, tôi sẽ lấy tiêu đề, nội dung trong trang chi tiết bài viết. Code như sau:

if (!empty($list_post)){
  foreach ($list_post as $post){
    	$post_link = $post->find('.post_title h2 a', 0)->href;
    	$thumb = $post->find('.post_thumb img')->src;

    	//Post Detail
    	$html_detail = file_get_html($post_link);
    	$title = $html_detail->find('.content-entry .the_title h1', 0)->plaintext;
    	$content = $html_detail->find('.content-entry .the_content', 0)->innertext;
   }
}

Như vậy tôi đã lấy được đủ thông tin rồi. Nếu bạn muốn xử lý dữ liệu hãy dùng biểu thức chính quy để xử lý.

Giờ làm gì với dữ liệu này là việc của bạn.

Crawler Data trong WordPress như thế nào?

Bạn đã Crawler Data được bằng Simple HTML Dom, thì bạn chỉ cần đưa vào WordPress là được. Sau đây, tôi sẽ hướng dẫn bạn áp dụng với WordPress.

Đầu tiên, bạn hãy sao chép file simple_html_dom.php vào thư mục theme bạn đang sử dụng.

Mở file functions.php và chèn đoạn code sau vào đầu file (Sau <?php)

require_once 'simple_html_dom.php';

Tiếp theo, tôi sẽ sử dụng hook init kết hợp với biến $_GET để tạo link thực hiện crawler. Khi tôi load link đó sẽ thực viện crawler và chèn nội dung vào bài viết WordPress.

function add_crawl_data(){
	if (!is_admin() && isset($_GET['act']) && $_GET['act']=='crawl'){
		//Code Crawler
                die();
	}
}

add_action('init', 'add_crawl_data');

Như vậy, link chạy crawler sẽ có dạng như sau: http://tenmiencuaban/?act=crawl

Tiếp theo, tôi đưa code crawler vào:

function add_crawl_data(){
	if (!is_admin() && isset($_GET['act']) && $_GET['act']=='crawl'){
		//Code Crawler
		$html_content = file_get_html('https://hoangan.net/wordpress');

		if (!empty($list_post)){
		  foreach ($list_post as $post){
		    	$post_link = $post->find('.post_title h2 a', 0)->href;
		    	$thumb = $post->find('.post_thumb img')->src;

		    	//Post Detail
		    	$html_detail = file_get_html($post_link);
		    	$title = $html_detail->find('.content-entry .the_title h1', 0)->plaintext;
		    	$content = $html_detail->find('.content-entry .the_content', 0)->innertext;
		   }
		}
		die();
	}
}

add_action('init', 'add_crawl_data');

Sau khi lấy được dữ liệu rồi, tôi tiến hành việc insert vào WordPress. Trước khi insert, tôi cần phải kiểm tra xem bài viết đó có tồn tại trong website chưa?

Sử dụng hàm post_exists bạn nhé. Nhưng để hàm này hoạt động, bạn cần chèn đoạn code sau trước khi gọi nó:

if ( ! function_exists( 'post_exists' ) ) {
  require_once( ABSPATH . 'wp-admin/includes/post.php' );
}

Tiếp theo, tôi sử dụng hàm wp_insert_post để chèn vào WordPress

$args = array(
	'post_type' => 'post',
	'post_status' => 'publish',
	'post_title' => $title,
	'post_content' => $content
);

$post_id = wp_insert_post($args);

Nếu biến $post_id trả về số nguyên dương thì vài viết đã insert thành công.

Tiếp theo, tôi sẽ thực hiện việc set chuyên mục cho bài viết vừa insert. Tôi sẽ sử dụng hàm wp_set_post_terms

if ($post_id>0){
	wp_set_post_terms($post_id, 41, 'category');
}

Trong đó có 3 tham số:

  • Tham số đầu tiên: Post ID
  • Tham số thứ hai: ID của chuyên mục
  • Tham số thứ ba: Slug của Taxonomy (Chuyên mục trong WordPress có slug là: category)

Tiếp theo, tôi cần set ảnh đại diện cho bài viết. Tuy nhiên, WordPress không cho phép sử dụng link ảnh ngoài để set ảnh đại diện. Tôi sẽ phải tải ảnh về thư viện của WordPress.

Trước đây tôi có một bài hướng dẫn làm việc này. Mời bạn đọc qua bài viết Lấy Link Ảnh Ngoài Làm Thumbnail Cho WordPress

Trong bài đó, tôi đã chia sẻ sẵn một hàm. Bạn copy nội dung hàm đó bỏ vào file functions.php

function Generate_Featured_Image( $image_url, $post_id  ){
    $upload_dir = wp_upload_dir();
    $image_data = file_get_contents($image_url);
    $filename = basename($image_url);
    if(wp_mkdir_p($upload_dir['path']))     $file = $upload_dir['path'] . '/' . $filename;
    else                                    $file = $upload_dir['basedir'] . '/' . $filename;
    file_put_contents($file, $image_data);
 
    $wp_filetype = wp_check_filetype($filename, null );
    $attachment = array(
        'post_mime_type' => $wp_filetype['type'],
        'post_title' => sanitize_file_name($filename),
        'post_content' => '',
        'post_status' => 'inherit'
    );
    $attach_id = wp_insert_attachment( $attachment, $file, $post_id );
    require_once(ABSPATH . 'wp-admin/includes/image.php');
    $attach_data = wp_generate_attachment_metadata( $attach_id, $file );
    $res1= wp_update_attachment_metadata( $attach_id, $attach_data );
    $res2= set_post_thumbnail( $post_id, $attach_id );
}

Tiếp theo, bạn thực hiện set thumbnail như sau:

if ($post_id>0){
	wp_set_post_terms($post_id, 41, 'category');
	Generate_Featured_Image($thumb, $post_id);
}

Có vẻ ok rồi đây, giờ ghép code lại như sau:

function add_crawl_data(){
	if (!is_admin() && isset($_GET['act']) && $_GET['act']=='crawl'){
		//Code Crawler
		$html_content = file_get_html('https://hoangan.net/wordpress');

		if ( ! function_exists( 'post_exists' ) ) {
		    require_once( ABSPATH . 'wp-admin/includes/post.php' );
		}

		if (!empty($list_post)){
		  foreach ($list_post as $post){
		    	$post_link = $post->find('.post_title h2 a', 0)->href;
		    	$thumb = $post->find('.post_thumb img')->src;

		    	//Post Detail
		    	$html_detail = file_get_html($post_link);
		    	$title = $html_detail->find('.content-entry .the_title h1', 0)->plaintext;
		    	$content = $html_detail->find('.content-entry .the_content', 0)->innertext;

		    	if (post_exists($title)===0){
					$args = array(
						'post_type' => 'post',
						'post_status' => 'publish',
						'post_title' => $title,
						'post_content' => $content
					);

					$post_id = wp_insert_post($args);

					if ($post_id>0){
						wp_set_post_terms($post_id, 41, 'category');
						Generate_Featured_Image($thumb, $post_id);
					}
				}
		   }
		}
		die();
	}
}

add_action('init', 'add_crawl_data');

Cuối cùng, bạn thử chạy link crawl để xem kết quả. Thời gian chạy có thể hơi lâu do số lượng bài viết trong chuyên mục. Nếu bị timeout, bạn tải lại nhé.

Nếu bạn muốn lấy dữ liệu tự động, cứ có bài mới thì sẽ tự lấy về. Hãy đưa link chạy vào cronjob.

Nếu bạn muốn crawler các phân trang nữa thì bạn đưa đoạn code crawler đã làm ở trên vào một vòng lặp các trang.

Đến đây tôi nghĩ bạn tự làm được rồi.

Kết thúc

Trên đây, tôi đã hướng dẫn cơ bản cho các bạn cách thức Crawler Data trong WordPress sử dụng thư viện Simple HTML Dom

Nó không khó, nhưng đòi hỏi bạn phải có kiến thức về lập trình. Bài sau, tôi sẽ viết về chủ đề Crawler nội dung Render bằng Ajax.

Nếu có bất kỳ câu hỏi nào hãy comment dưới bài viết này.

Nguồn : https://hoangan.net

Đánh giá post
[related_posts_by_tax posts_per_page="6" title="Bài liên quan" taxonomies="category,post_tag"]

4 bình luận về “Hướng dẫn Crawler Data trong WordPress

  1. IN cho biết:

    Ad cho em hỏi: website của em mới lập được mấy tháng nhưng khi kiểm tra trên google lại hiển thị mấy bài viết có chữ tiếng trung, click vào thì không truy cập được. nhiều người bảo là web bị nhiễm mã độc, e hỏi bên đặt hosting thì họ bảo ko phải, không biết là bị gì nữa
    web đây ạ inuvhanoi.com

Trả lời

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *

Hotline: 0974.0707.83(Zalo/Viber)