PHP 抓取网页表格数据范例

温馨提示:
本文所述内容具有依赖性,可能因软硬条件不同而与预期有所差异,故请以实际为准,仅供参考。

一、背景

  准备将一卡通消费记录批量导进随手记,但是学校的一卡通消费查询系统并不支持数据导出,要我一页页地把数据复制到Excel上?这种重复无聊的事情不应该是靠擅长做这些事情的计算机去解决的吗?所以我开始打算写个脚本一键抓取我的一卡通消费记录。

二、分析

  首先打开消费记录查询的网页,掏出开发者工具,观察这个网页,找到我们的目标,是一个table标签。

  接着寻找这个标签是怎么生成的,是服务器后端直接生成出来的网页,还是前端ajax访问后端拿到数据再渲染出来的呢?点开 Network 标签刷新网页,发现网页并没有出现异步的请求,每一页都是一个新的网页,所以是前者的情况。而且每一页的 url 都是 http://app.scnu.edu.cn/ecard/consump.html?page=[页码] ,所以我只要让程序访问这个 url 并且解析其中的 html ,得到表格内部的数据,再通过某种方式收集起来就能完成目标了。
  要将结果导入到Excel之中,这里用到了一种简单方便的表格文件格式 .CSV,本质上 csv 的表格文件只是一种文本文件,它用逗号等分隔符分隔表格的字段,表格中每一行的数据用换行符分隔(在Excel里面换行符是 "rn")

字段1,字段2,字段3,字段4
A,B,C,D
1,2,3,4

  就是这么简洁明了!对于任意的程序,只需要简单的字符串拼接即可生成一个csv格式的表格。
  经过我的测试,我这一个学期以来的消费记录在这个网页上只有50多页,所以爬虫需要爬取的数据量很小,处理起来是完全没有压力的,直接一次性得到所有的结果之后保存文件就行了。
  至于爬虫程序的语言选择,我也没什么好说的,目前我也就对PHP比较熟悉一些,所以接下来的程序我也是用PHP完成的。

三、执行

  首先确定我应该怎么模拟登录这个系统,这里我们应该要知道,HTTP 是一种无状态的协议,所以服务器要确定当前请求的用户是谁的话,就要通过 HTTP 请求的 Cookie中保存的信息来确定。所以我们如果要让服务器知道爬虫发出的 HTTP 请求的用户是我的话,应该让爬虫发出的 HTTP 请求带上这个 cookie,在这里我们可以把这个 cookie 从 chrome 复制出来,把它的值保存在某个变量之中备用。
  查看浏览器访问这个页面的 header,发现 cookie 只有 JSESSIONID。

  接下来写一个循环,把每一页抓取的结果添加到保存结果的字符串之中,当找不到数据时则跳出循环,保存结果,程序结束。
  提取数据时我用了 simple_html_dom ,一个简单方便的解析 html 中的 DOM结构的库。
  最后将字符串中的内容保存到 result.csv 中。

  代码如下:

<?php
/**
 * Created by PhpStorm.
 * User: qing
 * Date: 17-2-12
 * Time: 下午1:59
 */
require_once "simple_html_dom.php";

$cookie = "JSESSIONID=C73FF91A6FF439C073EC664E532C67E6";
$result = "消费时间,消费金额,卡内余额,消费地点\r\n";

$page = 1;

while (true){
    echo "Fetching page $page...\n";
    $html = get_url("http://app.scnu.edu.cn/ecard/consump.html?page=$page", $cookie);
    //echo $html;exit();
    if (!$html)
        exit("Network Error!!");
    if (strpos($html, "暂无数据") !== false)
        break;
    $dom = new simple_html_dom();
    $dom->load($html);
    $trs = $dom->find("table", 0)->find("tr");
    foreach ($trs as $tr){
        $arr = [];
        $tds = $tr->find("td");
        //忽略表头
        if (!$tds)
            continue;
        foreach ($tds as $td){
            //过滤结果中的标签
            $arr[] = strip_tags($td->innertext);
        }
        $result .= implode(",", $arr) . "\r\n";
    }
    $page++;
}

file_put_contents("result.csv", $result);

echo "Finished\n";

function get_url($url, $cookie=''){
    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array('User-Agent: Mozilla/5.0 (Linux; U; Android 4.1.2; zh-cn; MB526 Build/JZO54K) AppleWebKit/530.17 (KHTML, like Gecko) FlyFlow/2.4 Version/4.0 Mobile Safari/530.17 baidubrowser/042_1.8.4.2_diordna_458_084/alorotoM_61_2.1.4_625BM/1200a/39668C8F77034455D4DED02169F3F7C7%7C132773740707453/1','Referer: http://app.scnu.edu.cn/ecard/consump.html'));
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_COOKIE, $cookie);
    $result = curl_exec($ch);
    $httpCode = curl_getinfo($ch,CURLINFO_HTTP_CODE);
    if ($httpCode != 200) return false;
    curl_close($ch);
    return $result;
}

  运行结果:

  实践证明,cli模式下运行的PHP还是很给力的 ^_^


参考文献:
1、用PHP爬取个人一卡通的消费记录


ArmxMod for Typecho
个性化、自适应、功能强大的响应式主题

推广

 继续浏览关于 爬虫php网页抓取spider 的文章

 本文最后更新于 2017/10/30 19:25:11,可能因经年累月而与现状有所差异

 引用转载请注明: VirCloud's Blog > 运维 > PHP 抓取网页表格数据范例

精选评论

  1. m0nst3r.me
    m0nst3r.me 回复

    Windows 10Chrome 60.0.3112.113来自 东京都 的大神

    大神,你的版权声明和跨屏、打赏功能用的什么插件?求指导。
    PS:看到你的留言过来膜拜下,Orz

    1. VirCloud

      并不是插件,直接在模板里的基础上修改的。

      1. m0nst3r.me
        m0nst3r.me 回复

        Windows 10Chrome 60.0.3112.113来自 广东 的大神

        博主666

      2. m0nst3r.me
        m0nst3r.me 回复

        Windows 10Chrome 60.0.3112.113来自 广东 的大神

        抄袭完毕 如果博主不介意的话。