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

2018-06-04 09:01:28 +08:00
 wyan453351466

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

于是就有了 XCrawler 这个项目。

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

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

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

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

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

8277 次点击
所在节点    程序员
24 条回复
gouchaoer
2018-06-04 10:20:23 +08:00
wyan453351466
2018-06-04 10:31:56 +08:00
@gouchaoer 所以应该把阻塞函数写在外面?这里的需求是请求间隔时间。一般用到阻塞的时候,就是单线程的场景了。

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

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

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

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

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

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

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

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


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

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

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

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

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

我无意和你讨论这些概念,因为这是非常明白的事情了
ucaime
2018-06-07 10:19:33 +08:00
最好用的?那 Beanbun 算啥?
http://www.beanbun.org/#/

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/460110

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX