Hướng dẫn lấy tin từ động từ vnexpress, dân trí với Simple HTML Dom

Simple Html Dom là thư viện của Php giúp cho việc chúng ta có thể lấy các thuộc tính của các thẻ HTML trong 1 website. Chúng ta có thể lấy trực tiếp thông tin từ link web hoặc là từ 1 chuỗi, đồng thời ta có thể lấy về, và sửa đổi nội dung. Trong nội dung bài viết này mình sẽ hướng dẫn các bạn lấy tin từ trang tin tức vnexpress

1.Giới thiệu về PHP Simple HTML DOM Parser.

Hiểu đơn giản PHP Simple HTML DOM Parser là một thư viện có chức năng chính là trích xuất nội dung HTML từ một trang nào đó hoặc một đoạn HTML do do bạn tự cung cấp, nó hỗ trợ một số tính năng như:

  • Hỗ trợ bóc tách dữ liệu theo từng id, class, hoặc thẻ img, a, table, p...

  • Code ngắn, dễ học, dễ viết, dễ nhớ.

  • Khá nhẹ nhưng cũng rất hữu dụng.

Và còn gì nữa thì có lẽ sau khi bạn sử dụng thì tự rút ra ý kiến chứ mình bị hạn hán lời nên liệt kê được thế thôi. Nói chung để mà viết pr cho mình là mình có thể viết rất tốt nhưng viết pr về vấn đề khác mình không làm được nên mình xin kết thúc phần một tại đây.

2. Hướng dẫn tải về và sử dụng PHP Simple HTML DOM Parser.

 

Để tải về thư viện này bạn có thể nên trang chủ của nó tại địa chỉ sau http://simplehtmldom.sourceforge.net để down về. 

Sau khi đã có thư viện bạn copy file simple_html_dom.php vào dự án của mình và include nó vào file bạn muốn lấy dữ liệu để có thể sử dụng.

Tiếp theo chúng ta cùng điểm qua một số ví dụ về việc lấy dự liệu với thư viện này nhé.

Để đọc nội dung một file ta dùng như sau.

$html = file_get_html('link cần lấy');
echo $html;

Bây giờ bạn có thể chạy thử để xem kết quả. Rất đơn giản phải không nào chỉ cần một dòng code là bạn đã có thể echo ra toàn bộ nội dung HTML của một trang web rồi. Và chúng ta cùng tìm hiểu tiếp về cách bóc tách dữ liệu bằng thư viện này rồi nhé nhé.

Hiển thị tất cả các ảnh từ trang cần lấy sang web mình.

$html = file_get_html('http://www.google.com/');
foreach($html->find('img') as $element) {
       echo '<img src="'.$element->src.'" /><br>';
}

Lưu ý biến $html bạn chỉ cần khai báo một lần trong file nhé, và ở các ví dụ sau mình sẽ không gọi lại nó nữa mà mặc định là chúng ta đã khai báo nó rồi.

Hiển thị tất cả các link trong bài viết.

foreach($html->find('a') as $element) 
       echo $element->href . '<br>';

Lấy nội dung từ một id cụ thể.

$noidung = $html->find('#ten_id',0);

Ở đây bạn tôi có chèn số 0 vì trong html find sẽ trả về dữ liệu dạng mảng nếu bạn không truyền 0 vào thì bạn sẽ cần cho nó vào vòng lặp để hiển thị nội dung ra. Con tôi truyền số 0 vào đằng sau để chỉ lấy nội dung trong id đầu tiên.

Đối với class chúng ta cũng làm tương tự như sau, giả sử trong file cần lấy có 3 class tên là content. Và tôi muốn lấy nội dung từ class content thứ hai thị bạn làm như sau

$noidung = $html->find('.content',1);

Làm tương tự đối với các thẻ khác như tablep... Bạn lưu ý nhé nếu như không truyền số vào đằng sau kết quả trả về là mảng bạn sẽ cần foreach để show dữ liệu ra, còn nếu truyền số vào thì kết quả trả về là một chuỗi bạn echo bình thường trong quá trình sử dụng tùy từng mục đích mà bạn áp dụng cho phù hợp.

Tiếp theo chúng ta cùng tìm hiểu cách lấy phần tử trong một phần tử. Ví dụ cụ thể như sau trong nội dung file cần lần có một id tên là properties. Trong  properties có một đoạn text và một list danh sách thuộc tính nằm trong thẻ li. Bây giờ bạn cần lấy ra chuỗi li đấy để đưa vào dữ liệu hoặc xuất ra website thì làm như sau.

$thuoctinh =  $html->find('#properties',0)->find('li');
foreach ($thuoctinh as $e) {
    echo $e->plaintext
};

Mục đích của ví dụ này để bạn hiểu về cách dùng find lồng từ đó có thể áp dụng vào các ví dụ cụ thể.

Lưu ý: trong thư viện này có hỗ trợ ta ba cách đọc nội dung như sau

  • plaintext: Lấy nội dung (text) từ trang web
  • innertext: Chỉ lấy nội dung bên trong thẻ..
  • outertext: Lấy cả thẻ và nội dung bên trong.

