SIM*_*SIM 6 php curl simple-html-dom web-scraping
我在php中编写了一个脚本,用于搜索title位于网页右上角的产品.该title是可见的Gucci.
当我执行下面的脚本时,它给了我一个错误Notice: Trying to get property 'plaintext' of non-object in C:\xampp\htdocs\runcode\testfile.php on line 16.
我怎样才能Gucci从该网页获得该名称?
我到目前为止写的:
<?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);
?>
Run Code Online (Sandbox Code Playgroud)
顺便说一下,我在剧本中使用的选择器完美无瑕.
为了清除这种混淆,我从页面源复制了一大块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>
Run Code Online (Sandbox Code Playgroud)
发布脚本:非常可悲的是我必须用另一种语言显示一个真实的例子,以确保名称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)
Run Code Online (Sandbox Code Playgroud)
输出它产生:
Gucci
Run Code Online (Sandbox Code Playgroud)
现在,很明显我寻找的内容是静态的.
请查看下面的图像,以识别title我已用铅笔标记的图像.
成功的 Python 脚本和 PHP 脚本之间的主要区别在于会话的使用。您的 PHP 脚本不使用 cookie,这会触发来自服务器的不同响应。
我们有两个选择:
更改选择器。正如Mark 的回答中提到的,该项目仍在 html 上,但在不同的标签中。我们可以用这个选择器得到它:
'a[itemprop="brand"]'
Run Code Online (Sandbox Code Playgroud)使用cookie。CURLOPT_COOKIESESSION如果我们使用临时文件来写入/读取 cookie, 我们可以获得与 Python 脚本相同的响应。
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
Run Code Online (Sandbox Code Playgroud)
该脚本执行两个请求;第一个请求将 cookie 写入文件,第二个请求读取并使用它们。
在这种情况下,服务器返回压缩响应,因此我用来CURLOPT_ENCODING解压缩内容。
由于您仅使用标头来设置用户代理,因此最好使用该CURLOPT_USERAGENT选项。
我设置CURLOPT_SSL_VERIFYPEER为 false 因为我没有设置证书,并且CURL无法使用 HTTPS。如果您可以与 HTTPS 站点通信,出于安全原因最好不要使用此选项。如果没有,您可以使用 来设置证书CURLOPT_CAINFO。