คุณแยกวิเคราะห์และประมวลผล HTML / XML ใน PHP ได้อย่างไร


คำตอบ:


1897

ส่วนขยาย XML เนทิฟ

ฉันชอบใช้ส่วนขยาย XML เนทิฟตัวใดตัวหนึ่งเนื่องจากมันมาพร้อมกับ PHP โดยปกติแล้วจะเร็วกว่า libs ของบุคคลที่สามทั้งหมดและให้การควบคุมทั้งหมดที่ฉันต้องการกับมาร์กอัป

DOM

ส่วนขยาย DOM ช่วยให้คุณทำงานบนเอกสาร XML ผ่าน DOM API กับ PHP 5 เป็นการดำเนินการของ Document Object Model Core ระดับ 3 ของ W3C ซึ่งเป็นส่วนต่อประสานระหว่างแพลตฟอร์มและภาษาที่ช่วยให้โปรแกรมและสคริปต์สามารถเข้าถึงและอัปเดตแบบไดนามิกได้ เนื้อหาโครงสร้างและรูปแบบของเอกสาร

DOM มีความสามารถในการแยกวิเคราะห์และแก้ไข HTML ในโลกแห่งความจริง (แตก) และสามารถทำการสืบค้น XPathได้ มันขึ้นอยู่กับlibxml

ต้องใช้เวลาพอสมควรเพื่อให้เกิดผลกับ DOM แต่เวลานั้นคุ้มค่ากับ IMO เนื่องจาก DOM เป็นอินเทอร์เฟซที่ไม่เชื่อเรื่องภาษาคุณจะพบการใช้งานในหลายภาษาดังนั้นหากคุณต้องการเปลี่ยนภาษาการเขียนโปรแกรมของคุณโอกาสที่คุณจะรู้วิธีใช้ DOM API ของภาษานั้นอยู่แล้ว

ตัวอย่างการใช้งานพื้นฐานสามารถพบได้ในGrabbing แอตทริบิวต์ href ขององค์ประกอบ Aและภาพรวมแนวคิดทั่วไปสามารถพบได้ที่DOMDocument ใน php

วิธีการใช้ส่วนขยาย DOM ได้รับการครอบคลุมอย่างกว้างขวางใน StackOverflowดังนั้นหากคุณเลือกที่จะใช้งานคุณสามารถมั่นใจได้ว่าปัญหาส่วนใหญ่ที่คุณพบสามารถแก้ไขได้ด้วยการค้นหา / เรียกดู Stack Overflow

XmlReader

ส่วนขยาย XMLReader เป็นตัวแยกวิเคราะห์ XML ตัวอ่านทำหน้าที่เป็นเคอร์เซอร์ไปข้างหน้าในกระแสข้อมูลเอกสารและหยุดที่แต่ละโหนดระหว่างทาง

XMLReader เช่น DOM ขึ้นอยู่กับ libxml ฉันไม่ทราบวิธีเรียกใช้โมดูลตัวแยกวิเคราะห์ HTML ดังนั้นโอกาสในการใช้ XMLReader สำหรับการแยกวิเคราะห์ HTML ที่ใช้งานไม่ได้อาจมีประสิทธิภาพน้อยกว่าการใช้ DOM ซึ่งคุณสามารถบอกให้ใช้โมดูล Parser HTML ของ libxml ได้อย่างชัดเจน

ตัวอย่างการใช้งานพื้นฐานสามารถดูได้ที่การรับค่าทั้งหมดจากแท็ก h1 โดยใช้ php

ตัวแยกวิเคราะห์ XML

ส่วนขยายนี้ให้คุณสร้างตัวแยกวิเคราะห์ XML จากนั้นกำหนดตัวจัดการสำหรับเหตุการณ์ XML ที่แตกต่างกัน ตัวแยกวิเคราะห์ XML แต่ละตัวยังมีพารามิเตอร์บางอย่างที่คุณสามารถปรับได้

ไลบรารี XML Parser ยังใช้ libxml และใช้ตัวแยกวิเคราะห์แบบพุชแบบ XML ของSAX มันอาจเป็นทางเลือกที่ดีกว่าสำหรับการจัดการหน่วยความจำกว่า DOM หรือ SimpleXML แต่จะทำงานได้ยากกว่าการใช้ parser แบบดึงซึ่งดำเนินการโดย XMLReader

SimpleXML

ส่วนขยาย SimpleXML มอบชุดเครื่องมือที่ง่ายและใช้งานได้ง่ายเพื่อแปลง XML เป็นวัตถุที่สามารถประมวลผลด้วยตัวเลือกคุณสมบัติปกติและตัววนซ้ำอาร์เรย์

SimpleXML เป็นตัวเลือกเมื่อคุณรู้ว่า HTML นั้นถูกต้อง XHTML หากคุณจำเป็นต้องแยกวิเคราะห์ HTML ที่เสียหายอย่าพิจารณาแม้แต่ SimpleXml เพราะจะทำให้หายใจไม่ออก

ตัวอย่างการใช้งานพื้นฐานสามารถพบได้ที่โปรแกรมที่ง่ายต่อ CRUD โหนดและโหนดค่าของไฟล์ XMLและมีจำนวนมากตัวอย่างเพิ่มเติมในคู่มือการใช้งานของ PHP


ไลบรารีบุคคลที่สาม (ใช้ libxml)

หากคุณต้องการใช้ lib บุคคลที่สามฉันขอแนะนำให้ใช้ lib ที่ใช้DOM / libxmlด้านล่างแทนการแยกสตริง

FluentDom - Repo

FluentDOM ให้บริการอินเตอร์เฟส XML ที่คล้ายกับ jQuery สำหรับ DOMDocument ใน PHP Selectors ถูกเขียนใน XPath หรือ CSS (ใช้ตัวแปลง CSS เป็น XPath) เวอร์ชันปัจจุบันขยายการใช้งานอินเทอร์เฟซมาตรฐานของ DOM และเพิ่มคุณสมบัติจาก DOM Living Standard FluentDOM สามารถโหลดรูปแบบเช่น JSON, CSV, JsonML, RabbitFish และอื่น ๆ สามารถติดตั้งผ่าน Composer

HtmlPageDom

