CMS e plataformas 11 min de leitura

Scraper para WordPress

Como fazer scraping para sites WordPress e preenchê-los com o conteúdo coletado: REST API, XML-RPC, plugins de importação e soluções sob medida.

EW
Equipe Web-Scraping.biz
Coleta de dados para as demandas do negócio
Publicado: 18 fevereiro 2025

O web scraping é uma das ferramentas mais requisitadas em sites feitos com WordPress. Com ele, você pode preencher o site de forma automática com conteúdo sempre atualizado: taxas de câmbio, notícias, previsão do tempo, produtos de fornecedores e muito mais. Neste artigo, veremos que plugins prontos existem, em que casos vale a pena escrever um scraper próprio em PHP e analisaremos quatro cenários práticos para integrar o scraping ao WordPress.

Se quiser se aprofundar na própria tecnologia de extração e análise de dados, recomendamos o material à parte «Web scraping em PHP», que descreve em detalhe os princípios de funcionamento, as bibliotecas (cURL, Guzzle, Simple HTML DOM, Symfony DomCrawler) e as armadilhas habituais. Aqui, o foco está justamente na integração com o WordPress.


O que é scraping no contexto do WordPress

O scraping (web scraping) é a coleta automática de dados de fontes externas: sites, APIs, feeds RSS, tabelas de preços. No WordPress, normalmente não basta obter esses dados; também é preciso:

  • salvá-los no banco de dados (como posts, produtos, metacampos ou options);
  • mantê-los em cache, para não sobrecarregar nem a fonte externa nem o próprio servidor;
  • atualizá-los de forma programada (via wp_cron ou o cron do sistema);
  • exibi-los no front-end (via shortcodes, widgets ou blocos do Gutenberg).

É justamente por isso que um «scraper para WordPress» não é um simples script que baixa alguma coisa, e sim um módulo completo, integrado ao ecossistema do CMS.


Panorama dos plugins existentes

Antes de escrever uma solução própria, faz sentido avaliar os plugins disponíveis. Eles cobrem muitas tarefas típicas sem uma única linha de código.

WP All Import

Uma das ferramentas de importação mais poderosas. Aceita XML, CSV e formatos de tabelas de preços, permite mapear visualmente os campos da fonte com os campos de posts, produtos do WooCommerce ou usuários. Suporta importação programada e atualização dos registros já importados. Encaixa bem no cenário dos produtos de um fornecedor, mas exige que a fonte entregue um feed estruturado.

Vantagens: mapeamento flexível, interface amigável, atualização confiável. Desvantagens: os recursos avançados estão na versão paga; não «scrapeia» páginas HTML arbitrárias sem um feed pronto.

Content Egg

Plugin agregador para marketing de afiliados e de conteúdo: sabe trazer produtos, preços, avaliações e outros conteúdos de uma infinidade de fontes e APIs. É usado com frequência para comparar preços e completar fichas de produto.

Vantagens: muitos módulos de origem prontos, templates de exibição. Desvantagens: é voltado a cenários específicos (afiliados, marketplaces) e tem lógica própria de apresentação.

WP RSS Aggregator / Feedzy

Plugins especializados na importação de feeds RSS e Atom. Permitem combinar vários feeds, filtrar por palavras-chave e converter os itens do feed em posts do WordPress.

Vantagens: configuração simples para notícias e RSS, filtragem e deduplicação. Desvantagens: ficam limitados ao formato de feed; não servem para HTML arbitrário.

Scrapers universais (WP Content Pilot, plugins de scraping)

Existem plugins capazes de extrair dados de páginas arbitrárias por meio de seletores CSS. São o que há de mais próximo de um scraper «de verdade», mas qualquer mudança no layout da fonte quebra a configuração, e é difícil implementar neles uma lógica complexa de pós-processamento.

Quando os plugins não bastam

