当前位置: 首页 > news >正文

如何使用PHP和Selenium快速构建自己的网络爬虫系统

近年来,随着互联网的普及,网络爬虫逐渐成为了信息采集的主要手段之一,然而,常规的爬虫技术不稳定、难以维护,市面上的纯web网页爬虫也只能在静态页面上进行操作。而php结合selenium可达到动态爬虫的效果,具有稳定性高、数据采集全面等优点,被广泛应用于爬虫开发中。本文将介绍如何使用php和selenium快速构建自己的网络爬虫系统。

一、Selenium和ChromeDriver的安装

Selenium是一个自动化测试工具,可以对Web应用程序进行自动化测试,其中将浏览器与操作系统分离式地处理,无强制插入代码实现页面渲染。ChromeDriver则是Selenium中调用Chrome浏览器的驱动程序,可以使Selenium直接操作Chrome,从而实现动态页面的爬取。

首先需要在本地安装Chrome浏览器和PHP环境。接着,我们需要安装相应版本的Selenium和ChromeDriver,在命令行中输入以下代码即可安装:

1

composer require facebook/webdriver

然后将ChromeDriver二进制文件(根据自己的本地Chrome版本下载相应版本的ChromeDrive)置于系统Path变量环境中,代码如下:

1

2

3

$webdriver = FacebookWebDriverRemoteRemoteWebDriver::create(

    'http://localhost:9515', FacebookWebDriverChromeChromeOptions::class

);

二、构建Selenium和ChromeDriver的封装类

Selenium封装类主要用来维护Selenium和ChromeDriver,避免重复创建、销毁,代码如下:

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

class Selenium

{

    private static $driver;

    private static $selenium;

    public static function getInstance()

    {

        if (null === self::$selenium) {

            $options = new ChromeOptions();

            $options->addArguments(['--no-sandbox','--disable-extensions','--headless','--disable-gpu']);

            self::$driver = RemoteWebDriver::create(

                'http://localhost:9515',

                DesiredCapabilities::chrome()->setCapability(

                    ChromeOptions::CAPABILITY,

                    $options

                )

            );

            self::$selenium = new self();

        }

        return self::$selenium;

    }

    public function __destruct()

    {

        self::$driver->quit();

        self::$selenium = null;

    }

    public function getDriver()

    {

        return self::$driver;

    }

}

注意,参数中的ChromeOptions主要是为了在无GUI(图形化界面)下仍能稳定运行,--no-sandbox参数是为了防止在linux系统下运行时报错。

三、创建网页源码解析类

爬虫系统的核心在于解析非静态页面,这里需要创建源码解析类,使用正则表达式或XPath表达式来定位和获取目标节点信息。

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

class PageParser

{

    private $pageSource;

    public function __construct(string $pageSource)

    {

        $this->pageSource = $pageSource;

    }

    public function parse(string $expression, $list = false)

    {

        if ($list) {

            return $this->parseList($expression);

        }

        return $this->parseSingle($expression);

    }

    private function parseList(string $expression)

    {

        $domXpath = new DOMXPath(@DOMDocument::loadHTML($this->pageSource));

        $items = $domXpath->query($expression);

        $result = [];

        foreach ($items as $item) {

            array_push($result,trim($item->nodeValue));

        }

        return $result;

    }

    private function parseSingle(string $expression)

    {

        $domXpath = new DOMXPath(@DOMDocument::loadHTML($this->pageSource));

        $item = $domXpath->query($expression)->item(0);

        if ($item) {

            return trim($item->nodeValue);

        }

        return '';

    }

}

这里主要用到了DOMXPath类和DOMDocument类来解析页面中的HTML节点,分别通过parseList和parseSingle方法来定位和获取多个和一个目标节点的内容。

四、创建爬虫类

最后,我们需要构建一个专门爬取页面内容的爬虫类,代码如下:

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

class Spider

{

    private $selenium;

