你用PHP爬取过数据吗? 解析json 解析dom树 总结和

「这是我参与11月更文挑战的第26天,活动详情查看:2021最后一次更文挑战

PHP除了做服务端开发已经,也是可以像Python一样来爬取数据的。

我认为爬取数据有两种实现思路:

1种是请求数据接口,解析json数据

另外1种是获得网页的dom树,解析dom树,获得数据。

今天重点介绍第二种,引用php的一个插件:simple_html_dom,解析json的思路也提一下。

image.png

解析json

解析json这种方式很好理解,所有支持请求网络的开发语言都能支持

思路就是获得爬取链接返回的json数据(也可以是其他类型的数据,json比较常用)

我们拿到json数据后进行解析,结合自身需求来处理数据。

这个比较通用,就不举例子了。

解析dom树

重点讲解一下PHP是如何爬取目标网站,解析dom树的。

举个栗子:

工具类代码:

做了缓存处理,我的场景只要请求的url相同返回的数据是不变的,所以做了缓存处理

请求的url之前请求通,不会重复请求,而是会从缓存中取值

sleep()的作用是避免给抓取数据的网站造成网络问题,控制一下请求频率

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
php复制代码public static function crawlContent($url, $encode = true)
{
$file_name = '../cache/' . md5($url);
if (!file_exists($file_name)) {
@touch($file_name);
}
$content = file_get_contents($file_name);
if (empty($content)) {
$content = Request::curl($url);
if (empty($content)) {
sleep(rand(3,10));
$content = Request::curl($url);
}
$encode && $content = iconv("GBK", "UTF-8//IGNORE", $content);
file_put_contents($file_name, $content);
}
return $content;
}

封装的 curl 工具

1
2
3
4
5
6
7
8
9
10
11
12
13
14
php复制代码public static function curl($url , $configs = array())
{
$b = microtime(true);
$new_ch = curl_init();
self::_setopt($new_ch , $url , $configs);
$result = curl_exec($new_ch);
$e = microtime(true);
if (curl_errno($new_ch))
{
Logger::log('CULR_BAD\t' . "curl_errno:" . curl_errno($new_ch) . "\t" . curl_error($new_ch) . "\t" . ($e - $b) . "\t" . $url);
}
curl_close($new_ch);
return $result;
}

解析dom树示例代码

上面的工具类代码我们获得了目标网页的数据

通过 str_get_html 函数获得字符串

再按照 simple_html_dom 获得元素的方式获得对应的值就可以了了

比如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
php复制代码
<?php
// 查找id='#container'的元素
$ret = $html->find('#container');

// 找到所有class=foo的元素
$ret = $html->find('.foo');

// 查找多个html标签
$ret = $html->find('a, img');

// 还可以这样用
$ret = $html->find('a[title], img[title]');
?>

更多取值方法可以查看官方文档,非常的简单好用,这里就不再这里赘述了。

我的示例代码

下面是我的示例代码,整理了一些爬取数据时需要注意的问题:

  1. 如果涉及抓取图片的话,最好把图片上传到自己的云存储
  2. 合理的控制爬取频率(已封装到工具类中)
  3. 合理的使用代理(已封装到工具类中)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
php复制代码<?php
include '../include/Config.php';
include '../include/Db.php';
include '../include/Logger.php';
include '../include/Request.php';
include '../include/simple_html_dom.php';
include '../include/Utils.php';
//综合脚本 一套代码完成 抓取商品详情链接 抓取商品图 下载商品图
$db_aliexpress = new Db($db_xxxx);

parseContent($db_xxxx);

function parseContent($spider)
{
for($p=9;$p<50;$p++){
$url = 'https://www.xxxxx.com/store/5435064/search/'.$p.'.html?SortType=bestmatch_sort';
var_dump($url);
$m_content = Utils::curlProxy($url, false);
$detail_html = str_get_html($m_content);
if ($detail_html) {
$content = $detail_html->find('.m-o-large-all-detail .ui-box .ui-box-body ul li');
if ($content) {
$counts = count($content);
for ($i = 0; $i < $counts; $i++) {
$name = trim($detail_html->find('.m-o-large-all-detail .ui-box .ui-box-body ul li .detail h3 a', $i)->plaintext); //名称
$href = 'https:'.trim($detail_html->find('.m-o-large-all-detail .ui-box .ui-box-body ul li .detail h3 a', $i)->href); //url
preg_match_all('/[1-9]\d*/', $href, $matches);
$source_id = $matches[0][0];
$price = trim($detail_html->find('.m-o-large-all-detail .ui-box .ui-box-body ul li .cost b', $i)->plaintext); //价格
$data = array(
'name' => $name,
'source_url' => $href,
'source_id' => $source_id,
'price'=>$price,
'created_at'=>date('Y-m-d H:i:s'),
'date'=>date('m-d'),
);
$id = $spider->insert('products', $data);
var_dump("商品信息:products_" . $id);
if ($id){
//存储图片
catchThumbs($id,$href,$spider);
}
}
}
}
}
}

//抓取商品图
function catchThumbs($id,$detail_url,$spider)
{
$m_content = Utils::curlProxy($detail_url, false);

$before = strpos($m_content, 'imagePathList');
$after = strpos($m_content,'ImageModule',1);
$count = $after-$before-24;

$thumbs = substr($m_content,$before+15,$count);

$data = array(
'thumbs'=>$thumbs,
'updated_at'=>date('Y-m-d H:i:s'),
);
$res = $spider->update('products', $data, 'id = '.$id);
var_dump('抓取商品图:'.$res." id=".$id);
if ($res){
//更新成功则下载图片
downloadThumbs($id,$thumbs,$spider);
}
}

//下载商品图
function downloadThumbs($id,$thumbs,$spider)
{
$Ymd = date('md');
$thumbs = json_decode($thumbs,true);
foreach ($thumbs as $key=> $thumb){
$image_name = $Ymd.'-'.$id.'-'.($key+1).'.jpg';
$image_name = './pics/'.$image_name;
saveImage($thumb,$image_name);
}
}

/**
* 从网上下载图片保存到服务器
* @param $path 图片网址
* @param $image_name 保存到服务器的路径 './public/upload/users_avatar/'.time()
*/
function saveImage($path, $image_name) {
$ch = curl_init ($path);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_BINARYTRANSFER,1);
$img = curl_exec ($ch);
curl_close ($ch);
//$image_name就是要保存到什么路径,默认只写文件名的话保存到根目录
$fp = fopen($image_name,'w');//保存的文件名称用的是链接里面的名称
fwrite($fp, $img);
fclose($fp);
}

总结和注意

以上就是PHP爬取数据的思路总结啦~

注意:在未经授权的情况下爬取数据是违法的!

本文仅是提供爬取数据的PHP实现思路而已,网络世界不是法外之地,谨慎使用爬取技术哦~

大家有什么好想法欢迎在评论区讨论

硬核文章推荐

PHP转Go 2021年年中总结

如何第一时间收到接口报错?不用测试妹子再质疑你是不是接口挂了。

Git使用实战:多人协同开发,紧急修复线上bug的Git操作指南。

性能优化反思:不要在for循环中操作DB

性能优化反思:不要在for循环中操作DB 进阶版

最后

👍🏻:觉得有收获请点个赞鼓励一下!

🌟:收藏文章,方便回看哦!

💬:评论交流,互相进步!

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

0%