数据之路 - Python爬虫 - PySpider框架

谁践踏了优雅 2023-06-02 10:59 199阅读 0赞

1.PySpider基本功能

  • 提供方便易用的WebUI系统,可视化地编写和调试爬虫。
  • 提供爬取进度监控、 爬取结果查看、爬虫项目管理等功能。
  • 支持多种后端数据库,如MySQL、 MongoDB、 Redis、 SQLite、 Elasticsearch、 PostgreSQL。
  • 支持多种消息队列,如RabbitMQ、 Beanstalk、 Redis、 Kombu。
  • 提供优先级控制、失败重试、定时抓取等功能。
  • 对接了PhantomJS,可以抓取JavaScript渲染的页面。
  • 支持单机和分布式部署,支持Docker部署。

2.PySpider架构

pyspider的架构主要分为Scheduler(调度器)、Fetcher( 抓取器)、Processer(处理器)三个部分,整个爬取过程受到Monitor (监控器)的监控,抓取的结果被Result Worker (结果处理器)处理。

Scheduler发起任务调度,Fetcher负责抓取网页内容,Processer负责解析网页内容,然后将新生成的Request发给Scheduler进行调度,将生成的提取结果输出保存。

  • 每个pyspider 的项目对应一个Pythonj阅本,该脚本中定义了一个Handler 类,它有一个on_start()方法。 爬取首先调用on_start()方法生成最初的抓取任务,然后发送给Scheduler进行调度。
  • Scheduler将抓取任务分发给Fetcher进行抓取,Fetcher执行并得到响应,随后将响应发送给Processer。
  • Processer 处理响应并提取出新的 URL生成新的抓取任务,然后通过消息队列的方式通知Schduler 当前抓取任务执行情况,并将新生成的抓取任务发送给Scheduler。 如果生成了新的提取结果,则将其发送到结果队列等待ResultWorker处理。
  • Scheduler接收到新的抓取任务,然后查询数据库,判断其如果是新的抓取任务或者是需要重试的任务就继续进行调度,然后将其发送回Fetcher进行抓取。
  • 不断重复以上工作,直到所有的任务都执行完毕,抓取结束。
  • 抓取结束后,程序会回调on_finished()方法,这里可以定义后处理过程。

1489220-20190629165613728-380916724.png

3.PySpider命令行

ContractedBlock.gif ExpandedBlockStart.gif

  1. ====================================================================================
  2. pyspider [OPTIONS) COMMAND [ARGS]
  3. -c, --config FILENAME # 指定配置文件名称
  4. --logging-config TEXT # 日志配置文件名称,默认 pyspider/pyspider/logging.conf
  5. --debug # 开启调试模式
  6. --queue-maxsize INTEGER # 队列的最大长度
  7. --taskdb TEXT # taskdb的数据库连接字符串,默认:sqlite
  8. --projectdb TEXT # projectdb的数据库连接字符串,默认:sqlite
  9. --resultdb TEXT # resultdb的数据库连接字符串,默认:sqlite
  10. --message-queue TEXT # 消息队列连接字符串,默认:multiprocessing.Queue
  11. --phantomjs-proxy TEXT # PhantomJS使用的代理,ip:port的形式
  12. --data-path TEXT # 数据库存放的路径
  13. --version # pyspider的版本
  14. --help # 显示帮助信息
  15. ====================================================================================
  16. pyspider scheduler [OPTIONS]
  17. --xmlrpc / --no-xmlrpc
  18. --xmlrpc -host TEXT
  19. --xmlrpc-port INTEGER
  20. --inqueue-limit INTEGER # 任务队列的最大长度,如果满了则新的任务会被忽略
  21. --delete-time INTEGER # 设置为delete标记之前的删除时间
  22. --active-tasks INTEGER # 当前活跃任务数量配置
  23. loop-limit INTEGER # 单轮最多调度的任务数量
  24. -scheduler els TEXT # Scheduler使用的类
  25. --help # 显示帮助信息
  26. ====================================================================================
  27. pysp1der fetcher [OPTIONS]
  28. --xmlrpc / --no-xmlrpc
  29. --xmlrpc-host TEXT
  30. --xmlrpc-port INTEGER
  31. --poolsize INTEGER # 同时请求的个数
  32. --proxy TEXT # 使用的代理
  33. --user-agent TEXT # 使用的User-Agent
  34. --timeout TEXT # 超时时间
  35. --fetcher-els TEXT # Fetcher使用的类
  36. --help # 显示帮助信息
  37. ====================================================================================
  38. pyspider processor [OPTIONS]
  39. --processor-cls TEXT Processor # 使用的类
  40. --help # 显示帮助信息
  41. ====================================================================================
  42. pyspider webui [OPTIONS]
  43. --host TEXT # 运行地址
  44. --port INTEGER # 运行揣口
  45. --cdn TEXT # JS和css的CDN服务器
  46. --scheduler-rpc TEXT # Scheduler的xmlrpc路径
  47. --fetcher-rpc TEXT # Fetcher的xmlrpc路径
  48. --max-rate FLOAT # 每个项目最大的rate
  49. --max-burst FLOAT # 每个项目最大的burst
  50. --username TEXT # Auth验证的用户名
  51. --password TEXT # Auth验证的密码
  52. --need-auth # 是否需要验证
  53. -- webui-instance TEXT # 运行时使用的Flask应用
  54. --help # 显示帮助信息
  55. ====================================================================================