Tiếp theo chúng ta cùng tìm hiểu về cách thay đổi nội dung của một trang trước khi xuất dữ liệu ra. Giả sử bạn có một trang trong đó có 3 table với những nội dung khác nhau, bạn muốn xóa table đầu tiên đi do có chứa thông tin không cần thiết thì làm như sau

$html->find('table',0)->outertext='';

Bạn nhớ nhé khi cần xóa một phần từ nào đó thi gán outertext = ''; như ở trên là đươc. Bạn làm tương tự với các class và id. Giờ trường hợp đặt ra là bạn xóa một đoạn text nằm trong một thẻ p nhưng oái oăm thay thẻ p này không có tên class hoặc id mà chỉ có style như sau <p style="font-family:宋体;'>. Đây là mình lấy từ ví dụ thực tế của mình khi làm dự án đầu tiên của mình.Lúc này ta cần làm như sau để loại text,

foreach ($html->find('p[style="font-family:宋体;"]') as $e) {          
    $e->outertext = '';
}

Như thế nếu bạn echo $html thì nội dung bạn chưa được sửa đổi đâu bạn cần thêm một bước này nữa trước khi xuất dữ liêụ ra.

$html ->load($html ->save());

Mục đích của dòng trên là để lưu lại nội dung $html đã được sửa đổi.

Trường hợp cuối cùng bạn cần lấy nội dung ở nhiều trang mình đã gặp trường hợp phải kết hợp mấy trang mới lấy hết thông tin. Một trang có nhiệm vụ show nội dung chi tiết sản phẩm, một trang show giá và một trang để lấy màu sắc của sản phẩm. Đối với trường hợp này bạn làm như sau.Sau khi bạn đã lấy được nội dung của trang thứ nhất và gán nó vào biến cụ thể rồi thì bạn hủy nội dung trong $html đi và tiếp tục get sang trang thứ hai. Phương pháp hủy như sau đây là phương pháp tôi demo và thấy nó chạy cũng không chắc là nó tối ưu nhưng mà dùng được.

$html->__destruct();
unset($html);
$html = null;

3. Thực hành lấy dữ liệu trang vnexpress.

 

Lấy danh sách các link bài viết để lưu vào cơ sở dữ liệu

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="content-style-type" content="text/css" />
</head>
<body>
<?php	
include "simple_html_dom.php"; 
$url					= 'https://vnexpress.net/tin-tuc/thoi-su';
$website_head     = 'https://vnexpress.net';
$html					= file_get_contents($url);

$html					= str_get_html($html);
$regular_group    = 'article[class=list_news]';
$regular_link     = 'h3[class=title_news] a';
$regular_title    = 'h3[class=title_news] a';

//Lay link cua tin
$arrLink    = array();
$arrTitle   = array();
$count   = 0;
foreach($html->find($regular_group) as $element_group){  
	//Lay duoc nhom noi dung cua 1 link
	//Lay link cua tin truoc
	$j=0; 
	foreach($element_group->find($regular_link) as $element){
		$arrLink[$j]		=	$element->href;	
		$j++;
	}	
   $lid_link	= $arrLink[0];	 
	if((substr($lid_link,0,7)	!=	"http://")and(substr($lid_link,0,8)	!=	"https://")){
		$lid_link	= 	$website_head . $lid_link;
	}
    echo "<br/>";
    echo $lid_link;
    echo "<br/>";
	//Lay xong link
   //Tieu de
   //Lay duoc nhom noi dung cua 1 link
	//Lay link cua tin truoc
	$j=0; 
	foreach($element_group->find($regular_title) as $element){
		$arrTitle[$j]		=	$element->plaintext;	
		$j++;
	}
   $title   = $arrTitle[0];
   echo $title;
   echo "<br/>";
   echo "<br/>";
   $count++;
}
echo $count;

?> 
</body>
</html>  

 

Lấy nội dung tin

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="content-style-type" content="text/css" />
</head>
<body>
<?php	
include "simple_html_dom.php"; 
$url			= 'https://vnexpress.net/tin-tuc/thoi-su/dam-truong-cong-an-xa-pho-bi-thu-bi-canh-cao-3833309.html';

$re_title_pa   	= 'section[class=sidebar_1]';
$re_title      	= 'h1';

$re_intro_pa     	= 'section[class=sidebar_1]';
$re_intro        	= 'h2[class=description]';

$re_avatar_pa   	= 'section[class=sidebar_1] article[class=content_detail]';
$re_avatar      	= 'img';

$re_description_pa   = 'section[class=sidebar_1]';
$re_description      = 'article[class=content_detail]';

$html	      =	file_get_contents($url);
$html			= 	str_get_html($html);  


$arr_title_pa     = $html->find($re_title_pa);
$element_title_pa = $arr_title_pa[0];
$arr_title        = $element_title_pa->find($re_title);
$element_title    = $arr_title[0];
$title            = $element_title->plaintext;
echo $title;
echo "<br/>";
echo "____________________intro_____________________________";
echo "<br/>";

