Como você analisa e processa HTML / XML em PHP?

Respostas:

1897

Extensões XML nativas

Eu prefiro usar uma das extensões XML nativas, pois elas são fornecidas com o PHP, geralmente são mais rápidas que todas as bibliotecas de terceiros e me dão todo o controle necessário sobre a marcação.

DOM

A extensão DOM permite que você opere em documentos XML por meio da API DOM com PHP 5. É uma implementação do Document Object Model Core Level 3 do W3C, uma interface neutra em plataforma e idioma que permite que programas e scripts acessem e atualizem dinamicamente o conteúdo, estrutura e estilo dos documentos.

O DOM é capaz de analisar e modificar o HTML do mundo real (quebrado) e pode fazer consultas XPath . É baseado em libxml .

Leva algum tempo para ser produtivo com o DOM, mas esse tempo vale a pena IMO. Como o DOM é uma interface independente de idioma, você encontrará implementações em vários idiomas; portanto, se precisar alterar sua linguagem de programação, é provável que você já saiba como usar a API DOM dessa linguagem.

Um exemplo de uso básico pode ser encontrado em Agarrando o atributo href de um elemento A e uma visão geral conceitual geral pode ser encontrada em DOMDocument no php

Como usar a extensão DOM foi abordada extensivamente no StackOverflow , portanto, se você optar por usá-la, pode ter certeza de que a maioria dos problemas encontrados pode ser resolvida pesquisando / navegando no Stack Overflow.

XMLReader

A extensão XMLReader é um analisador de recebimento XML. O leitor age como um cursor avançando no fluxo de documentos e parando em cada nó no caminho.

O XMLReader, como o DOM, é baseado em libxml. Não sei como acionar o HTML Parser Module, portanto, as chances de usar o XMLReader para analisar HTML quebrado podem ser menos robustas do que usar o DOM, onde você pode explicitamente dizer a ele para usar o HTML Parser Module da libxml.

Um exemplo básico de uso pode ser encontrado na obtenção de todos os valores das tags h1 usando php

Analisador de XML

Essa extensão permite criar analisadores XML e definir manipuladores para diferentes eventos XML. Cada analisador XML também possui alguns parâmetros que você pode ajustar.

A biblioteca XML Parser também é baseada na libxml e implementa um analisador push XML estilo SAX . Pode ser uma escolha melhor para gerenciamento de memória que o DOM ou o SimpleXML, mas será mais difícil trabalhar com o analisador de pull implementado pelo XMLReader.

SimpleXml

A extensão SimpleXML fornece um conjunto de ferramentas muito simples e facilmente utilizável para converter XML em um objeto que pode ser processado com seletores de propriedades normais e iteradores de matriz.

SimpleXML é uma opção quando você sabe que o HTML é XHTML válido. Se você precisar analisar HTML quebrado, nem considere o SimpleXml, pois ele engasga.

Um exemplo de uso básico pode ser encontrado em Um programa simples para o nó CRUD e os valores do nó do arquivo xml e há muitos exemplos adicionais no Manual do PHP .


Bibliotecas de terceiros (com base em libxml)

Se você preferir usar uma lib de terceiros, sugiro usar uma lib que realmente use DOM / libxml por baixo, em vez de análise de string.

FluentDom - Repo

O FluentDOM fornece uma interface XML fluente semelhante a jQuery para o DOMDocument em PHP. Os seletores são escritos em XPath ou CSS (usando um conversor de CSS para XPath). As versões atuais estendem o DOM implementando interfaces padrão e adicionam recursos do DOM Living Standard. O FluentDOM pode carregar formatos como JSON, CSV, JsonML, RabbitFish e outros. Pode ser instalado via Composer.

HtmlPageDom

