0%

后台定时执行php爬虫抓取学院内外网新闻

前言

  年初在Appstore发布了一个科文学院的app[科文教务],下载量不大,也一直未推广,因为Android版的没做好,毕竟学生还是使用安卓手机的居多,(使用Apple的大部分都是不好好学习的)

  毕竟丰富的App功能离不开强大的后台数据支持,起初做的教务App中新闻主要抓取学院主页上的通知公告,一方面内容太少,另一方面每次运行后抓取数据都需要等待,尤其图片新闻,图片加载太慢。所以,想改用服务器后台整合数据,通过JSON将整合好的数据统一反馈给app。

运行环境 Windows Server + IIS + php

  1. windows server 服务器用于定时执行php脚本;

  2. SQL server 用于存储整合后的数据;

  3. IIS下的php运行环境,提供返回Json数据;

网页代码分析

  学院内往外网页代码不同,需分开分析,主要用到工具Chrome浏览器。

分析学院主页

网址

  首先分析浏览器的网址,不同的新闻分类有不同的网址,需要找到网址的相同部分,和不同的地方。http://kwxy.jsnu.edu.cn/***/list.htm 这是网页的共同点,***为不同分类对应不同的数字。

网页代码

  利用Chrome浏览器右击检查,查看网页源代码,定位到需要抓取的内容,分析我们需要的HTML标签、CSS等代码。如下图:

网页分析1

可以发现我们需要获取的内容,共有的标签是 <a class="column-news-item item-1 ...,因此把这个HTML标签的class作为我们分析网页文本抓取数据的关键。

分析院内办公网

  内网分析使用相同的方法,此处不再累赘,结果详见下面的代码。

实现代码

目标地址数组

1
2
3
4
5
6
7
8
//网页跟目录
$url = ['kwxy' => "http://kwxy.jsnu.edu.cn/", 'office' => "http://219.230.252.17/list.asp?id="];
$tag = ['kwxy' => "/list", 'office' => "&PageNo="];
$html = ['kwxy' => ".htm", 'office' => ""];

//读取目录 http://kwxy.jsnu.edu.cn/7154/list.htm
$category = ['kwxy' => ['学务通知' => '7154', '教务通知' => '7153', '学院要闻' => '7165', '校园活动' => '7398', '招生快讯' => '10048', '通知公告' => '7151'],
'office' => ['通知公告' => '6', '党委文件' => '3', '部门文件' => '4']];

   以上代码为分析后的网址及我们需要的几个分类对应的编号,使用数组存储方便后期增加其他分类。

爬虫代码

1
2
3
4
5
6
7
8
9
10
11
//目标网址
$target_url = $value.$cate_value.$tag[$key].$page.$html[$key];
//爬虫开始 ...............
$che = curl_init();
curl_setopt($che, CURLOPT_URL, $target_url);
curl_setopt($che, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($che, CURLOPT_CONNECTTIMEOUT, $timeout);
//读取内容
$content = curl_exec($che);
//爬虫结束 ...............
curl_close($che);

  目标网址根据上面的数组循环生成相应的访问网址。在循环中每次抓取后分析网页内容,根据前面分析的HTML代码提取需要的数据。

解析Html网页代码

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
//解析HTML
$htmls = new simple_html_dom();
$htmls -> load($content);
if($key == 'office'){
$news = $htmls -> find('.newstitle');
for($i = 0; $i < count($news); $i++){
$href = $news[$i] -> children(0) -> href;
//提取文章ID
$article_id = explode('=', $href)[1];
if($article_id != null){
array_push($all_news, array(
"article" => $article_id,
"category" => $cate_key,
"href" => '/'.explode('/', $href)[1],
"title" => strtr(enc($news[$i] -> children(0) -> innertext), $special_char),
"date" => $news[$i] -> next_sibling() -> innertext,
"image" => "",
"kwxy" => 0
));
}
}
}else{
//外网解析代码类似,此处省略
}
$htmls -> clear();

  内外网解析代码类似,利用前面分析的Class值,区别在于再获取对应html的文本时,使用不同的代码children(0) -> innertext,外网根据html结构再做调整。

储存数据

  使用SQL Server储存整合后的数据,代码省略。

后台定时执行php文件

  php有自带的方法可以在后台无限次执行,在本地测试一切正常,但是放到服务器上就会执行中断,不知道问题出在什么地方,好在Windows上有[任务计划程序]也可以定时执行。

1
"G:\php_7.1.9\php.exe" -f "G:\jwb\myjw\services\get_all_news_in_background.php"

将文本保存为bat文件,在[任务计划程序]中创建基本任务,分别设置触发器和操作。

触发器设置

设置每两小时执行一次。

操作

设置需要执行的程序,此处为bat文件,需要值得注意的是,一定要在”起始于(可选)”这一栏中填入bat文件的存放目录,不然任务不能执行。

写在最后

需要注意点问题

  1. 设置定时执行任务时的起始于目录,上面一提到;

  2. 测试代码过程中,当读取的网页较多时(网页分类或者读取的页数),可能会出现网页响应超时的问题。

    • php文件中加入set_time_limit(0); // run script forever,可使脚本持续执行;
    • IIS中设置网页的超时时间,默认只有120s。

后续

  整合好数据再写一个php文件读取返回Json数据,就可以应用到各个app中去了。

获取新闻API


  好久没有更新,解决了好几个问题。

  1. 没想到现在可以使用相对路径调用本地图片啦!!!😸
  2. 把Hexo文件放到Coding.net上了,可以在办公室电脑上写文章了,还是有点懒呢。