As soluções prontas funcionam de maravilha enquanto a tarefa é padrão. Mas assim que aparece uma fonte atípica, uma lógica de transformação complexa, autenticação do lado do fornecedor ou requisitos específicos de cache, a flexibilidade do plugin deixa de ser suficiente. Nesse caso, escreve-se um scraper próprio.


Um scraper próprio em PHP dentro do WordPress

A grande vantagem de uma solução própria é o controle total. Você decide como obter os dados, como limpá-los, onde armazená-los e quando atualizá-los. O WordPress oferece um bom conjunto de ferramentas para isso, e não há nenhuma necessidade de recorrer ao file_get_contents «cru».

Os «tijolos» básicos sobre os quais se constrói qualquer scraper para WordPress:

php
// 1. Obtenção de dados: via HTTP API integrada do WordPress
$response = wp_remote_get( 'https://example.com/data', array(
    'timeout' => 15,
    'headers' => array( 'User-Agent' => 'MySiteBot/1.0' ),
) );

if ( is_wp_error( $response ) ) {
    error_log( 'Erro na requisição: ' . $response->get_error_message() );
    return;
}

$body = wp_remote_retrieve_body( $response );
php
// 2. Cache via Transients API, para não bater na fonte a cada exibição
function my_get_cached_data() {
    $cache_key = 'my_parser_data';
    $data = get_transient( $cache_key );

    if ( false === $data ) {
        $data = my_fetch_and_parse(); // sua função de scraping
        set_transient( $cache_key, $data, HOUR_IN_SECONDS );
    }

    return $data;
}
php
// 3. Atualização programada via WP-Cron
add_action( 'init', function () {
    if ( ! wp_next_scheduled( 'my_parser_update' ) ) {
        wp_schedule_event( time(), 'hourly', 'my_parser_update' );
    }
} );

add_action( 'my_parser_update', 'my_fetch_and_parse' );

A análise detalhada das bibliotecas de parsing de HTML, o tratamento de codificações, o contorno de proteções e a construção de um scraper robusto estão no material à parte «Web scraping em PHP». A seguir, nos apoiamos nesses princípios e mostramos justamente o que é específico do WordPress.

Passemos agora aos cenários concretos.


Cenário 1. Scraping de taxas de câmbio

Uma tarefa típica de loja virtual ou de site de conteúdo: exibir os preços em várias moedas ao mesmo tempo e convertê-los automaticamente. Como fonte servem os dados oficiais de um banco central — o Banco Central do Brasil, por exemplo, publica as cotações oficiais do boletim PTAX por meio de uma API pública. No exemplo abaixo usamos outra fonte clássica e estável, o feed XML do Banco Central Europeu com as taxas de referência do euro (que incluem o real); a lógica de integração com o WordPress é a mesma para qualquer uma das duas.

A lógica é simples: uma vez por dia baixamos o XML com as taxas de câmbio, fazemos o parsing, guardamos o resultado nas options do WordPress e o usamos na exibição dos preços.

php
function parse_currency_rates() {
    $url = 'https://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml'; // feed de taxas de referência do BCE
    $response = wp_remote_get( $url, array( 'timeout' => 15 ) );

    if ( is_wp_error( $response ) ) {
        return;
    }

    $xml = simplexml_load_string( wp_remote_retrieve_body( $response ) );
    if ( false === $xml ) {
        return;
    }

    $xml->registerXPathNamespace( 'e', 'http://www.ecb.int/vocabulary/2002-08-01/eurofxref' );

    $rates = array();
    foreach ( $xml->xpath( '//e:Cube[@currency]' ) as $cube ) {
        $code  = (string) $cube['currency'];          // USD, BRL ...
        $value = (float) $cube['rate'];
        $rates[ $code ] = $value;                     // unidades de moeda por 1 EUR
    }

    update_option( 'my_currency_rates', $rates );
    update_option( 'my_currency_rates_updated', current_time( 'mysql' ) );
}
add_action( 'my_currency_update', 'parse_currency_rates' );

Conversão de um preço para a moeda desejada:

php
function convert_price( $eur_amount, $currency = 'USD' ) {
    $rates = get_option( 'my_currency_rates', array() );
    if ( empty( $rates[ $currency ] ) ) {
        return $eur_amount;
    }
    return round( $eur_amount * $rates[ $currency ], 2 );
}

E um shortcode para exibir a taxa de câmbio em uma página:

php
add_shortcode( 'currency_rate', function ( $atts ) {
    $atts  = shortcode_atts( array( 'code' => 'USD' ), $atts );
    $rates = get_option( 'my_currency_rates', array() );
    $code  = strtoupper( $atts['code'] );

    return isset( $rates[ $code ] )
        ? esc_html( '1 € = ' . number_format( $rates[ $code ], 2 ) . ' ' . $code )
        : '—';
} );
// Uso: [currency_rate code="BRL"]

A análise completa dos formatos XML/JSON dos bancos centrais, do trabalho com várias moedas e do cálculo de taxas cruzadas está no material específico «Scraping de taxas de câmbio».


Cenário 2. Scraping de notícias e RSS

O segundo cenário popular é preencher o site com notícias automaticamente. Aqui o WordPress traz um bônus agradável: o núcleo já inclui um parser de feeds integrado, fetch_feed(), baseado na biblioteca SimplePie. É a forma mais confiável de trabalhar com RSS sem reinventar a roda.

php
function import_news_from_rss( $feed_url ) {
    include_once ABSPATH . WPINC . '/feed.php';

    $feed = fetch_feed( $feed_url );
    if ( is_wp_error( $feed ) ) {
        return;
    }

    $max_items = $feed->get_item_quantity( 10 );
    $items     = $feed->get_items( 0, $max_items );

    foreach ( $items as $item ) {
        $guid = $item->get_id();

        // Proteção contra duplicatas: buscamos um post com o mesmo GUID de origem
        $existing = get_posts( array(
            'meta_key'   => '_source_guid',
            'meta_value' => $guid,
            'post_type'  => 'post',
            'fields'     => 'ids',
        ) );
        if ( $existing ) {
            continue;
        }

        $post_id = wp_insert_post( array(
            'post_title'   => sanitize_text_field( $item->get_title() ),
            'post_content' => wp_kses_post( $item->get_content() ),
            'post_date'    => $item->get_date( 'Y-m-d H:i:s' ),
            'post_status'  => 'draft', // vai para moderação, para evitar conteúdo lixo
            'post_type'    => 'post',
        ) );

        if ( $post_id && ! is_wp_error( $post_id ) ) {
            update_post_meta( $post_id, '_source_guid', $guid );
        }
    }
}

Disparamos a importação de forma programada:

php
add_action( 'my_news_import', function () {
    import_news_from_rss( 'https://example.com/feed/' );
} );

Se a fonte não oferece RSS e as notícias precisam ser tiradas diretamente da página HTML por meio de seletores, isso já é scraping de verdade, com análise do layout. Projetos desse tipo nós entregamos prontos como serviço de extração de artigos de imprensa: configuramos a extração de manchetes, datas, imagens e texto de sites arbitrários, levando em conta a estrutura de cada um.

As nuances do trabalho com feeds, os formatos RSS 2.0 e Atom, a filtragem e a combinação de várias fontes são tratados no artigo à parte sobre RSS.


Cenário 3. Scraping da previsão do tempo

Um widget de previsão do tempo é um pedido frequente de portais regionais, sites de hotéis e agências de viagem. Os dados costumam vir de uma API meteorológica que devolve JSON. A tarefa, no contexto do WordPress, consiste em integrar esse widget ao site com cuidado: obter a previsão, mantê-la em cache por um período curto e exibi-la por meio de um shortcode ou bloco.