    private $url;

    public function __construct($url)

    {

        $this->selenium = Selenium::getInstance();

        $this->url = $url;

        $this->selenium->getDriver()->get($url);

        sleep(1);

    }

    public function __destruct()

    {

        $this->selenium->getDriver()->close();

        $this->selenium = null;

    }

    public function getContent($expression, $list = false)

    {

        $pageSource = $this->selenium->getDriver()->getPageSource();

        $parser = new PageParser($pageSource);

        return $parser->parse($expression, $list);

    }

}

该类的getContent方法接收两个参数,一个是目标节点的XPath表达式,另一个是是否获取多个内容。 getModelContent函数请求URL并解析节点来获取所需内容,该函数获取结束后关闭浏览器进程。

五、使用示例

最后,我们使用实际例子来说明如何使用这个爬虫类。假设我们需要从一个拥有多个a标签的网页上,爬取a标签中的href属性和文本信息。我们可以通过以下代码来实现:

1

2

3

4

5

6

7

8

$spider = new Spider('https://www.example.com');

$aTags = $spider->getContent('//a', true);

foreach ($aTags as $a) {

    $href = $a->getAttribute('href');

    $text = $a->nodeValue;

    echo "$href -> $text

";

}

在以上代码中,首先使用Spider类获取页面源码,然后通过XPath表达式获取多个a标签的节点信息,最后通过getAttribute和nodeValue方法获取每个a标签的href属性和文本。

六、总结

综上所述,本文通过介绍如何使用PHP和Selenium构建网页爬虫系统,并通过实际示例说明如何获取页面中的节点信息,该爬虫具有稳定性高、数据采集全面等优点,具有一定的应用价值。但同时需要注意的是,爬取数据时需要注意合法性和道德性,并遵守相关法律法规。

相关文章:

如何使用PHP和Selenium快速构建自己的网络爬虫系统

近年来,随着互联网的普及,网络爬虫逐渐成为了信息采集的主要手段之一,然而,常规的爬虫技术不稳定、难以维护,市面上的纯web网页爬虫也只能在静态页面上进行操作。而php结合selenium可达到动态爬虫的效果,具…...

intellij idea安装R包ggplot2报错问题求解

1、intellij idea安装R包ggplot2问题 在我上次解决图形显示问题后,发现安装ggplot2包时出现了问题,这在之前高版本中并没有出现问题, install.packages(ggplot2) ERROR: lazy loading failed for package lifecycle * removing C:/Users/V…...

【C++】初识C++(一)

