찾다
백엔드 개발PHP 튜토리얼php实现爬取和分析知乎用户数据,php_PHP教程

php实现爬取和分析知乎用户数据,php

背景说明:小拽利用php的curl写的爬虫,实验性的爬取了知乎5w用户的基本信息;同时,针对爬取的数据,进行了简单的分析呈现。

php的spider代码和用户dashboard的展现代码,整理后上传github,在个人博客和公众号更新代码库,程序仅供娱乐和学习交流;如果有侵犯知乎相关权益,请尽快联系本人删除。

无图无真相

移动端分析数据截图

pc端分析数据截图

整个爬取,分析,展现过程大概分如下几步,小拽将分别介绍

  1. curl爬取知乎网页数据
  2. 正则分析知乎网页数据
  3. 数据数据入库和程序部署
  4. 数据分析和呈现

curl爬取网页数据

PHP的curl扩展是PHP支持的,允许你与各种服务器使用各种类型的协议进行连接和通信的库。是一个非常便捷的抓取网页的工具,同时,支持多线程扩展。

本程序抓取的是知乎对外提供用户访问的个人信息页面https://www.zhihu.com/people/xxx,抓取过程需要携带用户cookie才能获取页面。直接上码

获取页面cookie

复制代码 代码如下:
// 登录知乎,打开个人中心,打开控制台,获取cookie
document.cookie
"_za=67254197-3wwb8d-43f6-94f0-fb0e2d521c31; _ga=GA1.2.2142818188.1433767929; q_c1=78ee1604225d47d08cddd8142a08288b23|1452172601000|1452172601000; _xsrf=15f0639cbe6fb607560c075269064393; cap_id="N2QwMTExNGQ0YTY2NGVddlMGIyNmQ4NjdjOTU0YTM5MmQ=|1453444256|49fdc6b43dc51f702b7d6575451e228f56cdaf5d"; __utmt=1; unlock_ticket="QUJDTWpmM0lsZdd2dYQUFBQVlRSlZUVTNVb1ZaNDVoQXJlblVmWGJ0WGwyaHlDdVdscXdZU1VRPT0=|1453444421|c47a2afde1ff334d416bafb1cc267b41014c9d5f"; __utma=51854390.21428dd18188.1433767929.1453187421.1453444257.3; __utmb=51854390.14.8.1453444425011; __utmc=51854390; __utmz=51854390.1452846679.1.dd1.utmcsr=google|utmccn=(organic)|utmcmd=organic|utmctr=(not%20provided); __utmv=51854390.100-1|2=registration_date=20150823=1^dd3=entry_date=20150823=1"

抓取个人中心页面

通过curl,携带cookie,先抓取本人中心页面

/**
 * 通过用户名抓取个人中心页面并存储
 * 
 * @param $username str :用户名 flag
 * @return boolean   :成功与否标志
 */
public function spiderUser($username)
{
  $cookie = "xxxx" ;
  $url_info = 'http://www.zhihu.com/people/' . $username; //此处cui-xiao-zhuai代表用户ID,可以直接看url获取本人id
  $ch = curl_init($url_info); //初始化会话
  curl_setopt($ch, CURLOPT_HEADER, 0);
  curl_setopt($ch, CURLOPT_COOKIE, $cookie); //设置请求COOKIE
  curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); //将curl_exec()获取的信息以文件流的形式返回,而不是直接输出。
  curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
  $result = curl_exec($ch);

   file_put_contents('/home/work/zxdata_ch/php/zhihu_spider/file/'.$username.'.html',$result);
   return true;
 }

正则分析网页数据分析新链接,进一步爬取

对于抓取过来的网页进行存储,要想进行进一步的爬取,页面必须包含有可用于进一步爬取用户的链接。通过对知乎页面分析发现:在个人中心页面中有关注人和部分点赞人和被关注人。
如下所示

复制代码 代码如下:
// 抓取的html页面中发现了新的用户,可用于爬虫

ok,这样子就可以通过自己-》关注人-》关注人的关注人-》。。。进行不断爬取。接下来就是通过正则匹配提取该信息

复制代码 代码如下:
// 匹配到抓取页面的所有用户
preg_match_all('/\/people\/([\w-]+)\"/i', $str, $match_arr);
// 去重合并入新的用户数组,用户进一步抓取
self::$newUserArr = array_unique(array_merge($match_arr[1], self::$newUserArr));

到此,整个爬虫过程就可以顺利进行了。
如果需要大量的抓取数据,可以研究下curl_multipcntl进行多线程的快速抓取,此处不做赘述。