$arr_intro_pa     = $html->find($re_intro_pa);
$element_intro_pa = $arr_intro_pa[0];
$arr_intro        = $element_intro_pa->find($re_intro);
$element_intro    = $arr_intro[0];
$intro            = $element_intro->innertext();
echo $intro;
echo "<br/>";
echo "________________________avatar_________________________";
echo "<br/>";

$arr_avatar_pa     = $html->find($re_avatar_pa);
$element_avatar_pa = $arr_avatar_pa[0];
$arr_avatar        = $element_avatar_pa->find($re_avatar);
$element_avatar    = $arr_avatar[0];
$avatar            = $element_avatar->src;
echo $avatar;
echo "<br/>";
echo "________________________chi tiet_________________________";
echo "<br/>";

$arr_description_pa     = $html->find($re_description_pa);
$element_description_pa = $arr_description_pa[0];
$arr_description       	= $element_description_pa->find($re_description);
$element_description    = $arr_description[0];
$description            = $element_description->innertext();
if(1){
   $explode_content     = explode('<div class="tn_print">',$description);
   $description     		= $explode_content[0];
}
$description	= str_replace($title,"",$description);
$description	= str_replace($intro,"",$description);
echo $description;
echo "<br/>";
?> 
</body>
</html>  

 

Bạn chạy lần lượt hai ví dụ để xem kết quả nhé.

4. Kết luận

Ở trên tôi vừa giới thiệu đến các bạn cách lấy dữ liệu với thư viện HTML DOM Parser hy vọng qua bài này bạn có thêm những lựa chọn cho mình khi lấy dữ liệu từ website khác. Những ví dụ tôi nêu ở trên là những ví dụ đơn giản còn trong quá trình làm dự án thực tế sẽ có những trường hợp phức tạp hơn rất nhiều nên các bạn cứ chịu khó quay tay nhiều vào thì vận may sẽ đến với các bạn.Trong bài viết có thể có nhiều chỗ chưa chính xác mang quan điểm cá nhân tác giả thì cũng mong nhận được sự góp ý từ phía các bạn.

Bài liên quan

Hướng dẫn lấy tin từ động từ vnexpress, dân trí với Simple HTML Dom

Simple Html Dom là thư viện của Php giúp cho việc chúng ta có thể lấy các thuộc tính của các thẻ HTML trong 1 website. Chúng ta có thể lấy trực tiếp thông tin từ link web hoặc là từ 1 chuỗi, đồng thời ta có thể lấy về, và sửa đổi nội dung. Trong nội dung bài viết này mình sẽ hướng dẫn các bạn lấy ...

Son Dong viết 00:08 ngày 03/11/2018

[VB.NET] Hướng dẫn chuyển đổi code HTML to BB code

Bài viết hôm nay, mình xin hướng dẫn các bạn cách chuyển đổi code từ code HTML to BBcode . Trong bài viết trước, mình đã có làm một bài hướng dẫn về cách đăng tin tự động lên diễn đàn Xenforo . Để đăng lên được các diễn đàn Forum, các bạn cần phải convert code ...

Trần Trung Dũng viết 00:55 ngày 02/10/2018

Hướng dẫn dùng fastlane để build, up test tự động

Fastlane là 1 công cụ hỗ trợ cho iOS, Android developer trong việc release, build test cực kỳ tốt. Các tính năng chính của nó các bạn có thể tham khảo trên trang chủ: https://fastlane.tools/. Trong khuôn khổ bài viết này, mình sẽ hướng dẫn các bạn dùng Fastlane để build, up file ipa test lên ...

Hoàng Hải Đăng viết 15:34 ngày 07/09/2018

Làm thế nào để lựa chọn công cụ kiểm thử tự động hóa hiệu quả nhất (Hướng dẫn hoàn chỉnh)

Lựa chọn công cụ kiểm thử tự động là một trong những bước quan trọng nhất trước khi bắt đầu tự động hóa cho một dự án bất kỳ. Điều quan trọng là bởi vì công cụ này sẽ ảnh hưởng lớn hoàn toàn đến nỗ lực tự động hóa toàn bộ của bạn. Nếu công cụ này là tốt và cung cấp cho bạn các tính năng yêu cầu, tự ...

Trịnh Tiến Mạnh viết 17:32 ngày 12/08/2018

Hướng dẫn tự động sao lưu dữ liệu mongodb lên AWS S3

Bài toán này xuất phát từ nhu cầu thực tế của team Machine Learning. Chẳng là anh em đang muốn backup dữ liệu của viblo lên cloud, để tiện sau này dùng, ngoài ra thì lưu nhiều data tại con product server của viblo cũng không phải giải pháp lâu dài. Thế là mình ngồi mày mò viết code ... php để sao ...

Tạ Quốc Bảo viết 16:00 ngày 12/08/2018
+1