4.PySpider基本使用

pyspider all,启动pyspider的所有组件,包括PhantomJS、ResultWorker、Processer、Fetcher、 Scheduler、WebUI,这些都是pyspider运行必备的组件。

  1. from libs.base_handler import *
  2. class Handler(BaseHandler):
  3. @every(minutes=24*60, seconds=0)
  4. def on_start(self):
  5. self.crawl('http://scrapy.org/', callback=self.index_page)
  6. # @every:告诉调度器 on_start方法每天执行一次。
  7. # on_start:作为爬虫入口代码,调用此函数,启动抓取。
  8. @config(age=10*24*60*60)
  9. def index_page(self, response):
  10. for each in response.doc('a[href^="http://"]').items():
  11. self.crawl(each.attr.href, callback=self.detail_page)
  12. # @config:告诉调度器 request请求的过期时间是10天,10天内再遇到这个请求直接忽略。此参数亦可在self.crawl(url, age=10*24*60*60)中设置。
  13. # index_page:获取一个Response对象,response.doc是pyquery对象的一个扩展方法。
  14. def detail_page(self, response):
  15. return {
  16. "url": response.url,
  17. "title": response.doc('title').text(),
  18. }
  19. # detail_page:返回一个结果集对象。这个结果默认会被添加到resultdb数据库(如果启动时没有指定数据库默认调用sqlite数据库)。

