V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
wyan453351466
V2EX  ›  程序员

可能是目前最好用的国产 PHP 爬虫框架 - XCrawler 1.0.0 版本发布

  •  
  •   wyan453351466 · 2018-06-04 09:01:28 +08:00 · 8298 次点击
    这是一个创建于 2401 天前的主题,其中的信息可能已经有所发展或是发生改变。

    感觉目前很多人提到爬虫首先想到 Python 应该是一种刻板印象吧。其实 PHP 也可以写出很好用的爬虫。而且如果你是以在有限的时间内开发出更好用的爬虫为目的的话,使用自己擅长的语言是再好不过的(以学习为目的的话就另当别论了)。

    于是就有了 XCrawler 这个项目。

    跟其他已有的 PHP 爬虫框架相比,XCrawler 的一个主要区别是,在核心组件上基于已有的成熟组件: Guzzle 和 Symfony 的 DomCrawler。并尽可能在满足常用爬虫功能(多线程 /失败重试 /进度日志 /Dom 解析等..)的前提下保持简单。

    0.1 版本(首个版本)发布的时候,当时是基于一个框架做的。所以使用的时候只能单独作为一个项目去写。使用起来不是很方便。

    这次的主要改进是封装成了一个 composer 包。 所以你可以把 xcrawler 在任何自己喜欢的框架或已有的项目中使用。

    GitHub 地址: https://github.com/yan68/xcrawler

    文档地址: https://xcrawler.yanshuju.com/docs/

    24 条回复    2018-06-18 12:53:42 +08:00
    gouchaoer
        1
    gouchaoer  
       2018-06-04 10:20:23 +08:00
    wyan453351466
        2
    wyan453351466  
    OP
       2018-06-04 10:31:56 +08:00 via iPhone
    @gouchaoer 所以应该把阻塞函数写在外面?这里的需求是请求间隔时间。一般用到阻塞的时候,就是单线程的场景了。

    可以在下个版本改进一下。
    gouchaoer
        3
    gouchaoer  
       2018-06-04 10:50:28 +08:00   ❤️ 1
    这个本来就是单进程 /单线程的,guzzle 的 pool 其实是包装的 curl_multi_*的 api 实现的并发,所以在回调函数里没有数据竞争,甚至可以都不用 redis

    至于这个爬虫框架,我个人觉得这只适合那种遍历的类型,实际业务中的爬虫需求各种各样模式化的爬虫框架根本无法满足,而且把问题复杂化了。。。

    我个人情感上的比较好的爬虫模式为:1、简单的单进程阻塞模型,不用回调不用 pool 不用 yield 啥太难的 2、爬虫并发直接开多进程就完了,简简单单 3、爬虫调度通过 redis 完成,数据老实存 mysql/pg 4、不用封装好的框架,太难拓展 5、有采样机制、log 机制,并且针对爬虫是遍历任务还是更新任务还是搜索任务定制化
    wyan453351466
        4
    wyan453351466  
    OP
       2018-06-04 11:01:17 +08:00 via iPhone
    @gouchaoer

    多线程是用的 curl_multi 系列的函数实现的。

    使用 redis 主要目的是为了实现失败重试和断点续爬这两个功能

    多进程的话,消耗要比多线程要大不少的吧。所以性能要逊色与多线程一些。。
    xiaoz
        5
    xiaoz  
       2018-06-04 11:50:45 +08:00
    请问下文档是用什么工具写的?
    wyan453351466
        6
    wyan453351466  
    OP
       2018-06-04 12:22:24 +08:00 via iPhone   ❤️ 1
    @xiaoz 文档的前端是使用的 hexo 官网( GitHub 上开源的),然后用 PHP 搭一个简单的框架。引入一个 Markdown 的 composer 包就 OK 了
    hubahuba
        7
    hubahuba  
       2018-06-04 12:33:22 +08:00 via Android
    @gouchaoer 大佬可否推荐个,最近在纠结学一下哪个爬虫。做个搜资源(磁力之类的)的站。node python 还是 php,哪个比较好。最近在看 php 的蜘蛛那个框架。
    wplct
        8
    wplct  
       2018-06-04 13:18:18 +08:00
    @hubahuba 建议 python 或 node。node 的异步适合当爬虫,python 库多,方便
    gouchaoer
        9
    gouchaoer  
       2018-06-04 13:47:08 +08:00
    @hubahuba 你如果熟悉 php 就用 php 就 ok 了,爬虫框架其实很多情况下派不上用场,直接用 guzzle、css-selector 和 php-webdriver 之类的手写就 ok 了。。。。另外别用啥异步回调啥的,太难了,就老老实实同步单进程阻塞写法,数据存 mysql,需要并发就开多进程。。。我正在构思一本 php 爬虫的书籍,我想纠正很多爬虫不太好的问题
    wyan453351466
        10
    wyan453351466  
    OP
       2018-06-04 16:07:41 +08:00 via iPhone
    @gouchaoer 这里补充一下。xcrawler 的回调函数不是异步执行的。是同步的哈。。

    xcrawler 的异步并行执行,目前仅仅是在请求阶段(利用的 php 的 curl_multi 系列函数)
    wyan453351466
        11
    wyan453351466  
    OP
       2018-06-04 16:11:06 +08:00 via iPhone
    @gouchaoer 直接用 guzzle 的话,有一个主要问题是,guzzle 框架缺少请求失败重试功能,还有一个是 guzzle 多线程请求的时候,返回结果的回调函数无法得知这个结果对应的是哪个请求。

    主要是有这两个小缺憾。写爬虫时可能会用到的。
    gouchaoer
        12
    gouchaoer  
       2018-06-04 16:36:52 +08:00
    @wyan453351466 guzzle 不是框架是一个 HttpClient,任何 HttpClient 都没有失败重试功能,你要失败重试自己去实现。另外 guzzle 没有多线程,返回结果回调函数里面有一个 index,这个 index 可以判断是哪个请求。。。你没必要用那个 yield 来动态生成 request,直接数组就 ok 了
    wyan453351466
        13
    wyan453351466  
    OP
       2018-06-04 18:27:42 +08:00 via iPhone
    并发请求不是多线程吗


    直接数组,如果请求网址多呢
    wyan453351466
        14
    wyan453351466  
    OP
       2018-06-04 18:35:00 +08:00 via iPhone
    @gouchaoer 所以说直接用 guzzle 写爬虫不方便啊。失败重试要自己写,判断是哪个请求还要自己用数组和 index 判断。而且这个方法在请求数量很大的时候还不适用。
    没听懂你说的 Guzzle 不支持多线程,多并发请求不是多线程吗
    gouchaoer
        15
    gouchaoer  
       2018-06-04 18:52:12 +08:00
    @wyan453351466 不是的,多线程需要用到 php 的 thread safe 版本,curl_multi_*是基于类似 select 的 api 包装的
    hubahuba
        16
    hubahuba  
       2018-06-04 19:14:30 +08:00 via Android
    @gouchaoer 好的大佬,期待出书
    wyan453351466
        17
    wyan453351466  
    OP
       2018-06-05 01:34:06 +08:00 via iPhone
    @gouchaoer

    Curl multi 不是多线程,那 multi 的意义何在?
    开 100 个并行请求如果和不开一样,还要这个干嘛?

    我知道回调函数是串行执行的,但是在请求这个部分请您回答是不是并行。如果是并行,不是多线程,请您解释下是什么。
    http://php.net/manual/zh/function.curl-multi-init.php
    jisibencom
        18
    jisibencom  
       2018-06-05 08:10:20 +08:00
    还是要写大量的代码,不适合我这样的小白。

    有个火车头的 WEB 版就好了
    gouchaoer
        19
    gouchaoer  
       2018-06-05 10:32:47 +08:00
    @wyan453351466
    https://windows.php.net/download/

    你看这个二进制,里面的 ts 版本才是多线程版本,curl_multi_*可以运行在非 ts 版本里,你说他是不是多线程,他只是回调了而已

    我无意和你讨论这些概念,因为这是非常明白的事情了
    ucaime
        20
    ucaime  
       2018-06-07 10:19:33 +08:00
    最好用的?那 Beanbun 算啥?
    http://www.beanbun.org/#/
    wyan453351466
        21
    wyan453351466  
    OP
       2018-06-08 05:28:35 +08:00 via iPhone
    @ucaime 注意关键字“可能”。
    wyan453351466
        22
    wyan453351466  
    OP
       2018-06-18 12:46:22 +08:00
    @gouchaoer ts 版本是线程安全版本,nts 版本是线程不安全版本。这个和是不是多线程有什么关系?
    如果 curl multi 不是多线程,请求速度和 curl 那它存在的意义是什么?

    老哥,建议你先搞清楚 ts 版本和 nts 版本的区别:

    https://blog.csdn.net/qq_31643343/article/details/48996735
    wyan453351466
        23
    wyan453351466  
    OP
       2018-06-18 12:46:53 +08:00
    @wyan453351466 *如果 curl multi 不是多线程,请求速度和 curl 一致, 那它存在的意义是什么?
    wyan453351466
        24
    wyan453351466  
    OP
       2018-06-18 12:53:42 +08:00
    @gouchaoer nts 版本不等于不能开启多线程,好吧? 选择 ts 版本还是 nts 版本 主要是跟使用的服务器( IIS、Nginx )的不同有关系。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1021 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 21:37 · PVG 05:37 · LAX 13:37 · JFK 16:37
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.