V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
laoyuan
V2EX  ›  Python

爬虫 pyspider 学习笔记

  •  
  •   laoyuan ·
    laoyuan · 2015-04-29 15:39:39 +08:00 · 9077 次点击
    这是一个创建于 3500 天前的主题,其中的信息可能已经有所发展或是发生改变。
    文档: http://docs.pyspider.org/
    版本:pyspider 0.3.4
    环境:Mac OS X 10.10


    Docs » Introduction

    代码部分看了个大概意思,就是把http://scrapy.org/ 页面上的所有a href= 链接抽取成{url, title} 字典。

    Docs » Quickstart

    安装和启动都很傻瓜。

    关于callback:
    查了一下大概就是把callback 前边的参数传给callback 这个函数来处理的意思。
    self.crawl('http://scrapy.org/', callback=self.index_page)
    翻译过来就是 self.index_page(self.crawl('http://scrapy.org/')),把页面抓下来交给index_page() 处理。

    使用WebUI:
    create 一个项目,以默认脚本为例,点run,这时并没有开抓,只是添加了一条url 而已,点下面的follows 可以看到这条,然后点链接后面的三角开始第一次抓取,也就是执行index_page(),得到了18条新链接,点任意一条的三角,就是对这个链接执行detail_page(),右下角可以看到detail_page() return 的结果了。注意run 所在的绿色框内的内容变化,run 下面的前进后退相当于切换run 的内容:on_start、index_page、detail_page。

    这节文档里有很多备注*,挨个点开看一眼,不明白也没关系,尽量多的弄明白,尤其是Response,它就是crawl() 爬到的结果,修改detail_page() 把Response 的每一项都return 出来看看(其实可以在return 之前print 出来看)。

    Docs » Command Line

    不是很明白,大体过了一遍。

    Docs » Level 1: HTML and CSS Selector

    这个例子中实际detail_page() 这一步没有必要,index_page() 得到的页面就可以抽取到足够的信息了,如何一次crawl() 生成多个result 我还在研究。将例子运行起来之后,发现数据保存在执行pyspider 命令行所在目录下data 文件夹内,sqlite 格式。做web 还是得保存到MySQL 里,转到学习文档Deployment。

    Docs » Deployment

    装好RabbitMQ,-detached 方式运行起来,安装pyspider[all],编辑好config.json 就可以运行了。之前没用Python 连过MySQL,结果没跑起来,结合错误信息将 /Library/Python/2.7/site-packages/mysql/connector/connection.py
    self._unix_socket = '/tmp/mysql.sock' 这一行配置下就好了。
    在MySQL 环境把Level 1 重新过一遍,可以发现webUI 项目页面的操作仅相当于调试并没有保存结果,在项目列表页把status 改为runnig 再点run,才是真正启动爬虫,数据入库。

    Docs » Level 2: AJAX and More HTTP

    这一节的示例代码解答了Level 1 提出来的问题:一次crawl() 只能打包成一个result。同时这一节带来更多问题:如何自定义header、使用cURL、POST。

    Docs » Level 3: Render with PhantomJS

    安装PhantomJS,Deployment 里给出的config.json 示例漏掉了一行:"phantomjs_proxy": "localhost:25555", 否则尽管localhost://25555 能访问,crawl() 仍然报501错误。第一个例子有时候能得到结果有时候不能,网络原因吧。

    Docs » Architecture

    主要弄明白了Processor 是干什么的。既然是异步的,不知道Fetcher 得到的结果暂时存放在哪里,假如很多Fetcher 在工作,Processor 或者result_worker 来不及处理会不会爆仓?可能Processor 处理的速度和Fetcher 抓页面不在一个数量级上,永远都不会爆。

    Docs » About Projects

    burst 大概就是从闲着没活可干到来活了,开干的那一下可以几个页面一块抓的意思。

    Docs » Script Environment

    抓一个不存在的页面,测试下 @catch_status_code_error,试试print

    Docs » self.crawl

    重点来了,先测试下header:
    headers={"User-Agent": "aaa"} 抓一下 http://headers.cloxy.net/request.php ,然后在 index_page() 里直接print response.text 看结果。发现headers 参数放在@config 里不好使,放在crawl_config 里可以。
    再测试下post:method="POST", data="xxx"
    另外age 的解释应该是 don't re-crawl if last_crawl_time + age < now. 少了个don't

    Docs » Response

    有些不知道干嘛的没关系了,有Response.text 基本就够了。

    Docs » self.send_message

    这一课才真正解决了Level 1 提出来的问题!原来一个url 只能对应一个result!
    第 1 条附言  ·  2015-05-24 18:51:02 +08:00
    'Accept-Encoding': 'gzip, deflate' 遭遇 fetch_type='js',CentOS 7 乱码,Mac 直接PhantomJS crash
    总之fetch_type='js' 时,header 不可设gzip
    6 条回复    2015-11-15 10:24:04 +08:00
    binux
        1
    binux  
       2015-04-29 19:02:19 +08:00   ❤️ 2
    1. @config 作用的是「以 @config 修饰的 method 为 callback 的 crawl 请求」。也就是说,@config 是以抓取的页面类型,而不是前链的页面类型来作用的。
    2. Fetcher 到的结果,会通过消息队列给 Processor,队列大小可以设置。
    3. 一个 callback 可以通过 yield 返回多个结果,只不过,只有最后一个会被保存到 resultdb 中。需要重载 result_worker 或者 on_result 自行处理多个结果的情况。
    laoyuan
        2
    laoyuan  
    OP
       2015-04-29 21:36:52 +08:00
    @binux 感谢指点!
    明天抓虾米,把我200多个好友收藏的音乐跑下来看谁收歌和我最接近,最近闹歌荒!
    laoyuan
        3
    laoyuan  
    OP
       2015-05-04 14:08:11 +08:00
    @binux 抓虾米的快写好了,目前比较郁闷的地方就是webUI 脚本窗口没有行号,出错了还要去数。。
    laoyuan
        4
    laoyuan  
    OP
       2015-05-09 15:02:24 +08:00
    headers 设置为空的方法:
    crawl_config = {
    'headers': {
    'User-Agent': '',
    'Accept': '',
    'Accept-Encoding': '',
    },
    }
    udumbara
        5
    udumbara  
       2015-11-15 01:38:50 +08:00
    关于 send_message()请教下,在 debug 界面可以正常显示出 message 数量,点开也可以显示内容,但是点 run 却没有反应,不知道您是怎么设置的,方便给过样例么?谢谢
    laoyuan
        6
    laoyuan  
    OP
       2015-11-15 10:24:04 +08:00
    @udumbara
    文档里的案例就可以啊。我自己写的用 send_message 来触发一批新的抓取任务

    send_message(self.project_name, ar_url)

    def on_message(self, project, ar_url):
    ....for url in ar_url:
    ........self.crawl(url 。。。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3367 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 11:34 · PVG 19:34 · LAX 03:34 · JFK 06:34
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.