Contents
  1. 1. 初始化项目
  2. 2. 安装http请求库
  3. 3. 添加CA文件
  4. 4. 安装HTML解析库
  5. 5. 开始抓取、解析列表页
  6. 6. 获取内页数据,获得新闻标题与正文

本文使用了php-cli的方式运行,请先确保已经安装php-cli并加入环境变量: 终端输入 php -v 看看是否能返回版本信息。

本教程旨在练习命令行与composer的使用,可以参考php的包管理工具Composer的安装与使用了解更多

本项目需要PHP7以上版本

初始化项目

新建空目录(下文称:项目目录),打开终端切换到项目目录

1
composer init

项目名称形如 <author>/<projectname>,其余一路回车

项目目录中新建index.php,内容如下:

1
2
<?php
require __DIR__.'/vendor/autoload.php';

安装http请求库

本项目使用的是guzzlehttp/guzzle,完整的手册看这里:Quickstart - Guzzle Documentation

1
composer require guzzlehttp/guzzle

此时 观察项目目录结构如下

1
2
3
4
├─vendor
├─composer.json
├─composer.lock
└─index.php

其中composer.json中添加了require信息,生成的composer.lock记录了当前所有安装的php组件的版本,vendor是当前项目的所有第三方依赖的安装位置

index.php中追加一行

1
use GuzzleHttp\Client;

添加CA文件

下载cacert.pem,也可以从网盘下载(网盘文件需解压)

下载完成后保存,打开PHP安装目录,找到php.ini文件,打开、搜索;openssl.cafile=,修改为:

1
openssl.cafile=下载的路径到/cacert.pem

添加完后GuzzleHttp\Client就可以使用了,可以测试一下:

1
2
3
4
5
6
7
8
<?php
require __DIR__.'/vendor/autoload.php';
use GuzzleHttp\Client;

$client = new Client(['base_uri' => 'https://www.lmlq.com/', 'timeout' => 5.0]);
$response = $client->request('GET', 'News/GroupNews/');

var_dump((string) $response->getBody()); # getBody()返回的是一个对象,你可以尝试打印看看里面有什么

安装HTML解析库

本项目使用的是voku/simple_html_dom,其选择器与jQuery相同。完整的手册看这里:simple html dom parser

1
2
composer require voku/simple_html_dom
composer require voku/portable-utf8 # if you need e.g. UTF-8 fixed output

index.php中追加一行

1
use voku\helper\HtmlDomParser;

开始抓取、解析列表页

还以刚刚的页面为例子,增加页面解析部分,尝试获取栏目中的内页地址:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 和前例相同的部分内容已省略

$body = (string) $response->getBody();
$dom = HtmlDomParser::str_get_html($body);

$a_list = $dom->findMultiOrFalse('.img_list li a');

$href_list = []; # 准备一个空数组用于保存文章链接
if ($a_list !== false) {
foreach ($a_list as $a) {
array_push($href_list, $a->getAttribute('href'));
}
}
print_r($href_list);

获取内页数据,获得新闻标题与正文

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 和前例相同的部分内容已省略

# 这里声明一个数组来保存抓取结果,实际使用时这里应该存入数据库
$res = [];

foreach($href_list as $href) {
$response = $client->request('GET', '/News/GroupNews/10313.html');
$body = (string) $response->getBody();
$dom = HtmlDomParser::str_get_html($body);
array_push($res, [
'title' => $dom->findOneOrFalse('title')->textContent,
'content' => $dom->findOneOrFalse('.cont')->textContent
]);
}
print_r($res);

这里将会打印当前列表下的几篇文章的内容。

完整代码如下,每行都加了注释:

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
<?php
require __DIR__ . '/vendor/autoload.php'; # 引入composer生成的自动加载文件

use GuzzleHttp\Client; # 引入HTTP请求库 guzzlehttp/guzzle
use voku\helper\HtmlDomParser; # 引入HTML解析库 voku/simple_html_dom

$client = new Client(['base_uri' => 'https://www.lmlq.com/', 'timeout' => 5.0]); # 实例化HTML解析库, 传入的两个参数分别是:实例的默认地址、请求超时时间
$response = $client->request('GET', 'News/GroupNews/'); # 抓取新闻的栏目页,返回的是一个对象

$body = (string) $response->getBody(); # 将抓取结果转为字符串保存
$dom = HtmlDomParser::str_get_html($body); # 使用HTML解析库解析抓取的结果,返回的是一个对象

$a_list = $dom->findMultiOrFalse('.img_list li a'); # 解析出栏目内页地址标签<a>

$href_list = []; # 准备一个空数组用于保存文章链接
if ($a_list !== false) {
foreach ($a_list as $a) {
array_push($href_list, $a->getAttribute('href')); # 获取每个<a>标签中的href属性,存入数组$href_lis
}
}
# 这里声明一个数组来保存抓取结果,实际使用时这里应该存入数据库
$res = [];

foreach($href_list as $href) {
$response = $client->request('GET', $href); # 请求内页
$body = (string) $response->getBody(); # 取得结果,转为字符串
$dom = HtmlDomParser::str_get_html($body); # 解析
array_push($res, [
'title' => $dom->findOneOrFalse('title')->textContent, # 取得标题
'content' => $dom->findOneOrFalse('.cont')->textContent # 取得正文
]);
}
print_r($res);

Contents
  1. 1. 初始化项目
  2. 2. 安装http请求库
  3. 3. 添加CA文件
  4. 4. 安装HTML解析库
  5. 5. 开始抓取、解析列表页
  6. 6. 获取内页数据,获得新闻标题与正文