5.crawl方法

  1. - url:爬取的url,可以是单个URL字符串,也可以是URL列表。
  2. =================================================================================================
  3. - callbackcallback是回调函数,指定了该URL对应的响应内容用哪个方法来解析。
  4. def on_start(self):
  5. self.crawl('http://scrapy.org/', callback=self.index_page)
  6. =================================================================================================
  7. - age:任务的有效时间。 如果某个任务在有效时间内且已经被执行,则它不会重复执行。
  8. # 设置方法1
  9. def on_start(self):
  10. self.crawl('http://www.example.org/', callback=self.callback, age=10*24*60*6o)
  11. # 设置方法2
  12. @config(age=10 * 24 * 60 * 60)
  13. def callback(self):
  14. pass
  15. =================================================================================================
  16. - priority:爬取任务的优先级,其值默认是0, priority的数值越大,对应的请求会越优先被调度。
  17. def index_page(self):
  18.   self.crawl('http://www.example.org/page.html', callback=self.index_page)
  19.   self.crawl('http://www.example.org/233.html’, callback=self .detail_page, priority=l)
  20. =================================================================================================
  21. - exetime:设置定时任务,其值是时间戳,默认是0,即代表立即执行。
  22. import time
  23. def on_start(self):
  24.   self.crawl(’http://www.example.org/', callback=self.callback, exetime=time.time()+30*60)
  25. =================================================================================================
  26. - retries:可以定义重试次数,其值默认是3
  27. =================================================================================================
  28. - itag:设置判定网页是存发生变化的节点值,在爬取时会判定次当前节点是否和上次爬取到的节点相同。
  29. 如果节点相同,则证明页面没有更新,就不会重复爬取。
  30. def index_page(self,response):
  31. for item in response.doc('.item’).items():
  32. self.crawl(item.find('a').attr.url, callback=self.detail_page, itag=item.find('.update-time’).text())
  33. =================================================================================================
  34. - auto_recrawl:当开启时,爬取任务在过期后会重新执行,循环时间即定义的age时间长度。
  35. def on_start(self):
  36. self.craw1('http://www.example.org/', callback=self.callback, age=5*60*60, auto_recrawl=True)
  37. =================================================================================================
  38. - methodHTTP请求方式,它默认是GET 如果想发起POST请求,可以将method设置为POST
  39. =================================================================================================
  40. - params:用于定义GET请求参数。
  41. def on_start(self):
  42. self.crawl(’http://httpbin.org/get’, callback=self.callback, params={
  43. 'a':123, 'b':'c'})
  44. self.crawl('http://httpbin.org/get?a=123&b=c’, callback=self.callback)
  45. =================================================================================================
  46. - data:用于传递POST表单数据。
  47. def on_start(self):
  48. self.crawl('http://httpbin.org/post', callback=self.callback, method='POST’, data={
  49. 'a':123, 'b':'c'})
  50. =================================================================================================
  51. - files:上传的文件,需要指定文件名。
  52. def on_start(self):
  53. self.crawl(’http://httpbin.org/post', callback=self.callback, method=’POST’, files={field:{filename:'content'}})
  54. =================================================================================================
  55. - user_agent:爬取使用的User-Agent
  56. - headers:爬取时使用的Headers,即Request Headers
  57. - cookies:爬取时使用的Cookies,为字典格式。
  58. - connect_timeout:初始化连接时的最长等待时间,它默认是20秒。
  59. - timeout:抓取网页时的最长等待时间,它默认是120秒。
  60. - allow_redirects:确定是否自动处理重定向,它默认是True
  61. - validate_cert:确定是否验证证书,此选项对HTTPS请求有效,默认是True
  62. =================================================================================================
  63. - proxy:爬取时使用的代理,它支持用户名密码的配置。
  64. # 设置方法1
  65. def on_start(self):
  66. self.crawl(’http://httpbin.org/get', callback=self.callback, proxy=’127.0.0.1:9743')
  67. # 设置方法2
  68. class Handler(BaseHandler):
  69. crawl_config = { 'proxy': '121.0.0.1:9743' }
  70. =================================================================================================
  71. - fetch_type:开启PhantomJS渲染。如果遇到JavaScript渲染的页面,指定此字段即可实现PhantomJS的对接,
  72. pyspider将会使用PhantomJS进行网页的抓取。
  73. def on_start(self):
  74. self.crawl('https://www.taobao.com', callback=self.index_page, fetch_type=’js')
  75. =================================================================================================
  76. - js_script:页面加载完毕后执行的JavaScript脚本。
  77. def on_start(self):
  78. self.crawl('http://www.example.org/,callback=self.callback, fetch_type=’js’, js_script='''
  79. function() {
  80. window. scrollTo(0, document.body.scrollHeight);
  81. return 123;
  82. }''')
  83. =================================================================================================
  84. - js_run_at:JavaScript脚本运行的位置,是在页面节点开头还是结尾,默认是结尾,即document-end。
  85. - js_viewport_width/js_viewport_height:渲染页面时的窗口大小。
  86. - load_ images:加载JavaScript页面时确定是否加载图片,它默认是否。
  87. =================================================================================================
  88. - save
  89. # 设置方法1
  90. def on_start(self):
  91. self.crawl(’http://www.example.org/', callback=self.callback, save={'page': 1})
  92. # 设置方法2
  93. def callback(self, response):
  94. return response.save['page']
  95. =================================================================================================
  96. - cancel:是取消任务,如果一个任务是ACTIVE状态的,则需要将force_update设置为True
  97. - force_ update

6.任务区分

在pyspider判断两个任务是否是重复的是使用的是该任务对应的URL的MD5值作为任务的唯一ID,如果D相同,那么两个任务就会判定为相同,其中一个就不会爬取了。很多情况下请求的链接可能是同一个,但是POST的参数不同。

这时可以重写task_id()方法,改变这个ID的计算方式来实现不同任务的区分。

  1. import json
  2. from pyspider.libs.utils import md5string
  3. def get_taskid(self, task):
  4. return md5string(task['url']+json.dumps(task['fetch'].get('data','')))

7.全局配置

pyspider可以使用crawl_config来指定全局的配置,配置中的参数会和crawl()方法创建任务时的参数合井。

  1. class Handler(BaseHandler):
  2. crawl_config = {
  3. 'headers':{
  4. 'User-Agent':'GoogleBot'}}

8.定时爬取

通过every属性来设置爬取的时间间隔。

  1. @every(minutes=24 * 60)
  2. def on_start(self):
  3. for url in urllist:
  4. self.crawl(url, callback=self.index_page)

9.项目状态

每个项目都有6个状态,分别是TODO、 STOP、 CHECKING、 DEBUG、 RUNNING、 PAUSE。

  • TODO:它是项目刚刚被创建还未实现时的状态。
  • STOP:如果想停止某项目的抓取,可以将项目的状态设置为STOP。
  • CHECKING:正在运行的项目被修改后就会变成CHEC阻NG状态,项目在中途出错需要调整的时候会遇到这种情况。
  • DEBUG/RUNNING:这两个状态对项目的运行没有影响,状态设置为任意一个,项目都可以运行,但是可以用二者来区分项目是否已经测试通过。
  • PAUSE:当爬取过程中出现连续多次错误时,项目会自动设置为PAUSE状态,并等待一定时间后继续爬取。

转载于:https://www.cnblogs.com/Iceredtea/p/11107890.html

发表评论

表情:
评论列表 (有 0 条评论,199人围观)

还没有评论,来说两句吧...

相关阅读

    相关 爬虫PySpider框架

    PySpider web界面编写调试脚本,启停脚本,监控执行状态,查看活动历史,获取产出结果: 提供SaaS服务,可以在线提交部署 支持MySQL、Mo