一.什么是C C语言是结构化和模块化的语言,适合处理较小规模的程序。对于复杂的问题,规模较大的程序,需要高度 的抽象和建模时,C语言则不合适。为了解决软件危机, 20世纪80年代, 计算机界提出了OOP(object o…...

【智能算法】目标检测算法

目录 一、目标检测算法分类 二、 常见目标检测算法及matlab代码实现 2.1 R-CNN 2.1.1 定义 2.1.2 matlab代码实现 2.2 Fast R-CNN 2.2.1 定义 2.2.2 matlab代码实现 2.3 Faster R-CNN 2.3.1 定义 2.3.2 matlab代码实现 2.4 YOLO 2.4.1 定义 2.4.2 matlab代码实现…...

python 中 json.load json.loadd json.dump json.dumps 详解

在Python中,json 模块提供了用于处理JSON数据的函数。json.load(), json.loads(), json.dump(), 和 json.dumps() 是这个模块中用于序列化和反序列化JSON数据的主要函数。下面是它们之间的区别详解: json.load() 作用:从一个文件对象&#x…...

【UE 网络】专用服务器和多个客户端加入游戏会话的过程,以及GameMode、PlayerController、Pawn的创建流程

目录 0 引言1 多人游戏会话1.1 Why?为什么要有这个1.2 How?怎么使用? 2 加入游戏会话的流程总结 🙋‍♂️ 作者:海码007📜 专栏:UE虚幻引擎专栏💥 标题:【UE 网络】在网络…...

磁盘分区工具(fdisk 和 parted)区别及操作笔记

fdisk 和 parted 都是 Linux 系统中用于磁盘分区的工具。 两者主要区别: 支持的分区表类型: fdisk 主要支持 MBR分区表,MBR分区表支持的硬盘单个分区最大容量为2TB,最多可以有4个主分区。parted 支持 MBR分区表 和 GPT分区表&…...

VisualStudio2019受支持的.NET Core

1.VS Studio2019受支持的.NET Core? 适用于 Visual Studio 的 .NET SDK 下载 (microsoft.com) Visual Studio 2019 默认并不直接支持 .NET 6 及以上版本。要使用 .NET 6 或更高版本,你需要在 Visual Studio 2019 中采取额外步骤,比如安装相应…...

Java——IO流(二)-(1/7):字符流-FileReader、FileWriter、字符输出流的注意事项(构造器及常用方法、小结)

目录 文件字符输入流-读字符数据进来 介绍 构造器及常用方法 实例演示 文件字符输出流-写字符数据出去 介绍、构造器及常用方法 实例演示 字符输出流使用时的注意事项 小结 文件字符输入流-读字符数据进来 介绍 FileReader(文件字符输入流) 作…...

Spring循环依赖问题——从源码画流程图

文章目录 关键代码相关知识为什么要使用二级缓存为什么要使用三级缓存只使用两个缓存的问题不能解决构造器循环依赖为什么多例bean不能解决循环依赖问题初始化后代理对象赋值给原始对象解决循环依赖SpringBoot开启循环依赖 循环依赖 在线流程图 关键代码 从缓存中查询getSingl…...

Android SurfaceFlinger——动画播放准备(十五)

BootAnimation 本质上是一个线程,执行 run 之后,会先执行 readyToRun,接着执行 treadLoop 方法。 一、线程启动 1、BootAnimation 源码位置:/frameworks/base/cmds/bootanimation/BootAnimation.cpp readyToRun status_t BootAnimation::readyToRun() {// 添加默认资源…...

Zynq7000系列FPGA中的DMA控制器简介(二)

AXI互连上的DMA传输 所有DMA事务都使用AXI接口在PL中的片上存储器、DDR存储器和从外设之间传递数据。PL中的从设备通过DMAC的外部请求接口与DMAC通信,以控制数据流。这意味着从设备可以请求DMA交易,以便将数据从源地址传输到目标地址。 虽然DMAC在技术…...

获取 url 地址栏 ? 后面的查询字符串,并以键值对形式放到对象里面

写在前面 在前端面试当中,关于 url 相关的问题很常见,而对于 url 请求参数的问题也很常见,大部分以笔试题常见,今天就根据这道面试题一起来看一下。 问题 获取 url 地址栏?后面的查询字符串,并以键值对形式放到对象…...

List接口, ArrayList Vector LinkedList

Collection接口的子接口 子类Vector,ArrayList,LinkedList 1.元素的添加顺序和取出顺序一致,且可重复 2.每个元素都有其对应的顺序索引 方法 在index 1 的位置插入一个对象,list.add(1,list2)获取指定index位置的元素&#…...

探讨数字化背景下VSM(价值流程图)的挑战和机遇

在信息化、数字化飞速发展的今天,各行各业都面临着前所未有的挑战与机遇。作为源自丰田生产模式的VSM(价值流程图),这一曾经引领制造业革命的工具,在数字化背景下又将如何乘风破浪,应对新的市场格局和技术变…...

Conda跨平台环境迁移

问题描述: 在一台Ubuntu电脑上完全复刻在Windows中通过conda创建的环境。 导出环境 在Windows机器上,需要导出当前conda环境的配置。这将生成一个environment.yml文件,其中包含所有已安装的包和版本信息。 打开Anaconda Prompt(…...

全面掌握 Jackson 序列化工具:原理、使用与高级配置详解

全面掌握 Jackson 序列化工具:原理、使用与高级配置详解 Jackson 是一个功能强大的 JSON 处理库,广泛应用于 Java 项目中。它提供了丰富的功能和灵活的配置选项,可以轻松地在 Java 对象和 JSON 数据之间进行转换。本文将详细介绍 Jackson 的…...

mathtype7.4永久激活码密钥及2024最新破解版注册码附安装教程

MathType 7版本号还提升了对教育行业的支持,如增加了大量预定义的教学公式和符号,使老师和学生在教学过程中能够更加便捷的应用。同时,它还加强了云备份功能,用户可将自己的公式存储在云端,随时随地访问和编辑&#xf…...

【SQL】优化慢 SQL的简单思路

优化慢 SQL 需要综合考虑多个方面,包括查询的结构、索引的使用、表结构设计等。以下是一些常见的 SQL 优化技巧和步骤: 1. 检查查询计划 使用数据库提供的工具查看查询计划(例如 MySQL 的 EXPLAIN 命令)可以帮助了解查询的执行路…...

禁止浏览器对input的自动填充和填充提示(适用于谷歌、火狐、Edge(原IE浏览器)等常见浏览器)

目录 1.要解决的问题2.一技能:原生属性,小试牛刀3.二技能:傀儡input,瞒天过海4.三技能:JavaScript出击,直接开大5.九九八十一难,永远还有最后一难 写在前面: 如有转载,务…...

CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型

CVPR 2025 | MIMO:支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题:MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者:Yanyuan Chen, Dexuan Xu, Yu Hu…...

DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径

目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...

c++ 面试题(1)-----深度优先搜索(DFS)实现

操作系统:ubuntu22.04 IDE:Visual Studio Code 编程语言:C11 题目描述 地上有一个 m 行 n 列的方格,从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子,但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...

剑指offer20_链表中环的入口节点

链表中环的入口节点 给定一个链表,若其中包含环,则输出环的入口节点。 若其中不包含环,则输出null。 数据范围 节点 val 值取值范围 [ 1 , 1000 ] [1,1000] [1,1000]。 节点 val 值各不相同。 链表长度 [ 0 , 500 ] [0,500] [0,500]。 …...

【算法训练营Day07】字符串part1

文章目录 反转字符串反转字符串II替换数字 反转字符串 题目链接&#xff1a;344. 反转字符串 双指针法&#xff0c;两个指针的元素直接调转即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …...

[10-3]软件I2C读写MPU6050 江协科技学习笔记(16个知识点)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16...

ElasticSearch搜索引擎之倒排索引及其底层算法

文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...

【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)

要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况&#xff0c;可以通过以下几种方式模拟或触发&#xff1a; 1. 增加CPU负载 运行大量计算密集型任务&#xff0c;例如&#xff1a; 使用多线程循环执行复杂计算&#xff08;如数学运算、加密解密等&#xff09;。运行图…...

Spring是如何解决Bean的循环依赖:三级缓存机制

1、什么是 Bean 的循环依赖 在 Spring框架中,Bean 的循环依赖是指多个 Bean 之间‌互相持有对方引用‌,形成闭环依赖关系的现象。 多个 Bean 的依赖关系构成环形链路,例如: 双向依赖:Bean A 依赖 Bean B,同时 Bean B 也依赖 Bean A(A↔B)。链条循环: Bean A → Bean…...

人机融合智能 | “人智交互”跨学科新领域

本文系统地提出基于“以人为中心AI(HCAI)”理念的人-人工智能交互(人智交互)这一跨学科新领域及框架,定义人智交互领域的理念、基本理论和关键问题、方法、开发流程和参与团队等,阐述提出人智交互新领域的意义。然后,提出人智交互研究的三种新范式取向以及它们的意义。最后,总结…...