Wa72 \ HtmlPageDom` เป็นไลบรารี PHP สำหรับการจัดการเอกสาร HTML ที่ใช้งานง่ายโดยต้องใช้DomCrawler จากคอมโพเนนต์ Symfony2สำหรับการสำรวจทรี DOM และขยายโดยเพิ่มวิธีการจัดการ Tree DOM ของเอกสาร HTML

phpQuery (ไม่ปรับปรุงสำหรับปี)

phpQuery เป็นฝั่งเซิร์ฟเวอร์, ตัวเลือก CSS3 ซึ่งเป็นตัวขับเคลื่อน CSS3 ซึ่งเป็นตัวขับเคลื่อนเอกสารที่ขับเคลื่อนด้วย API บนพื้นฐานของ jQuery JavaScript Library ที่เขียนด้วย PHP5 และให้ Command Line Interface (CLI) เพิ่มเติม

ดูเพิ่มเติมที่: https://github.com/electrolinux/phpquery

Zend_Dom

Zend_Dom จัดเตรียมเครื่องมือสำหรับการทำงานกับเอกสารและโครงสร้าง DOM ขณะนี้เราขอเสนอ Zend_Dom_Query ซึ่งมีอินเทอร์เฟซแบบรวมสำหรับการสืบค้นเอกสาร DOM ที่ใช้ทั้งตัวเลือก XPath และ CSS

QueryPath

QueryPath เป็นห้องสมุด PHP สำหรับจัดการ XML และ HTML มันถูกออกแบบมาเพื่อทำงานไม่เพียง แต่กับไฟล์ในเครื่อง แต่ยังมีบริการบนเว็บและทรัพยากรฐานข้อมูล มันใช้อินเตอร์เฟซ jQuery เป็นส่วนใหญ่ (รวมถึงตัวเลือกสไตล์ CSS) แต่ได้รับการปรับแต่งอย่างมากสำหรับการใช้งานฝั่งเซิร์ฟเวอร์ สามารถติดตั้งผ่าน Composer

fDOMDocument

fDOMDocument ขยาย DOM มาตรฐานเพื่อใช้ข้อยกเว้นในทุกโอกาสที่เกิดข้อผิดพลาดแทนคำเตือนหรือประกาศ PHP พวกเขายังเพิ่มวิธีการที่กำหนดเองและทางลัดต่าง ๆ เพื่อความสะดวกและเพื่อให้การใช้ DOM ง่ายขึ้น

กระบี่ / XML

saber / xml เป็นไลบรารีที่ล้อมรอบและขยายคลาส XMLReader และ XMLWriter เพื่อสร้างระบบการแมป "xml to object / array" แบบง่ายและรูปแบบการออกแบบ การเขียนและอ่าน XML เป็นแบบผ่านครั้งเดียวและสามารถรวดเร็วและต้องการหน่วยความจำเหลือน้อยในไฟล์ xml ขนาดใหญ่

FluidXML

FluidXML เป็นห้องสมุด PHP สำหรับจัดการ XML ด้วย API ที่กระชับและคล่องแคล่ว มันใช้ประโยชน์จาก XPath และรูปแบบการเขียนโปรแกรมได้อย่างคล่องแคล่วเพื่อความสนุกสนานและมีประสิทธิภาพ


บุคคลที่สาม (ไม่ใช่ libxml-based)

ประโยชน์ของการสร้างจาก DOM / libxml คือคุณได้รับประสิทธิภาพการทำงานที่ดีเพราะคุณใช้ส่วนขยายแบบเนทีฟ อย่างไรก็ตามไม่ใช่ libs บุคคลที่สามทั้งหมดที่ลงเส้นทางนี้ บางคนอยู่ด้านล่าง

PHP Simple HTML Parser DOM

  • เครื่องมือแยกวิเคราะห์ HTML DOM ที่เขียนด้วย PHP5 + ช่วยให้คุณจัดการ HTML ได้อย่างง่ายดาย!
  • ต้องการ PHP 5+
  • รองรับ HTML ที่ไม่ถูกต้อง
  • ค้นหาแท็กในหน้า HTML ที่มีตัวเลือกเช่นเดียวกับ jQuery
  • แยกเนื้อหาจาก HTML ในบรรทัดเดียว

ฉันไม่แนะนำให้ใช้เครื่องมือแยกวิเคราะห์นี้ codebase นั้นแย่มากและ parser นั้นค่อนข้างช้าและหน่วยความจำก็หิว ไม่สามารถเลือก jQuery Selectors ทั้งหมด (เช่นตัวเลือกลูก ) ได้ ไลบรารีที่ใช้ libxml ควรมีประสิทธิภาพสูงกว่านี้อย่างง่ายดาย

PHP Html Parser

PHPHtmlParser เป็นตัวแยกวิเคราะห์ html ที่เรียบง่ายยืดหยุ่นซึ่งอนุญาตให้คุณเลือกแท็กโดยใช้ตัวเลือก css เช่น jQuery เป้าหมายคือช่วยในการพัฒนาเครื่องมือที่ต้องการวิธีที่ง่ายและรวดเร็วในการคัดลอก html ไม่ว่าจะถูกต้องหรือไม่ก็ตาม! โครงการนี้ได้รับการสนับสนุนดั้งเดิมโดย sunra / php-simple-html-dom-parser แต่การสนับสนุนดูเหมือนจะหยุดลงดังนั้นโครงการนี้คือการปรับตัวของงานก่อนหน้านี้ของฉัน

อีกครั้งฉันจะไม่แนะนำ parser นี้ ค่อนข้างช้าด้วยการใช้งาน CPU สูง นอกจากนี้ยังไม่มีฟังก์ชั่นเพื่อล้างหน่วยความจำของวัตถุ DOM ที่สร้างขึ้น ปัญหาเหล่านี้ขยายขอบเขตโดยเฉพาะอย่างยิ่งกับลูปซ้อนกัน เอกสารนั้นไม่ถูกต้องและสะกดผิดโดยไม่มีการตอบกลับการแก้ไขตั้งแต่วันที่ 14 เม.ย. 16

Ganon

  • โทเค็นอเนกประสงค์และตัวแยก DOM DOM HTML / XML / RSS
    • ความสามารถในการจัดการองค์ประกอบและคุณสมบัติของพวกเขา
    • รองรับ HTML และ UTF8 ที่ไม่ถูกต้อง
  • สามารถดำเนินการแบบสอบถาม CSS3 เหมือนขั้นสูงในองค์ประกอบ (เช่น jQuery - รองรับ namespaces)
  • เครื่องมือตกแต่ง HTML (เช่น HTML Tidy)
    • ลดขนาด CSS และ Javascript
    • จัดเรียงแอตทริบิวต์เปลี่ยนตัวอักษรกรณีการเยื้องที่ถูกต้อง ฯลฯ
  • Extensible
    • การแยกเอกสารโดยใช้การเรียกกลับตามอักขระ / โทเค็นปัจจุบัน
    • การดำเนินการแยกกันในฟังก์ชั่นขนาดเล็กเพื่อการเอาชนะได้ง่าย
  • ง่ายและรวดเร็ว

ไม่เคยใช้มัน ไม่สามารถบอกได้ว่ามันดีหรือไม่


HTML 5

คุณสามารถใช้ด้านบนสำหรับการแยกวิเคราะห์ HTML5 แต่อาจมีข้อผิดพลาดเนื่องจากมาร์กอัพ HTML5 อนุญาต ดังนั้นสำหรับ HTML5 คุณต้องการพิจารณาใช้ parser เฉพาะเช่น

html5lib

การใช้งาน Python และ PHP ของตัวแยกวิเคราะห์ HTML ตามข้อกำหนด WHATWG HTML5 เพื่อความเข้ากันได้สูงสุดกับเว็บเบราว์เซอร์เดสก์ท็อปหลัก

เราอาจเห็นตัวแยกวิเคราะห์เฉพาะเพิ่มเติมเมื่อ HTML5 ได้รับการสรุป นอกจากนี้ยังมีบล็อกโพสต์โดย W3 ชื่อว่าHow-To สำหรับการแยกวิเคราะห์ HTML 5ที่ควรค่าแก่การตรวจสอบ


WebServices

หากคุณไม่ต้องการเขียนโปรแกรม PHP คุณสามารถใช้บริการเว็บได้ โดยทั่วไปแล้วฉันพบยูทิลิตี้น้อยมากสำหรับสิ่งเหล่านี้ แต่นั่นเป็นเพียงฉันและกรณีใช้งานของฉัน

ScraperWiki

อินเทอร์เฟซภายนอกของ ScraperWiki ช่วยให้คุณสามารถดึงข้อมูลในแบบฟอร์มที่คุณต้องการใช้บนเว็บหรือในแอปพลิเคชันของคุณเอง คุณยังสามารถดึงข้อมูลเกี่ยวกับสถานะของมีดโกนใด ๆ


นิพจน์ทั่วไป

ที่ผ่านมาและน้อยแนะนำให้คุณสามารถดึงข้อมูลจาก HTML ที่มีการแสดงออกปกติ โดยทั่วไปแล้วไม่สนับสนุนการใช้นิพจน์ปกติบน HTML

ตัวอย่างข้อมูลส่วนใหญ่ที่คุณจะพบบนเว็บเพื่อจับคู่มาร์กอัปนั้นมีความเปราะ ในกรณีส่วนใหญ่พวกเขาจะทำงานเฉพาะกับ HTML ที่เฉพาะเจาะจงเท่านั้น การเปลี่ยนแปลงมาร์กอัปเล็ก ๆ เช่นเพิ่มช่องว่างที่ไหนสักแห่งหรือเพิ่มหรือเปลี่ยนแอตทริบิวต์ในแท็กสามารถทำให้ RegEx ล้มเหลวเมื่อเขียนไม่ถูกต้อง คุณควรรู้ว่าคุณกำลังทำอะไรก่อนใช้ RegEx บน HTML

ตัวแยกวิเคราะห์ HTML รู้จักกฎการสร้างประโยคของ HTML แล้ว นิพจน์ทั่วไปจะต้องมีการสอนสำหรับ RegEx ใหม่แต่ละรายการที่คุณเขียน RegEx นั้นใช้ได้ในบางกรณี แต่ขึ้นอยู่กับการใช้งานของคุณ

คุณสามารถเขียนตัวแยกวิเคราะห์ที่เชื่อถือได้มากขึ้นแต่การเขียนตัวแยกวิเคราะห์แบบกำหนดเองที่สมบูรณ์และเชื่อถือได้ด้วยนิพจน์ทั่วไปนั้นเป็นการเสียเวลาเมื่อไลบรารีดังกล่าวมีอยู่แล้วและทำงานได้ดีขึ้นมาก

ดูที่การแยกวิเคราะห์ Html The Cthulhu Way


หนังสือ

หากคุณต้องการใช้เงินลองดูที่

ฉันไม่ได้มีส่วนเกี่ยวข้องกับ PHP Architect หรือผู้เขียน


10
@Naveed ขึ้นอยู่กับความต้องการของคุณ ฉันไม่จำเป็นต้องใช้คำสั่ง CSS Selector ซึ่งเป็นเหตุผลที่ฉันใช้ DOM กับ XPath โดยเฉพาะ phpQuery ตั้งเป้าที่จะเป็นพอร์ต jQuery Zend_Dom มีน้ำหนักเบา คุณต้องตรวจสอบพวกเขาเพื่อดูว่าคนที่คุณชอบที่สุด
กอร์ดอน

2
@ Ms2ger เป็นส่วนใหญ่ แต่ไม่สมบูรณ์ เช่นเดียวกับที่ได้กล่าวไว้ข้างต้นคุณสามารถใช้ตัวแยกวิเคราะห์ libxml แต่มีกรณีพิเศษที่สิ่งเหล่านี้จะทำให้หายใจไม่ออก หากคุณต้องการความเข้ากันได้สูงสุดคุณก็จะดีขึ้นด้วยโปรแกรมแยกวิเคราะห์เฉพาะ ฉันชอบที่จะรักษาความแตกต่าง
Gordon

9
จุดของคุณที่ไม่ได้ใช้ PHP Simple HTML Parser DOM ดูเหมือนว่า moot
Petah

3
ตั้งแต่วันที่ 29 มีนาคม 2012, DOM ไม่รองรับ html5, XMLReader ไม่รองรับ HTML และการส่ง html5lib สำหรับ PHP ครั้งสุดท้ายในเดือนกันยายน 2009 จะใช้อะไรในการแยกวิเคราะห์ HTML5, HTML4 และ XHTML
Shiplu Mokaddim

4
@Nasha ฉันจงใจไม่ให้พูดจาโผงผาง Zalgo ที่น่าอับอายจากรายการด้านบนเพราะมันไม่ได้เป็นประโยชน์กับตัวเองมากนักและนำไปสู่ลัทธิการขนส่งสินค้าบางส่วนตั้งแต่มันถูกเขียนขึ้นมา ผู้คนถูกตบด้วยลิงก์นั้นไม่ว่า regex จะเหมาะสมเพียงใดในการแก้ปัญหา สำหรับความเห็นที่สมดุลมากขึ้นโปรดดูการเชื่อมโยงที่ฉันไม่รวมถึงการแทนและไปผ่านความเห็นที่stackoverflow.com/questions/4245008/...
กอร์ดอน

322

ลองใช้HTML DOM Parser แบบง่าย

  • เครื่องมือแยกวิเคราะห์ HTML DOM ที่เขียนด้วย PHP 5+ ที่ให้คุณปรับเปลี่ยน HTML ได้อย่างง่ายดาย!
  • ต้องการ PHP 5+
  • รองรับ HTML ที่ไม่ถูกต้อง
  • ค้นหาแท็กในหน้า HTML ที่มีตัวเลือกเช่นเดียวกับ jQuery
  • แยกเนื้อหาจาก HTML ในบรรทัดเดียว
  • ดาวน์โหลด


ตัวอย่าง:

วิธีรับองค์ประกอบ HTML:

// Create DOM from URL or file
$html = file_get_html('http://www.example.com/');

// Find all images
foreach($html->find('img') as $element)
       echo $element->src . '<br>';

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


วิธีแก้ไของค์ประกอบ HTML:

// Create DOM from string
$html = str_get_html('<div id="hello">Hello</div><div id="world">World</div>');

$html->find('div', 1)->class = 'bar';

$html->find('div[id=hello]', 0)->innertext = 'foo';

echo $html;


แยกเนื้อหาจาก HTML:

// Dump contents (without tags) from HTML
echo file_get_html('http://www.google.com/')->plaintext;


การขูด Slashdot:

// Create DOM from URL
$html = file_get_html('http://slashdot.org/');

// Find all article blocks
foreach($html->find('div.article') as $article) {
    $item['title']     = $article->find('div.title', 0)->plaintext;
    $item['intro']    = $article->find('div.intro', 0)->plaintext;
    $item['details'] = $article->find('div.details', 0)->plaintext;
    $articles[] = $item;
}

print_r($articles);

8
ก่อนอื่นมีสิ่งที่ฉันต้องเตรียมสำหรับเช่น DOM ที่ไม่ดี, รหัส Invlid, และการวิเคราะห์ js กับเครื่องยนต์ DNSBL, สิ่งนี้จะถูกใช้เพื่อมองหาเว็บไซต์ / เนื้อหาที่เป็นอันตราย, เช่นเดียวกับที่ฉันได้สร้างเว็บไซต์ของฉันรอบกรอบ ได้สร้างมันจะต้องสะอาดอ่านง่ายและมีโครงสร้างที่ดี SimpleDim ยอดเยี่ยม แต่รหัสยุ่งเล็กน้อย
RobertPitt

9
@Robert คุณอาจต้องการตรวจสอบhtmlpurifier.orgสำหรับสิ่งที่เกี่ยวข้องกับความปลอดภัย
Gordon

3
เขามีประเด็นที่ถูกต้องอย่างหนึ่ง: simpleHTMLDOM นั้นยากที่จะขยายออกไปเว้นแต่คุณจะใช้รูปแบบมัณฑนากรซึ่งฉันพบว่าไม่สะดวก ฉันพบว่าตัวเองสั่นเพียงแค่ทำการเปลี่ยนแปลงในระดับพื้นฐาน
Erik

1
สิ่งที่ฉันทำคือเรียกใช้ html ของฉันผ่านระเบียบเรียบร้อยก่อนที่จะส่งไปยัง SimpleDOM
MB34

1
ฉันใช้สิ่งนี้ในขณะนี้เรียกใช้เป็นส่วนหนึ่งของโครงการเพื่อประมวลผล URL ไม่กี่ร้อยรายการ มันเริ่มช้ามากและหมดเวลาปกติ มันเป็นสคริปต์เริ่มต้นที่ยอดเยี่ยมและง่ายต่อการเรียนรู้ แต่เพียงพื้นฐานเกินไปสำหรับโครงการขั้นสูง
luke_mclachlan

236

เพียงใช้DOMDocument-> loadHTML ()และใช้งาน อัลกอริทึมการแยกวิเคราะห์ HTML ของ libxml ค่อนข้างดีและรวดเร็วและตรงกันข้ามกับความเชื่อที่ได้รับความนิยมไม่สำลัก HTML ที่ผิดรูปแบบ


19
จริง และทำงานร่วมกับคลาส XPath และ XSLTProcessor ในตัวของ PHP ซึ่งยอดเยี่ยมสำหรับการแยกเนื้อหา
Kornel

8
สำหรับ HTML ที่ยุ่งเหยิงจริงๆคุณสามารถเรียกใช้ผ่าน htmltidy ก่อนส่งไปยัง DOM เมื่อใดก็ตามที่ฉันต้องการขูดข้อมูลจาก HTML ฉันมักจะใช้ DOM หรืออย่างน้อย simplexml
แฟรงก์เกษตรกร

9
อีกสิ่งหนึ่งที่มีการโหลด HTML ที่มีรูปแบบไม่ถูกต้องซึ่งอาจเป็นการดีที่จะเรียก libxml_use_internal_errors (จริง) เพื่อป้องกันคำเตือนที่จะหยุดการแยกวิเคราะห์
Husky

6
ฉันใช้ DOMDocument เพื่อแยกวิเคราะห์ประมาณ 1,000 แหล่ง html (ในภาษาต่างๆที่เข้ารหัสด้วยชุดอักขระที่แตกต่างกัน) โดยไม่มีปัญหาใด ๆ คุณอาจพบปัญหาการเข้ารหัสกับสิ่งนี้ แต่สิ่งเหล่านี้ไม่สามารถเอาชนะได้ คุณจำเป็นต้องรู้ 3 สิ่ง: 1) loadHTML ใช้ชุดอักขระของเมตาแท็กเพื่อตรวจสอบการเข้ารหัส 2) # 2 สามารถนำไปสู่การตรวจจับการเข้ารหัสที่ไม่ถูกต้องหากเนื้อหา HTML ไม่รวมข้อมูลนี้ 3) อักขระ UTF-8 ไม่ดี ในกรณีเช่นนี้ให้ใช้การรวมกันของ mb_detect_encoding () และ Simplepie RSS Parser ของการเข้ารหัส / การแปลง / การลอก / การลอกรหัสอักขระ UTF-8 ที่ไม่ดีสำหรับการแก้ไขปัญหา
ศูนย์

1
DOM ไม่จริงสนับสนุน XPath ใช้เวลาดูที่DOMXPath
Ryan McCue

147

ทำไมคุณไม่ควรและเมื่อคุณควรใช้การแสดงออกปกติ?

ก่อนอื่นการเรียกชื่อผิดทั่วไป: Regexps ไม่ใช่สำหรับ"การแยกวิเคราะห์ " HTML อย่างไรก็ตาม Regexes สามารถ" ดึง "ข้อมูลได้ การแยกเป็นสิ่งที่พวกเขาทำ ข้อเสียเปรียบที่สำคัญของการแยก HTML regex ผ่านชุดเครื่องมือ SGML หรือตัวแยกวิเคราะห์ XML พื้นฐานคือความพยายามในการสร้างประโยคและความน่าเชื่อถือที่แตกต่างกัน

พิจารณาว่าการสร้าง regex สกัด HTML ที่เชื่อถือได้ค่อนข้าง:

<a\s+class="?playbutton\d?[^>]+id="(\d+)".+?    <a\s+class="[\w\s]*title
[\w\s]*"[^>]+href="(http://[^">]+)"[^>]*>([^<>]+)</a>.+?

เป็นวิธีที่น้อยกว่าการอ่านง่ายกว่าเทียบเท่า phpQuery หรือ QueryPath:

$div->find(".stationcool a")->attr("title");

อย่างไรก็ตามมีกรณีการใช้งานเฉพาะที่พวกเขาสามารถช่วยได้

  • ส่วนหน้าการสำรวจเส้นทาง DOM จำนวนมากไม่เปิดเผยความคิดเห็น HTML <!--ซึ่งบางครั้งก็เป็นจุดยึดที่มีประโยชน์มากกว่าสำหรับการแยกไฟล์ โดยเฉพาะอย่างยิ่งรูปแบบหลอก HTML <$var>หรือเศษ SGML นั้นง่ายต่อการเชื่องด้วย regexps
  • บ่อยครั้งที่นิพจน์ทั่วไปสามารถบันทึกการประมวลผลภายหลัง อย่างไรก็ตามเอนทิตี HTML มักต้องการการดูแลด้วยตนเอง
  • และสุดท้ายสำหรับงานที่ง่ายมากเช่นการแยก <img src = urls พวกเขาเป็นเครื่องมือที่น่าจะเป็นจริง ความได้เปรียบด้านความเร็วของตัวแยกวิเคราะห์ SGML / XML ส่วนใหญ่เพิ่งมาเล่นสำหรับขั้นตอนการดึงข้อมูลพื้นฐานเหล่านี้

บางครั้งก็แนะนำให้แยกตัวอย่างของ HTML ล่วงหน้าโดยใช้นิพจน์ปกติ/<!--CONTENT-->(.+?)<!--END-->/และประมวลผลส่วนที่เหลือโดยใช้ส่วนหน้า HTML parser ที่ง่ายกว่า

หมายเหตุ:ฉันมีแอพนี้จริงๆที่ฉันใช้การแยกวิเคราะห์ XML และแสดงผลปกติหรือ เมื่อสัปดาห์ที่แล้วการแยกวิเคราะห์ PyQuery หยุดชะงักและ regex ยังทำงานอยู่ ใช่แปลกและฉันไม่สามารถอธิบายได้ด้วยตนเอง แต่มันก็เกิดขึ้น
ดังนั้นโปรดอย่าโหวตให้กับการพิจารณาในโลกแห่งความจริงเพราะมันไม่ตรงกับ regex = evil meme แต่เราก็ไม่ควรลงคะแนนมากเกินไป มันเป็นเพียง sidenote สำหรับหัวข้อนี้


20
DOMCommentสามารถอ่านความคิดเห็นได้ดังนั้นจึงไม่มีเหตุผลที่จะใช้ Regex
กอร์ดอน

4
ชุดเครื่องมือ SGML หรือตัวแยกวิเคราะห์ XML ไม่เหมาะสำหรับการแยกวิเคราะห์ HTML ในโลกแห่งความเป็นจริง สำหรับสิ่งนั้นตัวแยกวิเคราะห์ HTML เฉพาะนั้นเหมาะสมเท่านั้น
Alohci

12
@Alohci DOMใช้libxmlและlibxml มีโมดูลตัวแยกวิเคราะห์ HTML แยกต่างหากซึ่งจะใช้เมื่อโหลด HTML ด้วยloadHTML()ดังนั้นจึงสามารถโหลด HTML "โลกแห่งความจริง" ได้อย่างมาก (อ่านไม่ทำงาน)
กอร์ดอน

6
เป็นเพียงความคิดเห็นเกี่ยวกับมุมมอง "การพิจารณาในโลกแห่งความเป็นจริง" ของคุณ แน่นอนว่ามีสถานการณ์ที่เป็นประโยชน์สำหรับ Regex เมื่อแยกวิเคราะห์ HTML และยังมีสถานการณ์ที่มีประโยชน์สำหรับการใช้ GOTO และมีสถานการณ์ที่เป็นประโยชน์สำหรับตัวแปรตัวแปร ดังนั้นจึงไม่มีการนำไปปฏิบัติโดยเฉพาะอย่างยิ่งรหัสเน่าสำหรับการใช้งาน แต่มันเป็นสัญญาณเตือนที่แข็งแกร่งมาก และนักพัฒนาซอฟต์แวร์โดยเฉลี่ยไม่น่าจะเหมาะสมพอที่จะบอกความแตกต่าง ดังนั้นตามกฎทั่วไป Regex GOTO และ Variable-Variables ล้วน แต่เป็นความชั่วร้าย มีการใช้ที่ไม่ใช่ความชั่ว แต่มีข้อยกเว้น (และหายากที่)
ircmaxell

11
@mario: ที่จริงแล้ว HTML สามารถแยกวิเคราะห์ 'ถูกต้อง' โดยใช้ regexes แม้ว่าโดยปกติแล้วจะใช้เวลาหลายคนในการทำงานที่ยุติธรรม tit มันเป็นเพียงความเจ็บปวดในกรณีทั่วไป ในบางกรณีที่มีการป้อนข้อมูลที่ชัดเจน นี่คือกรณีที่ผู้คนควรใช้ regexes ตัวแยกวิเคราะห์ผู้หิวโหยขนาดใหญ่ที่เก่าแก่จริงๆแล้วเป็นสิ่งที่คุณต้องการสำหรับกรณีทั่วไปแม้ว่ามันจะไม่ชัดเจนสำหรับผู้ใช้ทั่วไปที่จะวาดเส้นนั้น รหัสใดง่ายกว่าและง่ายกว่าชนะ
tchrist

131

phpQueryและQueryPathมีความคล้ายคลึงกันอย่างมากในการจำลอง jQuery API ได้อย่างคล่องแคล่ว นั่นเป็นเหตุผลว่าทำไมพวกเขาถึงวิธีที่ง่ายที่สุดสองวิธีในการแยกวิเคราะห์ HTML ใน PHP อย่างถูกต้อง

ตัวอย่างสำหรับ QueryPath

โดยพื้นฐานแล้วคุณสร้างทรี DOM ที่สืบค้นได้จากสตริง HTML เป็นครั้งแรก:

 $qp = qp("<html><body><h1>title</h1>..."); // or give filename or URL

วัตถุที่เป็นผลลัพธ์ประกอบด้วยการแสดงทรีที่สมบูรณ์ของเอกสาร HTML มันสามารถถูก traversed โดยใช้วิธี DOM แต่วิธีการทั่วไปคือการใช้ตัวเลือก CSS เช่นใน jQuery:

 $qp->find("div.classname")->children()->...;

 foreach ($qp->find("p img") as $img) {
     print qp($img)->attr("src");
 }

ส่วนใหญ่คุณต้องการใช้ง่าย#idและ.classหรือแท็กเตอร์สำหรับDIV ->find()แต่คุณสามารถใช้คำสั่งXPathซึ่งบางครั้งก็เร็วกว่า ยังมีวิธีการ jQuery ทั่วไปชอบ->children()และ->text()โดยเฉพาะอย่างยิ่ง->attr()ลดความซับซ้อนของการแยกตัวอย่าง HTML ขวา (และมีเอนทิตี SGML ของพวกเขาถอดรหัสอยู่แล้ว)

 $qp->xpath("//div/p[1]");  // get first paragraph in a div

QueryPath ยังอนุญาตให้ฉีดแท็กใหม่ลงในสตรีม ( ->append) และส่งออกในภายหลังและ prettify เอกสารที่อัปเดต ( ->writeHTML) ไม่เพียง แต่สามารถแยกวิเคราะห์ HTML ที่มีรูปแบบไม่ถูกต้อง แต่ยังสามารถใช้ภาษาถิ่น XML ต่างๆ (ที่มีเนมสเปซ) และแม้แต่แยกข้อมูลจากไมโครฟอร์แมต HTML (XFN, vCard)

 $qp->find("a[target=_blank]")->toggleClass("usability-blunder");

.

phpQuery หรือ QueryPath?

โดยทั่วไป QueryPath จะเหมาะกว่าสำหรับการจัดการเอกสาร ในขณะที่ phpQuery ยังใช้เมธอด AJAX หลอกๆ (ร้องขอ HTTP) เพื่อให้คล้ายกับ jQuery มากขึ้น ว่ากันว่า phpQuery มักจะเร็วกว่า QueryPath (เพราะคุณสมบัติโดยรวมน้อยลง)

สำหรับข้อมูลเพิ่มเติมเกี่ยวกับความแตกต่างที่เห็นการเปรียบเทียบนี้บนเครื่อง Wayback จาก tagbyte.org (แหล่งที่มาดั้งเดิมหายไปดังนั้นนี่คือลิงค์เก็บถาวรทางอินเทอร์เน็ตใช่คุณยังสามารถค้นหาผู้คนที่หายไป)

และนี่คือการแนะนำ QueryPath ครอบคลุม

ข้อดี

  • ความเรียบง่ายและความน่าเชื่อถือ
  • ทางเลือกที่ใช้ง่าย ->find("a img, a object, div a")
  • unescaping ข้อมูลที่เหมาะสม (เปรียบเทียบกับ grepping นิพจน์ทั่วไป)

88

Simple HTML DOM เป็นโปรแกรมแยกวิเคราะห์โอเพ่นซอร์สที่ยอดเยี่ยม:

simplehtmldom.sourceforge

มันปฏิบัติต่อองค์ประกอบ DOM ในลักษณะเชิงวัตถุและการวนซ้ำใหม่มีความครอบคลุมมากสำหรับรหัสที่ไม่เข้ากัน นอกจากนี้ยังมีฟังก์ชั่นที่ยอดเยี่ยมเช่นที่คุณเห็นใน JavaScript เช่นฟังก์ชัน "ค้นหา" ซึ่งจะส่งคืนองค์ประกอบทั้งหมดของชื่อแท็กนั้น

ฉันใช้มันเป็นเครื่องมือจำนวนหนึ่งทดสอบกับหน้าเว็บหลายประเภทและฉันคิดว่ามันใช้งานได้ดี


61

วิธีการทั่วไปอย่างหนึ่งที่ฉันไม่ได้กล่าวถึงในที่นี้คือการเรียกใช้ HTML ผ่านTidyซึ่งสามารถตั้งค่าให้คาย XHTML ที่ถูกต้องซึ่งรับประกันได้ จากนั้นคุณสามารถใช้ไลบรารี XML เก่า ๆ ได้

แต่สำหรับปัญหาเฉพาะของคุณคุณควรดูที่โครงการนี้: http://fivefilters.org/content-only/ - เป็นอัลกอริทึมการอ่านที่ได้รับการแก้ไขซึ่งถูกออกแบบมาเพื่อแยกเนื้อหาที่เป็นข้อความ (ไม่ใช่ส่วนหัว และท้ายกระดาษ) จากหน้า


56

สำหรับ 1a และ 2: ฉันจะลงคะแนนให้คลาส Symfony Componet ใหม่ DOMCrawler ( DomCrawler ) ชั้นนี้ช่วยให้แบบสอบถามที่คล้ายกับ CSS Selectors ลองดูที่นำเสนอนี้สำหรับตัวอย่างจริงของโลก: ข่าวของ symfony2 โลก

ส่วนประกอบถูกออกแบบมาเพื่อทำงานแบบสแตนด์อโลนและสามารถใช้งานได้โดยไม่ต้องใช้ Symfony

ข้อเสียเปรียบเพียงอย่างเดียวคือมันจะทำงานกับ PHP 5.3 หรือใหม่กว่าเท่านั้น


jQuery-like css query ได้รับการกล่าวถึงอย่างดีเพราะมีบางสิ่งที่ขาดหายไปในเอกสาร w3c แต่มีอยู่ในคุณสมบัติพิเศษใน jquery
Nikola Petkanski

53

นี้เป็นที่นิยมเรียกว่าขูดหน้าจอโดยวิธีการ ห้องสมุดที่ฉันได้ใช้สำหรับเรื่องนี้คือHTML อย่างง่าย Dom Parser


8
ไม่เป็นความจริงอย่างเคร่งครัด ( en.wikipedia.org/wiki/Screen_scraping#Screen_scraping ) เบาะแสอยู่ใน "หน้าจอ"; ในกรณีที่อธิบายไม่มีหน้าจอที่เกี่ยวข้อง แม้ว่าเป็นที่ยอมรับกันแล้วคำดังกล่าวได้รับความเดือดร้อนจากการใช้ผิดวิธีจำนวนมากอย่างไม่น่าเชื่อ
บ๊อบบี้แจ็ค

4
ฉันไม่ได้คัดลอกเนื้อหาที่จะแยกวิเคราะห์จะได้รับอนุญาตจากผู้จัดหาเนื้อหาภายใต้ข้อตกลงของฉัน
RobertPitt

41

เราได้สร้างโปรแกรมรวบรวมข้อมูลค่อนข้างน้อยสำหรับความต้องการของเราก่อน ในตอนท้ายของวันมันมักจะเป็นนิพจน์ธรรมดาที่ทำสิ่งที่ดีที่สุด แม้ว่าไลบรารี่ที่ระบุไว้ด้านบนนั้นดีสำหรับเหตุผลที่สร้างขึ้น แต่ถ้าคุณรู้ว่าคุณกำลังมองหานิพจน์ทั่วไปเป็นวิธีที่ปลอดภัยกว่าในการไปเพราะคุณสามารถจัดการกับโครงสร้างHTML / XHTML ที่ไม่ถูกต้องซึ่งจะล้มเหลวถ้าโหลด ผ่านตัวแยกวิเคราะห์ส่วนใหญ่



36

ดูเหมือนว่าคำอธิบายงานที่ดีของเทคโนโลยีW3C XPath เป็นเรื่องง่ายที่จะแสดงข้อความค้นหาเช่น "ส่งคืนhrefแอตทริบิวต์ทั้งหมดในimgแท็กที่ซ้อนกันอยู่<foo><bar><baz> elements" ไม่ใช่การเป็น PHP PHP ฉันไม่สามารถบอกคุณได้ว่าแบบฟอร์ม XPath ใดที่พร้อมใช้งาน หากคุณสามารถเรียกโปรแกรมภายนอกเพื่อประมวลผลไฟล์ HTML คุณควรจะสามารถใช้ XPath เวอร์ชันบรรทัดคำสั่งได้ สำหรับบทนำอย่างรวดเร็วดูhttp://en.wikipedia.org/wiki/XPath


29

ทางเลือกบุคคลที่สามเพื่อ SimpleHtmlDom ว่าการใช้ DOM แทน String แยก: phpQuery , Zend_Dom , QueryPathและFluentDom


3
หากคุณคัดลอกความคิดเห็นของฉันที่เชื่อมโยงได้อย่างถูกต้องอย่างน้อย;) ที่ควรจะเป็น: แนะนำทางเลือกบุคคลที่สามเพื่อSimpleHtmlDomที่จริงใช้DOMแทน String แยก: phpQuery , Zend_Dom , QueryPathและFluentDom
Gordon

1
คำตอบที่ดีคือแหล่งที่ดี stackoverflow.com/questions/3606792/…
danidacar

24

ใช่คุณสามารถใช้ simple_html_dom เพื่อจุดประสงค์ อย่างไรก็ตามฉันได้ทำงานค่อนข้างมากกับ simple_html_dom โดยเฉพาะอย่างยิ่งสำหรับการทำให้เว็บเสียและพบว่ามีความเสี่ยงเกินไป มันเป็นงานขั้นพื้นฐาน แต่ฉันจะไม่แนะนำเลย

ฉันไม่เคยใช้ curl เพื่อจุดประสงค์ แต่สิ่งที่ฉันได้เรียนรู้คือ curl สามารถทำงานได้อย่างมีประสิทธิภาพมากขึ้นและแข็งแกร่งขึ้น

กรุณาตรวจสอบลิงค์นี้: scraping-sites-with-curl


2
curl สามารถรับไฟล์ได้ แต่มันจะไม่แยก HTML สำหรับคุณ นั่นเป็นส่วนที่ยาก
cHao

23

QueryPathนั้นดี แต่โปรดระวัง "สถานะการติดตาม" หากคุณไม่ทราบว่ามันหมายถึงอะไรมันอาจหมายความว่าคุณเสียเวลาในการดีบักจำนวนมากพยายามค้นหาว่าเกิดอะไรขึ้นและทำไมรหัสไม่ทำงาน

หมายความว่าอะไรการโทรแต่ละครั้งบนชุดผลลัพธ์จะปรับเปลี่ยนชุดผลลัพธ์ในวัตถุมันไม่สามารถโยงได้เหมือนกับ jquery โดยที่แต่ละลิงก์เป็นชุดใหม่คุณมีชุดเดียวซึ่งเป็นผลลัพธ์จากแบบสอบถามของคุณและแต่ละฟังก์ชันเรียกแก้ไข ชุดเดียวนั้น

เพื่อให้ได้พฤติกรรมที่เหมือน jQuery คุณต้องแยกสาขาก่อนที่จะทำการกรอง / ดัดแปลงเช่นการดำเนินการซึ่งหมายความว่ามันจะสะท้อนสิ่งที่เกิดขึ้นใน jquery อย่างใกล้ชิดยิ่งขึ้น

$results = qp("div p");
$forename = $results->find("input[name='forename']");

$resultsตอนนี้มีชุดผลลัพธ์สำหรับinput[name='forename']ข้อความค้นหาดั้งเดิมที่ไม่ทำให้"div p"ฉันสะดุดมากสิ่งที่ฉันพบคือQueryPathติดตามตัวกรองและการค้นหาและทุกอย่างที่แก้ไขผลลัพธ์ของคุณและเก็บไว้ในวัตถุ คุณต้องทำสิ่งนี้แทน

$forename = $results->branch()->find("input[name='forname']")

จากนั้น$resultsจะไม่ได้รับการแก้ไขและคุณสามารถนำชุดผลลัพธ์กลับมาใช้ซ้ำแล้วซ้ำอีกบางทีใครบางคนที่มีความรู้มากกว่านี้สามารถล้างข้อมูลนี้ได้เล็กน้อย แต่โดยพื้นฐานแล้วมันเป็นแบบนี้จากสิ่งที่ฉันพบ


20

Advanced Html Domเป็นการแทนที่HTML DOMแบบง่ายที่นำเสนออินเทอร์เฟซเดียวกัน แต่ใช้ DOM ซึ่งหมายความว่าไม่มีปัญหาหน่วยความจำที่เกี่ยวข้องเกิดขึ้น

นอกจากนี้ยังมีการสนับสนุน CSS แบบเต็มรวมถึงส่วนขยายjQuery


ฉันได้รับผลลัพธ์ที่ดีจาก Advanced Html Dom และฉันคิดว่าควรอยู่ในรายการในคำตอบที่ยอมรับได้ สิ่งสำคัญที่ควรทราบสำหรับทุกคนที่อาศัย "เป้าหมายของโครงการนี้คือการใช้ดรอปดาวน์แบบ DOM-based สำหรับไลบรารี html dom ที่เรียบง่ายของ PHP ... หากคุณใช้ไฟล์ / str_get_html คุณไม่จำเป็นต้อง เปลี่ยนอะไรก็ได้ " archive.is/QtSuj#selection-933.34-933.100คือคุณอาจต้องทำการเปลี่ยนแปลงรหัสของคุณเพื่อรองรับความเข้ากันไม่ได้บางอย่าง ฉันได้สังเกตเห็นสี่คนที่รู้จักกับฉันในปัญหา GitHub ของโครงการ github.com/monkeysuffrage/advanced_html_dom/issues
ChrisJJ

ทำงานแล้ว! ขอบคุณ
Faisal Shani

18

สำหรับHTML5 ตอนนี้ html5 lib ถูกยกเลิกไปหลายปีแล้ว ไลบรารี HTML5 เดียวที่ฉันสามารถค้นหาได้ด้วยการอัปเดตล่าสุดและบันทึกการบำรุงรักษาคือhtml5-phpซึ่งเพิ่งนำไปสู่เบต้า 1.0 เล็กน้อยเมื่อสัปดาห์ที่แล้ว


17

ฉันได้เขียนตัวแยกวิเคราะห์ XML วัตถุประสงค์ทั่วไปที่สามารถจัดการไฟล์ GB ได้อย่างง่ายดาย มันขึ้นอยู่กับ XMLReader และใช้งานง่ายมาก:

$source = new XmlExtractor("path/to/tag", "/path/to/file.xml");
foreach ($source as $tag) {
    echo $tag->field1;
    echo $tag->field2->subfield1;
}

นี่คือ repo github: XmlExtractor


17

ฉันสร้างห้องสมุดชื่อPHPPowertools / DOM-Queryซึ่งอนุญาตให้คุณรวบรวมข้อมูลเอกสาร HTML5 และ XML เช่นเดียวกับที่คุณทำกับ jQuery

ภายใต้ประทุนนั้นจะใช้symfony / DomCrawlerสำหรับการแปลง CSS selectors เป็นXPath selectors มันมักจะใช้ DomDocument เดียวกันแม้ว่าจะผ่านวัตถุหนึ่งไปยังวัตถุอื่นเพื่อให้มั่นใจถึงประสิทธิภาพที่ดี


ตัวอย่างการใช้:

namespace PowerTools;

// Get file content
$htmlcode = file_get_contents('https://github.com');

// Define your DOMCrawler based on file string
$H = new DOM_Query($htmlcode);

// Define your DOMCrawler based on an existing DOM_Query instance
$H = new DOM_Query($H->select('body'));

// Passing a string (CSS selector)
$s = $H->select('div.foo');

// Passing an element object (DOM Element)
$s = $H->select($documentBody);

// Passing a DOM Query object
$s = $H->select( $H->select('p + p'));

// Select the body tag
$body = $H->select('body');

// Combine different classes as one selector to get all site blocks
$siteblocks = $body->select('.site-header, .masthead, .site-body, .site-footer');

// Nest your methods just like you would with jQuery
$siteblocks->select('button')->add('span')->addClass('icon icon-printer');

// Use a lambda function to set the text of all site blocks
$siteblocks->text(function( $i, $val) {
    return $i . " - " . $val->attr('class');
});

// Append the following HTML to all site blocks
$siteblocks->append('<div class="site-center"></div>');

// Use a descendant selector to select the site's footer
$sitefooter = $body->select('.site-footer > .site-center');

// Set some attributes for the site's footer
$sitefooter->attr(array('id' => 'aweeesome', 'data-val' => 'see'));

// Use a lambda function to set the attributes of all site blocks
$siteblocks->attr('data-val', function( $i, $val) {
    return $i . " - " . $val->attr('class') . " - photo by Kelly Clark";
});

// Select the parent of the site's footer
$sitefooterparent = $sitefooter->parent();

// Remove the class of all i-tags within the site's footer's parent
$sitefooterparent->select('i')->removeAttr('class');

// Wrap the site's footer within two nex selectors
$sitefooter->wrap('<section><div class="footer-wrapper"></div></section>');

[...]

วิธีการที่รองรับ:


  1. เปลี่ยนชื่อเป็น 'select' ด้วยเหตุผลที่ชัดเจน
  2. เปลี่ยนชื่อเป็น 'โมฆะ' เนื่องจาก 'empty' เป็นคำที่สงวนไว้ใน PHP

บันทึก :

ไลบรารี่ยังมีออโต้โหลดเดอร์ที่เป็นศูนย์ของตัวเองสำหรับไลบรารีที่เข้ากันได้กับ PSR-0 ตัวอย่างที่รวมไว้ควรจะทำงานนอกกรอบโดยไม่มีการกำหนดค่าเพิ่มเติมใด ๆ หรือคุณสามารถใช้กับนักแต่งเพลง


ดูเหมือนเครื่องมือที่เหมาะสมสำหรับงาน แต่ไม่โหลดสำหรับฉันใน PHP 5.6.23 ใน Worpress มีคำแนะนำเพิ่มเติมเกี่ยวกับวิธีรวมอย่างถูกต้องหรือไม่ รวมไว้ใน: define ("BASE_PATH", dirname ( FILE )); define ("LIBRARY_PATH", BASE_PATH. DIRECTORY_SEPARATOR. 'lib / ผู้ขาย'); ต้องการ LIBRARY_PATH DIRECTORY_SEPARATOR 'Loader.php'; ตัวโหลด :: init (อาร์เรย์ (LIBRARY_PATH, USER_PATH)); ใน functions.php
lithiumlab

15

คุณสามารถลองใช้บางสิ่งบางอย่างเช่นHTML Tidyเพื่อล้าง HTML ที่ "เสีย" และแปลง HTML เป็น XHTML ซึ่งคุณสามารถแยกวิเคราะห์ด้วยตัวแยกวิเคราะห์ XML ได้


15

ตัวเลือกที่คุณสามารถลองก็คือQueryPath มันเป็นแรงบันดาลใจจาก jQuery แต่บนเซิร์ฟเวอร์ใน PHP และใช้ในDrupal


12

XML_HTMLSaxค่อนข้างเสถียร - แม้ว่าจะไม่ได้รับการบำรุงรักษาอีกต่อไป อีกทางเลือกหนึ่งคือไปป์ HTML ของคุณผ่านHtml Tidyแล้วแยกวิเคราะห์ด้วยเครื่องมือ XML มาตรฐาน



11

มีหลายวิธีในการประมวลผล HTML / XML DOM ซึ่งส่วนใหญ่ได้รับการกล่าวถึงแล้ว ดังนั้นฉันจะไม่พยายามแสดงตน

ฉันแค่ต้องการเพิ่มว่าโดยส่วนตัวแล้วฉันต้องการใช้ส่วนขยาย DOM และ:

  • iit ใช้ประโยชน์จากประสิทธิภาพสูงสุดของรหัส C พื้นฐาน
  • มันเป็น OO PHP (และอนุญาตให้ฉันทำคลาสย่อย)
  • มันค่อนข้างอยู่ในระดับต่ำ (ซึ่งทำให้ฉันสามารถใช้มันเป็นรากฐานที่ไม่บวมสำหรับพฤติกรรมขั้นสูงเพิ่มเติม)
  • มันให้การเข้าถึงทุกส่วนของ DOM (ไม่เหมือนเช่น SimpleXml ซึ่งไม่สนใจฟีเจอร์ XML ที่รู้จักกันน้อย)
  • มันมีไวยากรณ์ที่ใช้สำหรับการรวบรวมข้อมูล DOM ที่คล้ายกับไวยากรณ์ที่ใช้ใน Javascript พื้นเมือง

และในขณะที่ฉันพลาดความสามารถในการใช้ตัวเลือก CSS สำหรับDOMDocumentมันมีวิธีที่ค่อนข้างง่ายและสะดวกในการเพิ่มคุณสมบัตินี้: การทำคลาสย่อยDOMDocumentและเพิ่ม JS-like querySelectorAllและquerySelectorเมธอดลงในคลาสย่อยของคุณ

สำหรับการแยกเตอร์ผมขอแนะนำให้ใช้ minimalistic มากองค์ประกอบ CssSelectorจากกรอบ Symfony คอมโพเนนต์นี้แปลตัวเลือก CSS เป็นตัวเลือก XPath ซึ่งสามารถป้อนลงใน a DOMXpathเพื่อดึงข้อมูล Nodelist ที่สอดคล้องกัน

จากนั้นคุณสามารถใช้คลาสย่อยนี้ (ยังคงต่ำมาก) เพื่อเป็นพื้นฐานสำหรับคลาสระดับสูงที่มีความตั้งใจมากขึ้นเช่น แยกประเภท XML ที่เฉพาะเจาะจงมาก ๆ หรือเพิ่มลักษณะการทำงานของ jQuery เพิ่มเติม

รหัสด้านล่างนี้นำเสนอไลบรารี DOM-Queryของฉันโดยตรงและใช้เทคนิคที่ฉันอธิบาย

สำหรับการแยกวิเคราะห์ HTML:

namespace PowerTools;

use \Symfony\Component\CssSelector\CssSelector as CssSelector;

class DOM_Document extends \DOMDocument {
    public function __construct($data = false, $doctype = 'html', $encoding = 'UTF-8', $version = '1.0') {
        parent::__construct($version, $encoding);
        if ($doctype && $doctype === 'html') {
            @$this->loadHTML($data);
        } else {
            @$this->loadXML($data);
        }
    }

    public function querySelectorAll($selector, $contextnode = null) {
        if (isset($this->doctype->name) && $this->doctype->name == 'html') {
            CssSelector::enableHtmlExtension();
        } else {
            CssSelector::disableHtmlExtension();
        }
        $xpath = new \DOMXpath($this);
        return $xpath->query(CssSelector::toXPath($selector, 'descendant::'), $contextnode);
    }

    [...]

    public function loadHTMLFile($filename, $options = 0) {
        $this->loadHTML(file_get_contents($filename), $options);
    }

    public function loadHTML($source, $options = 0) {
        if ($source && $source != '') {
            $data = trim($source);
            $html5 = new HTML5(array('targetDocument' => $this, 'disableHtmlNsInDom' => true));
            $data_start = mb_substr($data, 0, 10);
            if (strpos($data_start, '<!DOCTYPE ') === 0 || strpos($data_start, '<html>') === 0) {
                $html5->loadHTML($data);
            } else {
                @$this->loadHTML('<!DOCTYPE html><html><head><meta charset="' . $encoding . '" /></head><body></body></html>');
                $t = $html5->loadHTMLFragment($data);
                $docbody = $this->getElementsByTagName('body')->item(0);
                while ($t->hasChildNodes()) {
                    $docbody->appendChild($t->firstChild);
                }
            }
        }
    }

    [...]
}

ดูเอกสารการแยกวิเคราะห์ XML ด้วยตัวเลือก CSSโดย Fabien Potencier ผู้สร้าง Symfony เกี่ยวกับการตัดสินใจของเขาในการสร้างองค์ประกอบ CssSelector สำหรับ Symfony และวิธีการใช้งาน


9

ด้วยFluidXMLคุณสามารถสอบถามและสำทับ XML ใช้XPathและCSS Selectors

$doc = fluidxml('<html>...</html>');

$title = $doc->query('//head/title')[0]->nodeValue;

$doc->query('//body/p', 'div.active', '#bgId')
        ->each(function($i, $node) {
            // $node is a DOMNode.
            $tag   = $node->nodeName;
            $text  = $node->nodeValue;
            $class = $node->getAttribute('class');
        });

https://github.com/servo-php/fluidxml


7

JSON และอาร์เรย์จาก XML ในสามบรรทัด:

$xml = simplexml_load_string($xml_string);
$json = json_encode($xml);
$array = json_decode($json,TRUE);

ตาดา!


7

มีเหตุผลหลายประการที่จะไม่แยกวิเคราะห์ HTML ตามนิพจน์ทั่วไป แต่ถ้าคุณมีการควบคุมทั้งหมดว่า HTML ใดที่จะถูกสร้างขึ้นคุณสามารถทำได้ด้วยการแสดงออกปกติอย่างง่าย

ด้านบนเป็นฟังก์ชันที่แยกวิเคราะห์ HTML ตามนิพจน์ทั่วไป โปรดทราบว่าฟังก์ชั่นนี้มีความละเอียดอ่อนมากและต้องการให้ HTML ปฏิบัติตามกฎบางอย่าง แต่ทำงานได้ดีในหลาย ๆ สถานการณ์ หากคุณต้องการเครื่องมือแยกวิเคราะห์อย่างง่ายและไม่ต้องการติดตั้งไลบรารีให้ลองทำดังนี้

function array_combine_($keys, $values) {
    $result = array();
    foreach ($keys as $i => $k) {
        $result[$k][] = $values[$i];
    }
    array_walk($result, create_function('&$v', '$v = (count($v) == 1)? array_pop($v): $v;'));

    return $result;
}

function extract_data($str) {
    return (is_array($str))
        ? array_map('extract_data', $str)
        : ((!preg_match_all('#<([A-Za-z0-9_]*)[^>]*>(.*?)</\1>#s', $str, $matches))
            ? $str
            : array_map(('extract_data'), array_combine_($matches[1], $matches[2])));
}

print_r(extract_data(file_get_contents("http://www.google.com/")));

2

ฉันได้สร้างห้องสมุดชื่อ HTML5DOMDocument ที่สามารถใช้ได้อย่างอิสระที่https://github.com/ivopetkov/html5-dom-document-php

รองรับตัวเลือกข้อความค้นหาด้วยซึ่งฉันคิดว่าจะเป็นประโยชน์อย่างยิ่งในกรณีของคุณ นี่คือตัวอย่างรหัส:

$dom = new IvoPetkov\HTML5DOMDocument();
$dom->loadHTML('<!DOCTYPE html><html><body><h1>Hello</h1><div class="content">This is some text</div></body></html>');
echo $dom->querySelector('h1')->innerHTML;

0

หากคุณคุ้นเคยกับตัวเลือก jQuery คุณสามารถใช้ScarletsQueryสำหรับ PHP

<pre><?php
include "ScarletsQuery.php";

// Load the HTML content and parse it
$html = file_get_contents('https://www.lipsum.com');
$dom = Scarlets\Library\MarkupLanguage::parseText($html);

// Select meta tag on the HTML header
$description = $dom->selector('head meta[name="description"]')[0];

// Get 'content' attribute value from meta tag
print_r($description->attr('content'));

$description = $dom->selector('#Content p');

// Get element array
print_r($description->view);

ไลบรารีนี้มักใช้เวลาน้อยกว่า 1 วินาทีในการประมวลผล html ออฟไลน์
นอกจากนี้ยังยอมรับ HTML ที่ไม่ถูกต้องหรือเครื่องหมายคำพูดที่หายไปในแอตทริบิวต์แท็ก


0

วิธีที่ดีที่สุดสำหรับการแยกวิเคราะห์ xml:

$xml='http://www.example.com/rss.xml';
$rss = simplexml_load_string($xml);
$i = 0;
foreach ($rss->channel->item as $feedItem) {
  $i++;
  echo $title=$feedItem->title;
  echo '<br>';
  echo $link=$feedItem->link;
  echo '<br>';
  if($feedItem->description !='') {
    $des=$feedItem->description;
  } else {
    $des='';
  }
  echo $des;
  echo '<br>';
  if($i>5) break;
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.