- pyspider的架构主要分为Scheduler调度器、Fetcher抓取器、Processer处理器三部分,整个抓取过程都会受到Monitor监控器的监控,抓取的结果被Result Worker结果处理器处理
- 点击Create按钮创建新项目
1 #!/usr/bin/env python 2 # -*- encoding: utf-8 -*- 3 # Created on 2019-07-10 15:17:59 4 # Project: baidu_spider 5 from pyspider.libs.base_handler import * 6 # BaseHandler是PySpider爬虫的基类 7 class Handler(BaseHandler): 8 """Handler是PySpider爬虫的主类""" 9 crawl_config = { 10 # 定义爬取配置,比如Headers、设置代理,配置之后全局有效 11 } 12 @every(minutes=24 * 60) # every属性设置爬取的时间间隔 13 def on_start(self): 14 """爬取入口,调用crawl方法新建一个爬取请求,第一个参数是爬取的URL,callback参数是指定这个页面爬取成功之后使用哪个方法解析""" 15 self.crawl('https://www.liaoxuefeng.com/', callback=self.index_page) 16 """http://travel.qunar.com/travelbook/list.htm""" 17 @config(age=10 * 24 * 60 * 60) 18 def index_page(self, response): 19 """接收response参数,该参数对接pyquery,可以直接使用doc进行解析""" 20 for each in response.doc('a[href^="http"]').items(): 21 self.crawl(each.attr.href, callback=self.detail_page) 22 @config(priority=2) 23 def detail_page(self, response): 24 """接收response参数,进行详情页的抓取""" 25 return { 26 "url": response.url, 27 "title": response.doc('title').text(), 28 }
- 点击run按钮,即可看见页面下方follow出现一个标注,其中包含数字1,代码有新的爬取请求产生
- 点击蓝色框围起来的箭头,在follows上会出现更多的爬取请求(爬取链接);其中web按钮可以查看页面,html按钮可以查看源代码
- 切换到Web页面,点击下方的enable css selector helper按钮,点击页面中的菜单,这时菜单外会多一个红框,上分出现CSS选择器,这就是当前菜单对应的CSS选择器,可以替换右侧代码中的CSS选择器(选择需要替换的CSS选择器),点击右上方的箭头实现替换
- 在源代码中没有img节点:这是因为pyspider是默认发生HTTP请求,请求的HTML文档本身就不包含img节点,所以必须修改fetch_type参数
self.crawl(url, callback=self.index_page, validate_cert=False, fetch_type='js')
- 在index_page方法选取爬取的详情页链接,通过编写detail_page需要爬取的信息
- 将爬虫的status设置为DEBUG或者RUNNING,点击Run按钮开始爬取
- 点击Active Tasks,即可查看最近请求的详细状况
- 点击Result,即可查看所有的爬取结果
- 项目状态
- TODO:他是项目刚刚被创建还未实现时的状态
- STOP:如果想停止某项目的爬取,可以将项目的状态设置为STOP
- CHECKING:正在运行的项目被修改之后会变成该状态,项目在中途出错需要调整的时候回遇见这种情况
- DEBUG/RUNNING:这两个状态对项目运行没有影响,设置为其中一个,项目都可以运行,但是可以用二者来区分项目是否已经通过测试
- PAUSE:在爬取过程中会出现连续多次错误,项目会自动设置为PAUSE状态,并等待一段时间继续爬取
- rate/burst:代表当前爬取的速率,rate代码1秒发出多少请求,burst相当于流量控制中的令牌桶算法的令牌数,rate和burst设置越大,爬取速率越快,需要考虑本机性能和爬取过快被封的问题
- progress:中的5m、1h、1d指定是最近5分钟、1小时、1天内的请求情况,all代表全部请求情况,其中蓝色代表等待被执行的请求,绿色代表成功的请求,黄色代表请求识别后等待重试的请求,红色代表失败次数过多而被忽略的请求
- 删除项目:pyspider没有直接删除项目的选项,如果需要删除项目,只能将项目的状态设置为STOP,将分组的名称设置为delete,等待24小时,则项目会自动删除
- 报错Exception: HTTP 599: SSL certificate problem: unable to get local issuer certificate
- 解决方法:这个错误会发生在请求 https 开头的网址,SSL 验证错误,证书有误,需要在crawl方法中使用validate_cert参数,基本可以解决
1 self.crawl(url, callback=self.index_page, validate_cert=False)
- 上述方法解决不了的情况下:第一步在Github上下载Pyspider源码,源码地址https://github.com/binux/pyspider;第二步下载之后的源码,找到其中的pyspider文件夹,替换本地的pyspider库安装文件夹,pip安装一般存放在" ..Libsite-packages"路径下;第三步重启Pyspider,添加validate_cert=False参数
- self.crawl函数分析
self.crawl(url, callback=self.index_page, age=10*24*60*60, priority=1, exectime=time.time()+30*60, itag=item.find('.time').text(), auto_recrawl=True) # url:要爬取的URL # callback:回调函数,指定该url对应的响应内容用哪个方法解析 # age:是任务的有效时间,如果某个任务在有效时间内已经被执行,则它不会重复执行,单位秒,或者直接在回调函数上设置修饰器@config(age=10*24*60*60) # priority:爬取任务优先级,默认为0,该参数值越大,对应的请求会越优先被调用 # exectime:可以设置定时任务,其值是时间戳,默认为0,即代表立即执行 # retries:定义重试次数,默认为3 # itag:设置判断页面是否发生变化的节点值,在爬取的时候回判定次当前节点是否和上次爬取的节点相同,如果节点相同,则证明页面没有更新 # auto_recrawl:设置为True;age为5小时,这样任务会每5小时执行一次 # method:HTTP请求方法,默认为GET # params:GET请求参数,字典类型 # data:post表单数据,字典类型 # file:上传的文件,需要指定文件名,{field: {filename: 'content'}} # user-agent:爬取使用的User-Agent # headers:爬取使用的Request Header # cookies:爬取时使用的Cookies,字典格式 # connect_timeout:初始化连接是的最长等待时间,默认20秒 # timeout:爬取网页时最长的等待时间,默认120秒 # allow_redirects:是否自动处理重定向,默认为True # validate_cert:是否验证证书,对HTTPS请求有用 # proxy:爬取时的代理,它支持username:password@hostname:port; # fetch_type:开启PhantomJS渲染,如果遇见JavaScript渲染的页面,指定该字段即实现PhantomJS的对接 self.crawl('http://www.example.org/', callback=self.callback, fetch_type='js', js_script='''function() { window.scrollTo(0,document.body.scrollHeight);return 123;} ''') # js_script:是页面加载完毕后执行的JavaScript脚本 # js_run_at:JavaScript脚本运行的位置,是在页面节点开头还是结尾,m默认结尾,即document-end # js_viewport_width/js_viewport_height:JavaScript渲染页面时的窗口大写 # load_images:加载JavaScript页面时确定是否加载图片,默认False def on_start(self): self.crawl('http://www.example.org/', callback=self.callback,save={'a': 123}) def callback(self, response): return response.save['a'] # save:用于在不同方法之间传递参数 # cancel:是取消任务,如果一个任务是ACTIVE状态的,需要将force_update=True # force_update:即使任务处于ACTIVE,那也会强制性更新状态
- 任务区分:在pyspider判断两个任务是否是重复的是使用该任务对于的URL的MD5值作为任务唯一的ID,如果ID相同,那么那个任务就会判相同,其中一个就不会爬取,但是很多情况下请求链接可能是同一个,但是POST的参数不同,这时就可以重写task_is()方法,改变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['fecth'].get('data','')))