Проблемы с получением названия продукта с веб-страницы - PullRequest
0 голосов
/ 19 сентября 2018

Я написал скрипт на php для очистки title продукта, расположенного в верхнем правом углу веб-страницы.title отображается как Gucci.

, когда я выполняю свой скрипт ниже, он выдает ошибку Notice: Trying to get property 'plaintext' of non-object in C:\xampp\htdocs\runcode\testfile.php on line 16.

Как я могу получить только имя Gucci с этой веб-страницы?

Ссылка на URL

Я уже написал:

<?php
include "simple_html_dom.php";
$link = "https://www.farfetch.com//bd/shopping/men/gucci-rhyton-web-print-leather-sneaker-item-12964878.aspx"; 

function get_content($url)
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_HTTPHEADER, array('User-Agent: Mozilla/5.0',));
        curl_setopt($ch, CURLOPT_BINARYTRANSFER, 1);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        $htmlContent = curl_exec($ch);
        curl_close($ch);
        $dom = new simple_html_dom();
        $dom->load($htmlContent);
        $itemTitle = $dom->find('#bannerComponents-Container [itemprop="name"]', 0)->plaintext;
        echo "{$itemTitle}";
    }
get_content($link);
?>

Кстати, селектор, который я использовал в скрипте, безупречен.

Чтобы устранить путаницу, я скопировал кусок html-элементов из источника страницы , который не генерирует ни динамически, ни зашифрованный javascript, поэтому я не нахожу причин для того, чтобы curl не смогчтобы справиться с этим:

<div class="cdb2b6" id="bannerComponents-Container">
    <p class="_41db0e _527bd9 eda00d" data-tstid="merchandiseTag">New Season</p>
    <div class="_1c3e57">
        <h1 class="_61cb2e" itemProp="brand" itemscope="" itemType="http://schema.org/Brand">
            <a href="/bd/shopping/men/gucci/items.aspx" class="fd9e8e e484bf _4a941d f140b0" data-trk="pp_infobrd" data-tstid="cardInfo-title" itemProp="url" aria-label="Gucci">
                <span itemProp="name">Gucci</span>
            </a>
        </h1>
    </div>
</div>

Post script: Очень жалко, что мне пришлось показать реальный пример из другого языка, чтобы убедиться, что имя Gucci не генерируется динамически какнесколько комментариев и ответ уже указали, что

Следующий скрипт написан на python (с использованием модуля requests, который не может обрабатывать динамический контент):

import requests
from bs4 import BeautifulSoup

url = "https://www.farfetch.com//bd/shopping/men/gucci-rhyton-web-print-leather-sneaker-item-12964878.aspx"

with requests.Session() as s:
    s.headers["User-Agent"] = "Mozilla/5.0"
    res = s.get(url)
    soup = BeautifulSoup(res.text,"lxml")
    item = soup.select_one('#bannerComponents-Container [itemprop="name"]').text
    print(item)

Вывод:

Gucci

Теперь ясно, что контент, который я ищу

Пожалуйста, проверьте изображение ниже, чтобы распознать title, который я уже отметил карандашом.

enter image description here

Ответы [ 3 ]

0 голосов
/ 22 сентября 2018

Основным отличием вашего успешного скрипта Python от скрипта PHP является использование сессии.Ваш скрипт PHP не использует куки, и это вызывает разные ответы от сервера.

У нас есть два варианта:

  1. Изменить селектор.Как упомянуто в Ответ Марка , элемент все еще находится в html, но в другом теге.Мы могли бы получить это с помощью этого селектора:

    'a[itemprop="brand"]'
    
  2. Использовать куки.Мы можем получить тот же ответ, что и ваш скрипт на Python, если мы используем CURLOPT_COOKIESESSION и временный файл для записи / чтения файлов cookie.

    function get_content($url) {
        $cookieFileh = tmpfile();
        $cookieFile=stream_get_meta_data($cookieFileh)['uri'];
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0');
        curl_setopt($ch, CURLOPT_COOKIESESSION, true);
        curl_setopt($ch, CURLOPT_COOKIEJAR, $cookieFile);
        curl_setopt($ch, CURLOPT_COOKIEFILE, $cookieFile); 
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); //
        curl_setopt($ch, CURLOPT_ENCODING, "gzip");
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_exec($ch);
        $htmlContent = curl_exec($ch);
        curl_close($ch);
        fclose($cookieFileh); // thanks to tmpfile(), this also deletes the cookie file.
        $dom = new simple_html_dom();
        $dom->load($htmlContent);
        $itemTitle = $dom->find('#bannerComponents-Container [itemprop="name"]', 0)->plaintext;
        echo "{$itemTitle}";
    }
    
    $link = "https://www.farfetch.com/bd/shopping/men/gucci-rhyton-web-print-leather-sneaker-item-12964878.aspx"; 
    get_content($link);
    //Gucci
    

    Этот скрипт выполняет два запроса;первый запрос записывает куки в файл, второй читает и использует их.

    В этом случае сервер возвращает сжатый ответ, поэтому я использовал CURLOPT_ENCODING, чтобы распаковать содержимое.

    Поскольку вы используете заголовки только для установки пользовательского агента, лучше всего использовать опцию CURLOPT_USERAGENT.

    Я установил CURLOPT_SSL_VERIFYPEER в false, потому что я не установилсертификат, и CURL не может использовать HTTPS.Если вы можете общаться с HTTPS-сайтами, лучше не использовать эту опцию из соображений безопасности.Если нет, вы можете установить сертификат с помощью CURLOPT_CAINFO.

0 голосов
/ 23 сентября 2018

@ tmadam уже решил проблему, я просто хочу добавить, что сегодня нет веской причины использовать simple_html_dom, кажется, что он не поддерживается, разработка остановлена ​​в 2014 году, есть много неразрешенных сообщений об ошибках, и, что самое важное, DOMDocument & DOMXPath может сделать примерновсе simple_html_dom может, и поддерживается, и является интегрированной частью PHP, что означает, что нет ничего, что можно включить / связать с вашим скриптом.парсинг с DOMDocument и DOMXPath будет выглядеть так:

$htmlContent = curl_exec($ch);
curl_close($ch);
fclose($cookieFileh); // thanks to tmpfile(), this also deletes the cookie file.
$dom = @DOMDocument::loadHTML($htmlContent);
$xp=new DOMXPath($dom);
$itemTitle = $xp->query('//*[@id="bannerComponents-Container"]//*[@itemprop="name"]')->item(0)->textContent;
echo $itemTitle;
0 голосов
/ 20 сентября 2018

Ваш селектор действительно работает в браузере, но ваш селектор отсутствует, когда вы используете curl для получения источника страницы.

Попробуйте сохранить свернутую страницу в терминале, и вы увидите, что структура страницы отличается от той, которую вы видите в браузере.

Это верно для большинства современных веб-сайтов, потому что они интенсивно используют Javascript и curl не запускает javascript для вас.

Я сохранил результаты скручивания в файл, информация о бренде выглядит так:

<a itemprop="brand" class="generic" data-tstid="Label_ItemBrand" href="/bd/shopping/men/gucci/items.aspx" dir="ltr">Gucci</a>

...