分析用户数据,提供分析

通过正则可以进一步匹配出更多的该用户数据,直接上码。

// 获取用户头像
preg_match('/<img .+src=\"&#63;([^\s]+\.(jpg|gif|bmp|bnp|png))\"&#63;.+ alt="php实现爬取和分析知乎用户数据,php_PHP教程" >/i', $str, $match_img);
$img_url = $match_img[1];

// 匹配用户名:
// <span class="name">崔小拽</span>
preg_match('/<span.+class=\"&#63;name\"&#63;>([\x{4e00}-\x{9fa5}]+).+span>/u', $str, $match_name);
$user_name = $match_name[1];

// 匹配用户简介
// class bio span 中文
preg_match('/<span.+class=\"&#63;bio\"&#63;.+\>([\x{4e00}-\x{9fa5}]+).+span>/u', $str, $match_title);
$user_title = $match_title[1];

// 匹配性别
//<input type="radio" name="gender" value="1" checked="checked" class="male"/> 男  
// gender value1 ;结束 中文
preg_match('/<input.+name=\"&#63;gender\"&#63;.+value=\"&#63;1\"&#63;.+([\x{4e00}-\x{9fa5}]+).+\;/u', $str, $match_sex);
$user_sex = $match_sex[1];

// 匹配地区
//<span class="location item" title="北京">
preg_match('/<span.+class=\"&#63;location.+\"&#63;.+\"([\x{4e00}-\x{9fa5}]+)\">/u', $str, $match_city);
$user_city = $match_city[1];

// 匹配工作
//<span class="employment item" title="人见人骂的公司">人见人骂的公司</span>
preg_match('/<span.+class=\"&#63;employment.+\"&#63;.+\"([\x{4e00}-\x{9fa5}]+)\">/u', $str, $match_employment);
$user_employ = $match_employment[1];

// 匹配职位
// <span class="position item" title="程序猿"><a href="/topic/19590046" title="程序猿" class="topic-link" data-token="19590046" data-topicid="13253">程序猿</a></span>
preg_match('/<span.+class=\"&#63;position.+\"&#63;.+\"([\x{4e00}-\x{9fa5}]+).+\">/u', $str, $match_position);
$user_position = $match_position[1];

// 匹配学历
// <span class="education item" title="研究僧">研究僧</span>
preg_match('/<span.+class=\"&#63;education.+\"&#63;.+\"([\x{4e00}-\x{9fa5}]+)\">/u', $str, $match_education);
$user_education = $match_education[1];

// 工作情况
// <span class="education-extra item" title='挨踢'>挨踢</span>
preg_match('/<span.+class=\"&#63;education-extra.+\"&#63;.+>([\x{4e00}-
\x{9fa5}]+)</u', $str, $match_education_extra);
$user_education_extra = $match_education_extra[1];


// 匹配关注话题数量
// class="zg-link-litblue"><strong>41 个话题</strong></a>
preg_match('/class=\"&#63;zg-link-litblue\"&#63;><strong>(\d+)\s.+strong>/i', $str, $match_topic);
$user_topic = $match_topic[1];

// 关注人数
// <span class="zg-gray-normal">关注了
preg_match_all('/<strong>(\d+)<.+<label>/i', $str, $match_care);
$user_care = $match_care[1][0];
$user_be_careed = $match_care[1][1];

// 历史浏览量
// <span class="zg-gray-normal">个人主页被 <strong>17</strong> 人浏览</span>
preg_match('/class=\"&#63;zg-gray-normal\"&#63;.+>(\d+)<.+span>/i', $str, $match_browse);
$user_browse = $match_browse[1];

在抓取的过程中,有条件的话,一定要通过redis入库,确实能提升抓取和入库效率。没有条件的话只能通过sql优化。这里来几发心德。

数据库表设计索引一定要慎重。在spider爬取的过程中,建议出了用户名,左右字段都不要索引,包括主键都不要,尽可能的提高入库效率,试想5000w的数据,每次添加一个,建立索引需要多少消耗。等抓取完毕,需要分析数据时,批量建立索引。

数据入库和更新操作,一定要批量。 mysql 官方给出的增删改的建议和速度:http://dev.mysql.com/doc/refman/5.7/en/insert-speed.html

# 官方的最优批量插入
INSERT INTO yourtable VALUES (1,2), (5,5), ...;