php
function get_weather( $city = 'Sao Paulo' ) {
    $cache_key = 'weather_' . sanitize_key( $city );
    $weather   = get_transient( $cache_key );

    if ( false !== $weather ) {
        return $weather; // servimos direto do cache
    }

    $url = add_query_arg( array(
        'q'     => $city,
        'units' => 'metric',
        'lang'  => 'pt_br',
        'appid' => 'YOUR_API_KEY',
    ), 'https://api.example-weather.com/data/forecast' );

    $response = wp_remote_get( $url, array( 'timeout' => 10 ) );
    if ( is_wp_error( $response ) ) {
        return null;
    }

    $data = json_decode( wp_remote_retrieve_body( $response ), true );

    $weather = array(
        'temp'        => $data['main']['temp'] ?? null,
        'description' => $data['weather'][0]['description'] ?? '',
        'icon'        => $data['weather'][0]['icon'] ?? '',
    );

    // O tempo muda com frequência: cache de apenas 30 minutos
    set_transient( $cache_key, $weather, 30 * MINUTE_IN_SECONDS );

    return $weather;
}

Shortcode para inserir o widget em qualquer post ou página:

php
add_shortcode( 'weather', function ( $atts ) {
    $atts    = shortcode_atts( array( 'city' => 'Sao Paulo' ), $atts );
    $weather = get_weather( $atts['city'] );

    if ( empty( $weather ) ) {
        return '<span class="weather-error">Previsão indisponível</span>';
    }

    return sprintf(
        '<div class="weather-widget">
            <span class="weather-city">%s</span>
            <span class="weather-temp">%s°C</span>
            <span class="weather-desc">%s</span>
        </div>',
        esc_html( $atts['city'] ),
        esc_html( round( $weather['temp'] ) ),
        esc_html( $weather['description'] )
    );
} );
// Uso: [weather city="Rio de Janeiro"]

Os pontos-chave específicos do WordPress: um TTL de cache curto (a previsão expira rápido), a exibição via shortcode/widget e o escape obrigatório dos dados antes de mostrá-los.

O guia completo sobre as fontes de dados meteorológicos, o parsing de previsões de vários dias e o tratamento da geolocalização está no material sobre scraping de dados meteorológicos; aqui, olhamos justamente pela ótica da integração em um site WordPress.


Cenário 4. Scraping do site de um fornecedor e importação de produtos para o WooCommerce

O cenário mais completo: preencher automaticamente uma loja virtual com os produtos de um fornecedor. A fonte pode ser uma tabela de preços (CSV/XML) ou o próprio site do fornecedor, que precisa ser analisado a partir do HTML. O resultado é importado para o WooCommerce na forma de produtos com preços, estoque, imagens e categorias.

Vejamos a importação a partir de um feed estruturado (a variante mais estável):

php
function import_supplier_products() {
    // Proteção contra execuções em paralelo
    if ( get_transient( 'import_lock' ) ) {
        return;
    }
    set_transient( 'import_lock', 1, 10 * MINUTE_IN_SECONDS );

    $response = wp_remote_get( 'https://supplier.example.com/price.xml', array(
        'timeout' => 60,
    ) );

    if ( is_wp_error( $response ) ) {
        delete_transient( 'import_lock' );
        return;
    }

    $xml = simplexml_load_string( wp_remote_retrieve_body( $response ) );

    foreach ( $xml->offer as $offer ) {
        $sku   = (string) $offer->sku;
        $name  = (string) $offer->name;
        $price = (float) $offer->price;
        $stock = (int) $offer->stock;

        upsert_product( $sku, $name, $price, $stock, (string) $offer->picture );
    }

    delete_transient( 'import_lock' );
}

A função «criar ou atualizar» produto (upsert): busca o produto pelo código (SKU) e, ou atualiza o existente, ou cria um novo:

php
function upsert_product( $sku, $name, $price, $stock, $image_url = '' ) {
    $product_id = wc_get_product_id_by_sku( $sku );

    if ( $product_id ) {
        // O produto já existe: atualizamos apenas o preço e o estoque
        $product = wc_get_product( $product_id );
    } else {
        // Produto novo
        $product = new WC_Product_Simple();
        $product->set_sku( $sku );
        $product->set_name( $name );

        // A imagem é baixada apenas na criação do produto
        if ( $image_url ) {
            $attach_id = media_sideload_image( $image_url, 0, $name, 'id' );
            if ( ! is_wp_error( $attach_id ) ) {
                $product->set_image_id( $attach_id );
            }
        }
    }

    $product->set_regular_price( (string) $price );
    $product->set_stock_quantity( $stock );
    $product->set_manage_stock( true );
    $product->set_stock_status( $stock > 0 ? 'instock' : 'outofstock' );

    $product->save();
}

Disparo da importação de forma programada (por exemplo, duas vezes ao dia):

php
add_action( 'init', function () {
    if ( ! wp_next_scheduled( 'supplier_import_event' ) ) {
        wp_schedule_event( time(), 'twicedaily', 'supplier_import_event' );
    }
} );
add_action( 'supplier_import_event', 'import_supplier_products' );

A que prestar atenção neste cenário:

  • Identificação por SKU. O código é a chave mais confiável para o pareamento de produtos entre o fornecedor e a loja.
  • As imagens são baixadas uma única vez. media_sideload_image() é uma operação cara; não deve ser repetida a cada atualização.
  • Processamento em lotes. Tabelas de preços grandes (dezenas de milhares de SKUs) convém processar por partes (batch), para não esbarrar nos limites de tempo e de memória do PHP.
  • Retirada de venda. Os produtos que somem da tabela do fornecedor convém passar para o status «sem estoque» em vez de excluí-los.

Se o fornecedor não entrega um feed e é preciso extrair as fichas de produto diretamente das páginas HTML do site dele, a tarefa fica mais trabalhosa e tem nuances próprias (paginação, carregamento dinâmico, proteção anti-bots). Os princípios desse tipo de análise estão descritos em detalhe no material «Web scraping em PHP».


Recomendações técnicas

Algumas regras universais que tornarão qualquer scraper para WordPress mais confiável:

  1. Use a HTTP API do WordPress (wp_remote_get/wp_remote_post) em vez de file_get_contents ou de cURL «cru»: ela leva em conta as configurações de proxy, os timeouts e os filtros do CMS.
  2. Faça cache via Transients API. Isso reduz a carga tanto do seu servidor quanto da fonte.
  3. Não scrapeie em tempo real durante o carregamento da página. O scraping pesado deve rodar em segundo plano via cron; o front-end lê dados já prontos.
  4. Substitua o WP-Cron pelo cron do sistema nas tarefas pesadas: o WP-Cron só dispara quando alguém visita o site e não serve para importações longas.
  5. Sempre escape os dados antes de exibi-los (esc_html, esc_url, wp_kses_post): uma fonte externa nunca pode ser considerada confiável.
  6. Registre os erros e verifique is_wp_error() em cada passo: a fonte externa pode ficar indisponível, mudar de formato ou devolver lixo.
  7. Cumpra as normas legais e éticas: respeite o robots.txt, os limites de requisições e os termos de uso da fonte.

Conclusão

O scraping é uma forma poderosa de automatizar o preenchimento de um site WordPress. Para as tarefas típicas, plugins prontos como WP All Import ou Feedzy costumam bastar. Mas assim que a fonte ou a lógica de processamento saem do padrão, um scraper próprio em PHP oferece um controle e uma flexibilidade incomparavelmente maiores.

Repassamos quatro cenários práticos — taxas de câmbio, notícias e RSS, previsão do tempo e importação dos produtos de um fornecedor para o WooCommerce — e mostramos como integrar cada um deles ao ecossistema do WordPress por meio da HTTP API, dos transients e do cron.

Quer se aprofundar na própria tecnologia de análise de dados? Comece pelo material básico «Web scraping em PHP». E, se precisar de um scraper pronto para a sua tarefa, cuidamos de tudo: da configuração da extração de artigos de imprensa à importação completa do catálogo de um fornecedor.