Wa72 \ HtmlPageDom` é uma biblioteca PHP para fácil manipulação de documentos HTML usando o Requer o DomCrawler dos componentes Symfony2 para percorrer a árvore DOM e a estende adicionando métodos para manipular a árvore DOM dos documentos HTML.

phpQuery (não atualizado por anos)

O phpQuery é uma API DOM (Document Object Model) orientada por seletor CSS3, encadeada e do servidor, baseada na biblioteca jQuery JavaScript escrita em PHP5 e fornece interface de linha de comando (CLI) adicional.

Consulte também: https://github.com/electrolinux/phpquery

Zend_Dom

O Zend_Dom fornece ferramentas para trabalhar com documentos e estruturas DOM. Atualmente, oferecemos o Zend_Dom_Query, que fornece uma interface unificada para consultar documentos DOM utilizando os seletores XPath e CSS.

QueryPath

QueryPath é uma biblioteca PHP para manipular XML e HTML. Ele foi projetado para funcionar não apenas com arquivos locais, mas também com serviços da web e recursos de banco de dados. Ele implementa grande parte da interface do jQuery (incluindo seletores no estilo CSS), mas é fortemente ajustado para uso no servidor. Pode ser instalado via Composer.

fDOMDocument

O fDOMDocument estende o DOM padrão para usar exceções em todas as ocasiões de erros, em vez de avisos ou avisos do PHP. Eles também adicionam vários métodos e atalhos personalizados por conveniência e para simplificar o uso do DOM.

sabre / xml

O sabre / xml é uma biblioteca que agrupa e estende as classes XMLReader e XMLWriter para criar um sistema de mapeamento e um padrão de design simples "xml to object / array". Escrever e ler XML é de passagem única e, portanto, pode ser rápido e requer pouca memória em arquivos xml grandes.

FluidXML

FluidXML é uma biblioteca PHP para manipular XML com uma API concisa e fluente. Ele utiliza o XPath e o padrão de programação fluente para ser divertido e eficaz.


Terceiros (não baseados em libxml)

O benefício de desenvolver o DOM / libxml é que você obtém um bom desempenho pronto para uso, porque se baseia em uma extensão nativa. No entanto, nem todas as bibliotecas de terceiros seguem esse caminho. Alguns deles listados abaixo

Analisador DOM HTML Simples em PHP

  • Um analisador HTML DOM escrito em PHP5 + permite manipular HTML de uma maneira muito fácil!
  • Requer PHP 5+.
  • Suporta HTML inválido.
  • Encontre tags em uma página HTML com seletores como o jQuery.
  • Extraia o conteúdo do HTML em uma única linha.

Eu geralmente não recomendo este analisador. A base de código é horrível e o analisador em si é bastante lento e tem muita memória. Nem todos os seletores jQuery (como seletores filhos ) são possíveis. Qualquer uma das bibliotecas baseadas em libxml deve superar isso facilmente.

Analisador de HTML Html

O PHPHtmlParser é um analisador html simples e flexível que permite selecionar tags usando qualquer seletor de css, como o jQuery. O objetivo é ajudar no desenvolvimento de ferramentas que exigem uma maneira rápida e fácil de descartar html, válido ou não! Este projeto foi originalmente suportado pelo sunra / php-simple-html-dom-parser, mas o suporte parece ter parado, portanto este projeto é a minha adaptação do seu trabalho anterior.

Novamente, eu não recomendaria este analisador. É bastante lento com alto uso da CPU. Também não há função para limpar a memória dos objetos DOM criados. Esses problemas escalam particularmente com loops aninhados. A documentação em si é imprecisa e com erros de ortografia, sem respostas para correções desde 14 de abril de 16.

Ganon

  • Um tokenizador universal e um analisador DOM HTML / XML / RSS
    • Capacidade de manipular elementos e seus atributos
    • Suporta HTML e UTF8 inválidos
  • Pode executar consultas avançadas do tipo CSS3 em elementos (como jQuery - namespaces suportados)
  • Um embelezador de HTML (como HTML Tidy)
    • Minimize CSS e Javascript
    • Classificar atributos, alterar maiúsculas e minúsculas, recuar corretamente, etc.
  • Extensível
    • Analisando documentos usando retornos de chamada com base no caractere / token atual
    • Operações separadas em funções menores para facilitar a substituição
  • Rápido e Fácil

Nunca usei. Não posso dizer se é bom.


HTML 5

Você pode usar o acima para analisar o HTML5, mas pode haver peculiaridades devido à marcação permitida pelo HTML5. Portanto, para HTML5, você deseja considerar o uso de um analisador dedicado, como

html5lib

Implementações em Python e PHP de um analisador de HTML com base na especificação WHATWG HTML5 para obter compatibilidade máxima com os principais navegadores da Web para desktop.

Poderemos ver mais analisadores dedicados após a finalização do HTML5. Há também um post do blog do W3 intitulado How-To for html 5, que vale a pena conferir.


Serviços web

Se você não gosta de programar PHP, também pode usar serviços da Web. Em geral, encontrei muito pouca utilidade para eles, mas somos apenas eu e meus casos de uso.

ScraperWiki .

A interface externa do ScraperWiki permite extrair dados da forma que você deseja usar na Web ou em seus próprios aplicativos. Você também pode extrair informações sobre o estado de qualquer raspador.


Expressões regulares

Por último e menos recomendado , você pode extrair dados do HTML com expressões regulares . Em geral, o uso de expressões regulares no HTML é desencorajado.

A maioria dos trechos que você encontrará na web para corresponder à marcação são quebradiços. Na maioria dos casos, eles estão trabalhando apenas para um pedaço muito específico de HTML. Pequenas alterações de marcação, como adicionar espaço em branco em algum lugar, adicionar ou alterar atributos em uma tag, podem fazer com que o RegEx falhe quando não for gravado corretamente. Você deve saber o que está fazendo antes de usar o RegEx em HTML.

Os analisadores de HTML já conhecem as regras sintáticas do HTML. Expressões regulares devem ser ensinadas para cada novo RegEx que você escreve. O RegEx é bom em alguns casos, mas realmente depende do seu caso de uso.

Você pode escrever analisadores mais confiáveis , mas escrever um analisador personalizado completo e confiável com expressões regulares é um desperdício de tempo quando as bibliotecas mencionadas já existem e fazem um trabalho muito melhor nisso.

Consulte também Análise de HTML da maneira Cthulhu


Livros

Se você quiser gastar algum dinheiro, dê uma olhada

Eu não sou afiliado ao PHP Architect ou aos autores.

Gordon
fonte
10
@Naveed que depende de suas necessidades. Não tenho necessidade de consultas CSS Selector, e é por isso que uso exclusivamente o DOM com XPath. O phpQuery pretende ser uma porta jQuery. Zend_Dom é leve. Você realmente precisa vê-los para ver qual deles você mais gosta.
26710 Gordon
2
@ Ms2ger Principalmente, mas não completamente. Como já apontado acima, você pode usar os analisadores baseados em libxml, mas há casos especiais em que eles serão bloqueados. Se você precisar de compatibilidade máxima, será melhor usar um analisador dedicado. Eu prefiro manter a distinção.
Gordon
9
Seu argumento por não usar o PHP Simple HTML DOM Parser parece discutível.
Petah
3
Em 29 de março de 2012, o DOM não suporta html5, o XMLReader não suporta HTML e o último commit no html5lib para PHP é em setembro de 2009. O que usar para analisar HTML5, HTML4 e XHTML?
Shiplu Mokaddim 29/03/12
4
@Nasha Excluí deliberadamente o infame discurso de Zalgo da lista acima, porque não é muito útil por si só e leva a um certo culto à carga desde que foi escrito. As pessoas foram agredidas com esse link, por mais apropriado que um regex fosse como solução. Para uma opinião mais equilibrada, consulte o link que eu queria incluir em vez e ir através dos comentários no stackoverflow.com/questions/4245008/...
Gordon
322

Experimente o Analisador HTML DOM Simples

  • Um analisador HTML DOM escrito em PHP 5+ que permite manipular HTML de uma maneira muito fácil!
  • Requer PHP 5+.
  • Suporta HTML inválido.
  • Encontre tags em uma página HTML com seletores como o jQuery.
  • Extraia o conteúdo do HTML em uma única linha.
  • Baixar


Exemplos:

Como obter elementos 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>';


Como modificar elementos 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;


Extrair conteúdo do HTML:

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


Raspando 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);
Naveed
fonte
8
Bem, em primeiro lugar, há coisas que eu preciso preparar, como DOMs ruins, código Invlid, também js analisando contra o mecanismo DNSBL, isso também será usado para procurar sites / conteúdos maliciosos, assim como eu construí meu site em torno de uma estrutura. construído, ele precisa ser limpo, legível e bem estruturado. SimpleDim é grande, mas o código é um pouco confuso
RobertPitt
9
@ Robert, você também pode querer dar uma olhada no htmlpurifier.org para obter informações relacionadas à segurança.
Gordon
3
Ele tem um ponto válido: é difícil estender o simpleHTMLDOM, a menos que você use o padrão decorador, o que acho difícil de manejar. Eu me senti tremendo só de fazer alterações nas classes subjacentes.
Erik
1
O que eu fiz foi executar meu html com arrumação antes de enviá-lo para o SimpleDOM.
precisa saber é o seguinte
1
Atualmente, estou usando isso, executando-o como parte de um projeto para processar algumas centenas de URLs. Está se tornando muito lento e os intervalos regulares persistem. É um ótimo roteiro para iniciantes e intuitivamente simples de aprender, mas básico demais para projetos mais avançados.
luke_mclachlan
236

Basta usar DOMDocument-> loadHTML () e pronto. O algoritmo de análise de HTML do libxml é bastante bom e rápido, e, contrariamente à crença popular, não se engasga com HTML malformado.

Edward Z. Yang
fonte
19
Verdade. E funciona com as classes XPath e XSLTProcessor do PHP, ótimas para extrair conteúdo.
Kornel
8
Para HTML realmente confuso, você sempre pode executá-lo através do htmltidy antes de entregá-lo ao DOM. Sempre que preciso raspar dados do HTML, sempre uso o DOM, ou pelo menos simplexml.
Frank fazendeiro
9
Outra coisa com o carregamento de HTML i malformado, que seria sensato chamar libxml_use_internal_errors (true) para evitar avisos que parem de analisar.
Husky
6
Eu usei o DOMDocument para analisar cerca de 1000 fontes html (em vários idiomas codificados com diferentes conjuntos de caracteres) sem problemas. Você pode ter problemas de codificação com isso, mas eles não são intransponíveis. Você precisa saber três coisas: 1) o loadHTML usa o charset da meta tag para determinar a codificação 2) # 2 pode levar à detecção incorreta de codificação se o conteúdo html não incluir essas informações 3) caracteres UTF-8 ruins podem desarmar o analisador. Nesses casos, use uma combinação de codificação / conversão / remoção de mb_detect_encoding () e do Simplepie RSS Parser para soluções alternativas.
Zero
1
O DOM realmente suporta XPath, dê uma olhada no DOMXPath .
Ryan McCue
147

Por que você não deveria e quando deveria usar expressões regulares?

Primeiro, um equívoco comum: as regexps não são para " analisar " o HTML. Regexes podem, no entanto, " extrair " dados. Extrair é para isso que eles são feitos. A principal desvantagem da extração de regex HTML sobre kits de ferramentas SGML adequados ou analisadores XML de linha de base é o esforço sintático e a confiabilidade variável.

Considere a criação de uma regex de extração HTML um tanto confiável:

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

é muito menos legível do que um simples equivalente phpQuery ou QueryPath:

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

No entanto, existem casos de uso específicos em que eles podem ajudar.

  • Muitas interfaces de travessia do DOM não revelam comentários em HTML <!--, que às vezes são as âncoras mais úteis para a extração. Em particular, variações pseudo-HTML <$var>ou resíduos SGML são fáceis de domar com regexps.
  • Muitas vezes, expressões regulares podem salvar o pós-processamento. No entanto, as entidades HTML geralmente exigem cuidados manuais.
  • E, finalmente, para tarefas extremamente simples como extrair <img src = urls, elas são de fato uma ferramenta provável. A vantagem da velocidade em relação aos analisadores SGML / XML geralmente vem para esses procedimentos de extração muito básicos.

Às vezes, é aconselhável pré-extrair um trecho de HTML usando expressões regulares /<!--CONTENT-->(.+?)<!--END-->/e processar o restante usando as interfaces mais simples do analisador de HTML.

Nota: Na verdade, eu tenho esse aplicativo , onde utilizo a análise XML e expressões regulares como alternativa. Na semana passada, a análise do PyQuery foi interrompida e o regex ainda funcionou. Sim estranho, e eu não posso explicar isso sozinho. Mas aconteceu.
Portanto, não vote em considerações do mundo real, apenas porque não corresponde ao meme regex = evil. Mas também não vamos votar muito nisso. É apenas uma nota lateral para este tópico.

mario
fonte
20
DOMCommentpode ler comentários, então não há razão para usar o Regex para isso.
Gordon
4
Nem os kits de ferramentas SGML nem os analisadores XML são adequados para analisar o HTML do mundo real. Para isso, apenas um analisador HTML dedicado é apropriado.
Alohci
12
O @Alohci DOMusa libxml e o libxml possui um módulo analisador de HTML separado , que será usado ao carregar o HTML, loadHTML()para que ele possa carregar muito o HTML "real" (leia quebrado).
Gordon
6
Bem, apenas um comentário sobre o seu ponto de vista "consideração do mundo real". Claro, existem situações úteis para o Regex ao analisar o HTML. E também existem situações úteis para usar o GOTO. E há situações úteis para variáveis-variáveis. Portanto, nenhuma implementação específica é definitivamente rot-code para usá-la. Mas é um sinal de alerta MUITO forte. E o desenvolvedor médio provavelmente não terá matizes suficientes para dizer a diferença. Portanto, como regra geral, o Regex GOTO e o Variable-Variables são todos maus. Há usos não-malignas, mas essas são as exceções (e rara em que) ... (IMHO)
ircmaxell
11
@ mario: Na verdade, o HTML pode ser 'adequadamente' analisado usando expressões regulares, embora normalmente sejam necessários vários deles para fazer um trabalho justo. É apenas uma dor real no caso geral. Em casos específicos, com entrada bem definida, ela é trivial. Esses são os casos em que as pessoas devem estar usando expressões regulares. Analisadores pesados ​​velhos e com fome são realmente o que você precisa para casos gerais, embora nem sempre seja claro para o usuário casual onde traçar essa linha. Qualquer que seja o código mais simples e fácil, ganha.
tchrist
131

O phpQuery e o QueryPath são extremamente semelhantes na replicação da API fluente do jQuery. É também por isso que são duas das abordagens mais fáceis para analisar corretamente o HTML no PHP.

Exemplos para QueryPath

Basicamente, você primeiro cria uma árvore DOM consultável a partir de uma string HTML:

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

O objeto resultante contém uma representação em árvore completa do documento HTML. Pode ser percorrido usando métodos DOM. Mas a abordagem comum é usar seletores CSS como no jQuery:

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

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

Principalmente você deseja usar seletores simples #ide .classou de DIVtag para ->find(). Mas você também pode usar instruções XPath , que às vezes são mais rápidas. Também métodos jQuery típicos, como ->children()e, ->text()particularmente, ->attr()simplificam a extração dos snippets HTML corretos. (E já têm suas entidades SGML decodificadas.)

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

O QueryPath também permite injetar novas tags no stream ( ->append) e, posteriormente, gerar e prettify um documento atualizado ( ->writeHTML). Ele não pode apenas analisar HTML malformado, mas também vários dialetos XML (com espaços para nome) e até extrair dados de microformatos HTML (XFN, vCard).

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

.

phpQuery ou QueryPath?

Geralmente, o QueryPath é mais adequado para manipulação de documentos. Enquanto o phpQuery também implementa alguns métodos pseudo AJAX (apenas solicitações HTTP) para se parecer mais com o jQuery. Dizem que o phpQuery geralmente é mais rápido que o QueryPath (devido a menos recursos gerais).

Para mais informações sobre as diferenças, consulte esta comparação na máquina de retorno de tagsbyte.org . (A fonte original desapareceu, então aqui está um link de arquivo da Internet. Sim, você ainda pode localizar as páginas ausentes, pessoas.)

E aqui está uma introdução abrangente ao QueryPath .

Vantagens

  • Simplicidade e Confiabilidade
  • Simples de usar alternativas ->find("a img, a object, div a")
  • Desescapamento de dados adequado (em comparação com grepping de expressão regular)
mario
fonte
88

O HTML simples DOM é um ótimo analisador de código-fonte aberto:

simplehtmldom.sourceforge

Ele trata os elementos DOM de maneira orientada a objetos, e a nova iteração tem muita cobertura para código não compatível. Também existem algumas funções excelentes, como as que você veria em JavaScript, como a função "find", que retornará todas as instâncias de elementos desse nome de tag.

Eu usei isso em várias ferramentas, testando-o em muitos tipos diferentes de páginas da web e acho que funciona muito bem.

Robert Elwell
fonte
61

Uma abordagem geral que não vi mencionada aqui é executar o HTML através do Tidy , que pode ser configurado para citar XHTML com garantia garantida. Em seguida, você pode usar qualquer biblioteca XML antiga.

Mas, para o seu problema específico, você deve dar uma olhada neste projeto: http://fivefilters.org/content-only/ - é uma versão modificada do algoritmo Readability , projetado para extrair apenas o conteúdo textual (não os cabeçalhos e rodapés) de uma página.

Eli
fonte
56

Para 1a e 2: eu votaria na nova classe DOMCrawler do Symfony Componet ( DomCrawler ). Essa classe permite consultas semelhantes aos seletores CSS. Dê uma olhada nesta apresentação para obter exemplos do mundo real: news-of-the-symfony2-world .

O componente foi projetado para funcionar de forma independente e pode ser usado sem o Symfony.

A única desvantagem é que ele funcionará apenas com o PHP 5.3 ou mais recente.

Timo
fonte
as consultas css do tipo jquery são bem ditas, porque há algumas coisas que estão faltando na documentação do w3c, mas estão presentes como recursos extras no jquery.
Nikola Petkanski
53

A propósito, isso geralmente é chamado de raspagem de tela . A biblioteca que usei para isso é o Simple HTML Dom Parser .

Joel Verhagen
fonte
8
Não é rigorosamente verdade ( en.wikipedia.org/wiki/Screen_scraping#Screen_scraping ). A pista está na "tela"; no caso descrito, não há tela envolvida. Embora, reconhecidamente, o termo tenha sofrido uma enorme quantidade de uso indevido recente.
Bobby Jack
4
Não estou raspando a tela, o conteúdo que será analisado será autorizado pelo fornecedor do conteúdo sob meu contrato.
RobertPitt 26/08/10
41

Criamos alguns rastreadores para nossas necessidades antes. No final do dia, geralmente são simples expressões regulares que fazem o melhor. Embora as bibliotecas listadas acima sejam boas pelo motivo de serem criadas, se você souber o que está procurando, expressões regulares são um caminho mais seguro, pois você também pode lidar com estruturas HTML / XHTML não válidas , que falhariam se carregadas através da maioria dos analisadores.

jancha
fonte
38

Eu recomendo o PHP Simple HTML DOM Parser .

Ele realmente possui recursos interessantes, como:

foreach($html->find('img') as $element)
       echo $element->src . '<br>';
Greg
fonte
36

Parece uma boa descrição da tarefa da tecnologia W3C XPath . É fácil expressar consultas como "retornar todos os hrefatributos em imgtags aninhadas <foo><bar><baz> elements". Não sendo um fã de PHP, não posso dizer de que forma o XPath pode estar disponível. Se você pode chamar um programa externo para processar o arquivo HTML, poderá usar uma versão de linha de comando do XPath. Para uma introdução rápida, consulte http://en.wikipedia.org/wiki/XPath .

Jens
fonte
29

Alternativas de terceiros ao SimpleHtmlDom que usam DOM em vez de Análise de String: phpQuery , Zend_Dom , QueryPath e FluentDom .

Amal Murali
fonte
3
Se você já copiou meus comentários, pelo menos os vincule corretamente;) Isso deve ser: Alternativas de terceiros sugeridas ao SimpleHtmlDom que realmente usam o DOM em vez de Análise de String: phpQuery , Zend_Dom , QueryPath e FluentDom .
Gordon
1
Boas respostas são uma ótima fonte. stackoverflow.com/questions/3606792/…
danidacar 8/8
24

Sim, você pode usar simple_html_dom para esse fim. No entanto, eu trabalhei bastante com o simple_html_dom, principalmente para demolição na Web e achei que era muito vulnerável. Ele faz o trabalho básico, mas não o recomendo.

Eu nunca usei o curl para esse fim, mas o que aprendi é que o curl pode fazer o trabalho com muito mais eficiência e é muito mais sólido.

Por favor, verifique este link: scraping-websites-with-curl

Rafay
fonte
2
o curl pode obter o arquivo, mas não analisa HTML para você. Essa é a parte mais difícil.
cHao
23

O QueryPath é bom, mas tenha cuidado com o "estado de rastreamento" porque, se você não percebeu o que significa, pode significar que você perde muito tempo de depuração tentando descobrir o que aconteceu e por que o código não funciona.

O que isso significa é que cada chamada no conjunto de resultados modifica o conjunto de resultados no objeto, não é encadeada como no jquery, onde cada link é um novo conjunto, você tem um único conjunto que é o resultado da sua consulta e cada chamada de função modifica esse conjunto único.

para obter um comportamento semelhante ao jquery, você precisa ramificar antes de fazer uma operação de filtro / modificação semelhante, o que significa que ele refletirá o que acontece no jquery muito mais de perto.

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

$resultsagora contém o conjunto de resultados para input[name='forename']NÃO a consulta original que "div p"me causou muitas desilusões, o que descobri foi que o QueryPath rastreia os filtros e as descobertas e tudo o que modifica seus resultados e os armazena no objeto. você precisa fazer isso

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

então $resultsnão será modificado e você poderá reutilizar o conjunto de resultados repetidamente; talvez alguém com muito mais conhecimento possa esclarecer um pouco isso, mas é basicamente assim pelo que encontrei.

Christopher Thomas
fonte
20

Advanced Html Dom é uma substituição simples de DOM em HTML que oferece a mesma interface, mas é baseada em DOM, o que significa que nenhum dos problemas de memória associados ocorre.

Ele também oferece suporte completo a CSS, incluindo extensões jQuery .

pguardiario
fonte
Obtive bons resultados do Advanced Html Dom e acho que deve constar na lista da resposta aceita. Porém, é importante saber para quem se apóia "O objetivo deste projeto é ser um substituto baseado em DOM para a biblioteca simples de html dom do PHP ... Se você usa file / str_get_html, não precisa mudar qualquer coisa. " archive.is/QtSuj#selection-933.34-933.100 é que você pode precisar fazer alterações no seu código para acomodar algumas incompatibilidades. Observei quatro conhecidos por mim nas questões do github do projeto. github.com/monkeysuffrage/advanced_html_dom/issues
ChrisJJ
Trabalhou! Obrigado
Faisal Shani
18

Para HTML5 , a html5 lib foi abandonada há anos. A única biblioteca HTML5 que posso encontrar com registros recentes de atualização e manutenção é o html5-php, que foi trazido para a beta 1.0 há pouco mais de uma semana.

Reid Johnson
fonte
17

Eu escrevi um analisador XML de uso geral que pode lidar facilmente com arquivos GB. É baseado no XMLReader e é muito fácil de usar:

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

Aqui está o repositório do github: XmlExtractor

Paul Warelis
fonte
17

Criei uma biblioteca chamada PHPPowertools / DOM-Query , que permite rastrear documentos HTML5 e XML, assim como você faz com o jQuery.

Sob o capô, ele usa o symfony / DomCrawler para converter seletores CSS em seletores XPath . Ele sempre usa o mesmo DomDocument, mesmo ao passar um objeto para outro, para garantir um desempenho decente.


Exemplo de uso:

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>');

[...]

Métodos suportados:


  1. Renomeado 'select', por razões óbvias
  2. Renomeado 'void', já que 'empty' é uma palavra reservada no PHP

NOTA :

A biblioteca também inclui seu próprio carregador automático de configuração zero para bibliotecas compatíveis com PSR-0. O exemplo incluído deve funcionar imediatamente, sem nenhuma configuração adicional. Como alternativa, você pode usá-lo com o compositor.

John Slegers
fonte
Parece a ferramenta certa para o trabalho, mas não está carregando para mim no PHP 5.6.23 no Worpress. Quaisquer instruções adicionais sobre como incluí-lo corretamente? Incluído com: define ("BASE_PATH", dirname ( FILE )); define ("LIBRARY_PATH", BASE_PATH. DIRECTORY_SEPARATOR. 'lib / vendor'); requer LIBRARY_PATH. DIRECTORY_SEPARATOR. 'Loader.php'; Loader :: init (matriz (LIBRARY_PATH, USER_PATH)); em functions.php
lithiumlab
15

Você pode tentar usar algo como HTML Tidy para limpar qualquer HTML "quebrado" e converter o HTML em XHTML, que poderá ser analisado com um analisador XML.

CesarB
fonte
15

Outra opção que você pode tentar é o QueryPath . É inspirado no jQuery, mas no servidor em PHP e usado no Drupal .

Ric
fonte
12

XML_HTMLSaxé bastante estável - mesmo que não seja mais mantido. Outra opção pode ser direcionar o HTML pelo Html Tidy e analisá-lo com ferramentas XML padrão.

Troelskn
fonte
11

A estrutura do Symfony possui pacotes configuráveis ​​que podem analisar o HTML, e você pode usar o estilo CSS para selecionar os DOMs em vez de usar o XPath .

Tuong Le
fonte
11

Existem várias maneiras de processar o DOM HTML / XML, dos quais a maioria já foi mencionada. Portanto, não tentarei listar esses dados pessoalmente.

Quero apenas acrescentar que pessoalmente prefiro usar a extensão DOM e por que:

  • O iit faz uso otimizado da vantagem de desempenho do código C subjacente
  • é OO PHP (e me permite subclassificá-lo)
  • é um nível bastante baixo (o que me permite usá-lo como uma base não inchada para comportamentos mais avançados)
  • fornece acesso a todas as partes do DOM (diferente de, por exemplo, o SimpleXml, que ignora alguns dos recursos XML menos conhecidos)
  • possui uma sintaxe usada para o rastreamento do DOM semelhante à sintaxe usada no Javascript nativo.

E, embora eu sinta falta da capacidade de usar seletores CSS DOMDocument, há uma maneira bastante simples e conveniente de adicionar esse recurso: subclassificar o DOMDocumente adicionar métodos querySelectorAlle querySelectormétodos JS à sua subclasse.

Para analisar os seletores, eu recomendo usar o componente CssSelector muito minimalista da estrutura do Symfony . Esse componente apenas converte seletores CSS em XPath, que podem ser alimentados em um DOMXpathpara recuperar o Nodelist correspondente.

Você pode então usar esta subclasse (ainda com nível muito baixo) como base para classes de mais alto nível, como por exemplo. analise tipos muito específicos de XML ou adicione mais comportamento semelhante ao jQuery.

O código abaixo vem diretamente da minha biblioteca DOM-Query e usa a técnica que descrevi.

Para análise de 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);
                }
            }
        }
    }

    [...]
}

Veja também Analisando documentos XML com seletores de CSS pelo criador do Symfony, Fabien Potencier, sobre sua decisão de criar o componente CssSelector para o Symfony e como usá-lo.

John Slegers
fonte
9

Com o FluidXML, você pode consultar e iterar XML usando os seletores XPath e CSS .

$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

Daniele Orlando
fonte
7

JSON e matriz de XML em três linhas:

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

Ta da!

Antonio Max
fonte
7

Há vários motivos para não analisar o HTML por expressões regulares. Mas, se você tiver controle total de qual HTML será gerado, poderá fazer isso com uma expressão regular simples.

Acima, é uma função que analisa HTML por expressão regular. Observe que essa função é muito sensível e exige que o HTML obedeça a certas regras, mas funciona muito bem em muitos cenários. Se você deseja um analisador simples e não deseja instalar bibliotecas, experimente:

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/")));
Daniel Loureiro
fonte
2

Eu criei uma biblioteca chamada HTML5DOMDocument que está disponível gratuitamente em https://github.com/ivopetkov/html5-dom-document-php

Ele também suporta seletores de consulta que eu acho que serão extremamente úteis no seu caso. Aqui está um exemplo de código:

$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;
Ivo Petkov
fonte
0

Se você estiver familiarizado com o seletor jQuery, poderá usar o ScarletsQuery para 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);

Essa biblioteca geralmente leva menos de 1 segundo para processar o html offline.
Também aceita HTML inválido ou aspas ausentes nos atributos da tag.

StefansArya
fonte
0

O melhor método para analisar 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;
}
user8031209
fonte