部署操作。程序在抓取过程中,有可能会出现异常挂掉,为了保证高效稳定,尽可能的写一个定时脚本。每隔一段时间干掉,重新跑,这样即使异常挂掉也不会浪费太多宝贵时间,毕竟,time is money。

#!/bin/bash

# 干掉
ps aux |grep spider |awk '{print $2}'|xargs kill -9
sleep 5s

# 重新跑
nohup /home/cuixiaohuan/lamp/php5/bin/php /home/cuixiaohuan/php/zhihu_spider/spider_new.php &  

数据分析呈现

数据的呈现主要使用echarts 3.0,感觉对于移动端兼容还不错。兼容移动端的页面响应式布局主要通过几个简单的css控制,代码如下

// 获取用户头像
preg_match('/<img .+src=\"&#63;([^\s]+\.(jpg|gif|bmp|bnp|png))\"&#63;.+ alt="php实现爬取和分析知乎用户数据,php_PHP教程" >/i', $str, $match_img);
$img_url = $match_img[1];

// 匹配用户名:
// <span class="name">崔小拽</span>
preg_match('/<span.+class=\"&#63;name\"&#63;>([\x{4e00}-\x{9fa5}]+).+span>/u', $str, $match_name);
$user_name = $match_name[1];

// 匹配用户简介
// class bio span 中文
preg_match('/<span.+class=\"&#63;bio\"&#63;.+\>([\x{4e00}-\x{9fa5}]+).+span>/u', $str, $match_title);
$user_title = $match_title[1];

// 匹配性别
//<input type="radio" name="gender" value="1" checked="checked" class="male"/> 男  
// gender value1 ;结束 中文
preg_match('/<input.+name=\"&#63;gender\"&#63;.+value=\"&#63;1\"&#63;.+([\x{4e00}-\x{9fa5}]+).+\;/u', $str, $match_sex);
$user_sex = $match_sex[1];

// 匹配地区
//<span class="location item" title="北京">
preg_match('/<span.+class=\"&#63;location.+\"&#63;.+\"([\x{4e00}-\x{9fa5}]+)\">/u', $str, $match_city);
$user_city = $match_city[1];

// 匹配工作
//<span class="employment item" title="人见人骂的公司">人见人骂的公司</span>
preg_match('/<span.+class=\"&#63;employment.+\"&#63;.+\"([\x{4e00}-\x{9fa5}]+)\">/u', $str, $match_employment);
$user_employ = $match_employment[1];

// 匹配职位
// <span class="position item" title="程序猿"><a href="/topic/19590046" title="程序猿" class="topic-link" data-token="19590046" data-topicid="13253">程序猿</a></span>
preg_match('/<span.+class=\"&#63;position.+\"&#63;.+\"([\x{4e00}-\x{9fa5}]+).+\">/u', $str, $match_position);
$user_position = $match_position[1];

// 匹配学历
// <span class="education item" title="研究僧">研究僧</span>
preg_match('/<span.+class=\"&#63;education.+\"&#63;.+\"([\x{4e00}-\x{9fa5}]+)\">/u', $str, $match_education);
$user_education = $match_education[1];

// 工作情况
// <span class="education-extra item" title='挨踢'>挨踢</span>
preg_match('/<span.+class=\"&#63;education-extra.+\"&#63;.+>([\x{4e00}-
\x{9fa5}]+)</u', $str, $match_education_extra);
$user_education_extra = $match_education_extra[1];


// 匹配关注话题数量
// class="zg-link-litblue"><strong>41 个话题</strong></a>
preg_match('/class=\"&#63;zg-link-litblue\"&#63;><strong>(\d+)\s.+strong>/i', $str, $match_topic);
$user_topic = $match_topic[1];

// 关注人数
// <span class="zg-gray-normal">关注了
preg_match_all('/<strong>(\d+)<.+<label>/i', $str, $match_care);
$user_care = $match_care[1][0];
$user_be_careed = $match_care[1][1];

// 历史浏览量
// <span class="zg-gray-normal">个人主页被 <strong>17</strong> 人浏览</span>
preg_match('/class=\"&#63;zg-gray-normal\"&#63;.+>(\d+)<.+span>/i', $str, $match_browse);
$user_browse = $match_browse[1];

不足和待学习

整个过程中涉及php,shell,js,css,html,正则等语言和部署等基础知识,但还有诸多需要改进完善,小拽特此记录,后续补充例:

  1. php 采用multicul进行多线程。
  2. 正则匹配进一步优化
  3. 部署和抓取过程采用redis提升存储
  4. 移动端布局的兼容性提升
  5. js的模块化和sass书写css。

