手把手教你写网络爬虫(5)html
做者:拓海 (https://github.com/tuohai666)git
摘要:从零开始写爬虫,初学者的速成指南!github
封面:web
你们好!从今天开始,我要与你们一块儿打造一个属于咱们本身的分布式爬虫平台,同时也会对涉及到的技术进行详细介绍。你们若是有什么好的想法请多留言,多提意见,一块儿来完善咱们的爬虫平台。在正式介绍平台以前,先用一些篇幅对基础篇作一点补充。数据库
此次的目标是爬一个众筹网站的全部项目,项目列表页以下:https://www.kaistart.com/project/more.html。打开后进行分析,页面显示出10个项目:api
若是想看到更多项目,并不能像网易云音乐那样点“下一页”翻页,而是须要向下拉滚动条或者向下滚动鼠标滚轮来触发异步请求。爬虫该如何应对这种状况呢?咱们可使用selenium的api执行js代码将屏幕内容滚动到指定位置。浏览器
下面这段代码会一直向下滚动项目页,一直到滚不动为止:服务器
# 一直滚动到最底部 js1 = 'return document.body.scrollHeight' js2 = 'window.scrollTo(0, document.body.scrollHeight)' old_scroll_height = 0 while browser.execute_script(js1) >= old_scroll_height: old_scroll_height = browser.execute_script(js1) browser.execute_script(js2) time.sleep(1)
scrollTo() 方法可把内容滚动到指定的坐标:网络
参数架构 |
描述 |
xpos |
必需。要在窗口文档显示区左上角显示的文档的 x 坐标。 |
ypos |
必需。要在窗口文档显示区左上角显示的文档的 y 坐标。 |
这里用到了scrollHeight,它和ClientHeight还有OffsetHeight有什么区别呢?
offsetHeight: 包括内容可见部分的高度,border,可见的padding,水平方向的scrollbar(若是存在);不包括margin。
clientHeight: 包括内容可见部分的高度,可见的padding;不包括border,水平方向的scrollbar,margin。
scrollHeight: 包括内容的高度(可见与不可见),padding(可见与不可见);不包括border,margin。
代码写好了,接下来就用selenium+phantomJs大法实验一下!滚到底后把项目列表提取出来看一下:
browser = webdriver.PhantomJs() url = 'https://www.kaistart.com/project/more.html' try: browser.get(url) wait = ui.WebDriverWait(browser, 20) wait.until(lambda dr: dr.find_element_by_class_name('project-detail').is_displayed()) # 一直滚动到最底部 js1 = 'return document.body.scrollHeight' js2 = 'window.scrollTo(0, document.body.scrollHeight)' old_scroll_height = 0 while browser.execute_script(js1) >= old_scroll_height: old_scroll_height = browser.execute_script(js1) browser.execute_script(js2) time.sleep(1) sel = Selector(text=browser.page_source) proj_list = sel.xpath('//li[@class="project-li"]')
程序运行结束后,显示proje_list里面只有25个元素,而咱们本身手动滚的话却有100多个,明显有bug。想定位这个问题很简单,截图便可,看看为何停在第25个项目。对,phantomJs虽然没有图形界面,可是能够截图。
browser.save_screenshot(debug.png')
这样就会把图片保存在项目目录,打开看看:
发现项目页只能显示一行,这说明网页不兼容phantomJs,这倒不是什么新鲜事,换一个浏览器试试呗。第一期介绍过,selenium是支持全部主流浏览器的。好比换成Chrome,只需改一行代码:
browser = webdriver.Chrome()
再次运行程序,不出所料,Chrome浏览器弹出来,不只可以正确显示页面,还一直在滚动:
项目全都刷出来了,想爬什么就爬吧!什么?你问我在Linux服务器上怎么爬?纯命令行的那种吗?
PhantomJs是无界面浏览器,能够在Linux服务器上正常运行,但Chrome会在调用GUI接口时报错。既然Linux服务器没有图形接口服务,也就是X Server,咱们就要虚拟出来一个,才能让Chrome正常运行。因而找到了Xvfb(X virtual frame buffer),它能够用来做为完整X服务程序的替代。Xvfb有一个Python的封装叫PyVirtualDisplay,咱们就用它来解决这个问题。
安装:
pip install pyvirtualdisplay
用法:
from selenium import webdriver from pyvirtualdisplay import Display display = Display(visible=0, size=(800, 600)) display.start() driver = webdriver.Chrome() driver.get("http://www.baidu.com") print (driver.page_source.encode('utf-8')) driver.quit() display.stop()
运行程序后打印出了baidu的页面内容,如今能够完美运行Chrome了。须要补充的是,在Linux上运行Chrome须要额外安装一个ChromeDriver,比较简单,就不详细介绍了。
既然咱们要打造本身的分布式爬虫平台,就要先知道什么是分布式系统,百度百科是这样定义的:
分布式系统(distributed system)是创建在网络之上的软件系统。正是由于软件的特性,因此分布式系统具备高度的内聚性和透明性。所以,网络和分布式系统之间的区别更多的在于高层软件(特别是操做系统),而不是硬件。内聚性是指每个数据库分布节点高度自治,有本地的数据库管理系统。透明性是指每个数据库分布节点对用户的应用来讲都是透明的,看不出是本地仍是远程。在分布式数据库系统中,用户感受不到数据是分布的,即用户不须知道关系是否分割、有无副本、数据存于哪一个站点以及事务在哪一个站点上执行等。
这个定义不太好理解,看看书上怎么说。《分布式系统概念与设计》一书中对分布式系统作了以下定义:
分布式系统是一个硬件或软件组件分布在不一样的网络计算机上,彼此之间仅仅经过消息传递进行通讯和协调的系统。
《分布式系统原理和范型》一书中是这样定义分布式系统的:
分布式系统是若干独立计算机的集合,这些计算机对于用户来讲就像是单个相关系统。
简单来讲就是一群独立计算机集合共同对外提供服务,可是对于系统的用户来讲,就像是一台计算机在提供服务同样。分布式意味着能够采用更多的普通计算机(相对于昂贵的大型机)组成分布式集群对外提供服务。计算机越多,CPU、内存、存储资源等也就越多,可以处理的并发访问量也就越大。
从分布式系统的概念中咱们知道,各个主机之间通讯和协调主要经过网络进行,因此,分布式系统中的计算机在空间上几乎没有任何限制,这些计算机可能被放在不一样的机柜上,也可能被部署在不一样的机房中,还可能在不一样的城市中,对于大型的网站甚至可能分布在不一样的国家。可是,不管空间上如何分布,一个标准的分布式系统应该具备如下几个主要特征:
透明性
系统资源被全部计算机共享。每台计算机的用户不只可使用本机的资源,还可使用本分布式系统中其余计算机的资源。
同一性
系统中的若干台计算机能够互相协做来完成一个共同的任务,或者说一个程序能够分布在几台计算机上并行地运行。
通讯性
系统中的计算机均可以经过通讯来交换信息。
今天先了解下基本概念,热热身。整个系统的架构及流程留到下次一块儿奉上。下期再见!