您可能感兴趣的文章:

  • php IIS日志分析搜索引擎爬虫记录程序
  • php 向访客和爬虫显示不同的内容
  • 一个PHP实现的轻量级简单爬虫
  • PHP实现简单爬虫的方法
  • PHP代码实现爬虫记录——超管用
  • PHP爬虫之百万级别知乎用户数据爬取与分析

www.bkjia.comtruehttp://www.bkjia.com/PHPjc/1096148.htmlTechArticlephp实现爬取和分析知乎用户数据,php 背景说明:小拽利用php的curl写的爬虫,实验性的爬取了知乎5w用户的基本信息;同时,针对爬取的数据...
성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
php怎么把负数转为正整数php怎么把负数转为正整数Apr 19, 2022 pm 08:59 PM

php把负数转为正整数的方法:1、使用abs()函数将负数转为正数,使用intval()函数对正数取整,转为正整数,语法“intval(abs($number))”;2、利用“~”位运算符将负数取反加一,语法“~$number + 1”。

php怎么实现几秒后执行一个函数php怎么实现几秒后执行一个函数Apr 24, 2022 pm 01:12 PM

实现方法:1、使用“sleep(延迟秒数)”语句,可延迟执行函数若干秒;2、使用“time_nanosleep(延迟秒数,延迟纳秒数)”语句,可延迟执行函数若干秒和纳秒;3、使用“time_sleep_until(time()+7)”语句。

php怎么除以100保留两位小数php怎么除以100保留两位小数Apr 22, 2022 pm 06:23 PM

php除以100保留两位小数的方法:1、利用“/”运算符进行除法运算,语法“数值 / 100”;2、使用“number_format(除法结果, 2)”或“sprintf("%.2f",除法结果)”语句进行四舍五入的处理值,并保留两位小数。

如何使用 PHP 爬虫爬取大数据如何使用 PHP 爬虫爬取大数据Jun 14, 2023 pm 12:52 PM

随着数据时代的到来,数据量以及数据类型的多样化,越来越多的企业和个人需要获取并处理海量数据。这时,爬虫技术就成为了一个非常有效的方法。本文将介绍如何使用PHP爬虫来爬取大数据。一、爬虫介绍爬虫是一种自动获取互联网信息的技术。其原理是通过编写程序在网络上自动获取并解析网站内容,并将所需的数据抓取出来进行处理或储存。在爬虫程序的演化过程中,已经出现了许多成熟

php怎么根据年月日判断是一年的第几天php怎么根据年月日判断是一年的第几天Apr 22, 2022 pm 05:02 PM

判断方法:1、使用“strtotime("年-月-日")”语句将给定的年月日转换为时间戳格式;2、用“date("z",时间戳)+1”语句计算指定时间戳是一年的第几天。date()返回的天数是从0开始计算的,因此真实天数需要在此基础上加1。

php怎么判断有没有小数点php怎么判断有没有小数点Apr 20, 2022 pm 08:12 PM

php判断有没有小数点的方法:1、使用“strpos(数字字符串,'.')”语法,如果返回小数点在字符串中第一次出现的位置,则有小数点;2、使用“strrpos(数字字符串,'.')”语句,如果返回小数点在字符串中最后一次出现的位置,则有。

php字符串有没有下标php字符串有没有下标Apr 24, 2022 am 11:49 AM

php字符串有下标。在PHP中,下标不仅可以应用于数组和对象,还可应用于字符串,利用字符串的下标和中括号“[]”可以访问指定索引位置的字符,并对该字符进行读写,语法“字符串名[下标值]”;字符串的下标值(索引值)只能是整数类型,起始值为0。

php怎么读取字符串后几个字符php怎么读取字符串后几个字符Apr 22, 2022 pm 08:31 PM

在php中,可以使用substr()函数来读取字符串后几个字符,只需要将该函数的第二个参数设置为负值,第三个参数省略即可;语法为“substr(字符串,-n)”,表示读取从字符串结尾处向前数第n个字符开始,直到字符串结尾的全部字符。

See all articles

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

뜨거운 도구

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

Atom Editor Mac 버전 다운로드

Atom Editor Mac 버전 다운로드

가장 인기 있는 오픈 소스 편집기

ZendStudio 13.5.1 맥

ZendStudio 13.5.1 맥

강력한 PHP 통합 개발 환경

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

Dreamweaver Mac版

Dreamweaver Mac版

시각적 웹 개발 도구