Python网络爬虫从入门到实践(第2版)(txt+pdf+epub+mobi电子书下载)


发布时间:2020-08-20 15:00:06

点击下载

作者:唐松

出版社:机械工业出版社

格式: AZW3, DOCX, EPUB, MOBI, PDF, TXT

Python网络爬虫从入门到实践(第2版)

Python网络爬虫从入门到实践(第2版)试读:

前言

近年来,大数据成为业界与学术界的热门话题之一,数据已经成为每个公司极为重要的资产。互联网上大量的公开数据为个人和公司提供了以往想象不到的可以获取的数据量,而掌握网络爬虫技术可以帮助你获取这些有用的公开数据集。

执笔本书的起因是我打算在知乎上写博客向香港中文大学市场营销学的研究生讲解Python网络爬虫技术,让这些商科学生掌握一些大数据时代重要的技术。因此,本书除了面向技术人员外,还面向不懂编程的“小白”,希望能够将网络爬虫学习的门槛降低,让大家都能享受到使用网络爬虫编程的乐趣。过去的一年中,本书第1版帮助很多读者开启了Python和网络爬虫的世界,因此有幸获得出版社的邀请,在之前版本的基础上进行修改,更新书中的案例以及添加新的内容,形成第2版。

本书所有代码均在Python 3.6中测试通过,并存放在Github和百度网盘上:Github链接为https://github.com/Santostang/PythonScraping;百度网盘链接为https://pan.baidu.com/s/14RA8Srew8tbqVT977JDvNw,提取码为h2kf。为了方便大家练习Python网络爬虫,我专门搭建了一个博客网站用于Python网络爬虫的教学,本书的教学部分全部基于爬取我的个人博客网(www.santostang.com)。一方面,由于这个网站不会更改设计和框架,因此本书的网络爬虫代码可以一直使用;另一方面,由于这是我自己的博客网站,因此可以避免一些法律上的风险。

读者对象

(1)对Python编程和网络爬虫感兴趣的大专院校师生,需要获取数据进行分析;(2)打算转行或入行爬虫工程师、数据分析师、数据科学家的人士;(3)需要使用网络爬虫技术自动获取数据分析的各行业人士。

勘误和支持

由于作者水平和能力有限,编写时间仓促,不妥之处在所难免,希望读者批评指正。本书的读者QQ群为798652826,欢迎读者加群交流。另外,也可以到我的博客www.santostang.com反馈意见,欢迎读者和网络爬虫爱好者不吝赐教。

如何阅读本书

本书分为17章。

第1~7章为基础部分,主要介绍Python入门,Python网络爬虫的获取网页、解析网页和存储数据三个流程,以及Scrapy爬虫框架。这部分每一章的最后都有自我实践题,读者可以通过实践题熟悉Python爬虫代码的编写。

第8~13章为进阶部分,主要介绍多线程和多进程爬虫、反爬虫、服务器爬虫和分布式爬虫等进阶爬虫技术,这部分为你在爬虫实践中遇到的问题提供了解决方案。

第14~17章为项目实践部分,每一章包含一个详细的爬虫案例,每个案例都覆盖之前章节的知识,让你在学习Python爬虫后,可以通过在真实网站中练习来消化和吸收Python爬虫的知识。

本书几乎每章都使用案例来学习Python网络爬虫,希望告诉读者“通过实战解决实际问题,才能高效地学习新知识”。手输代码,练习案例,才是学习Python和网络爬虫的有效方法。

致谢

首先感谢卞诚君老师在我写书过程中给予的指导和帮助。没有他的提议,我不会想到将自己的网络爬虫博客整理成一本书出版,更不会有本书的第2版。

从转行数据分析,到申请去康奈尔大学读书,再到回国做数据分析师,我在计算机技术和数据科学的道路上,得到了无数贵人的帮助和提携。首先感谢刘建南教授带我进入了数据挖掘的大门,无私地将数据挖掘、营销知识和经验倾囊相授,您是我的启蒙老师,也是我一生的恩师。

感谢腾讯公司商业分析组和数据服务中心的各位同事,特别感谢我的组长张殿鹏和导师王欢,他们耐心地培养和教导我如何成为一名优秀的数据分析师,让我放手去挑战和尝试不同项目,坚持将数据分析的成果落地。

感谢一路走来,支持我、帮助我的前辈和朋友,包括香港中文大学的教授和朋友——马旭飞教授、李宜威博士、数据科学家周启航、数据分析师赵作栋、数据分析师王礼斌以及好友孙成帅、张蓓等,康奈尔大学的同学——数据科学家汤心韵等、思路富邦有限公司总裁陈智铨、数据科学家吴嘉杰。尤其感谢IBM香港CTO戴剑寒博士、香港中文大学(深圳)校长讲席教授贾建民博士、TalkingData腾云大学执行校长杨慧博士和DaoCloud首席架构师王天青在百忙中热情地为本书写推荐语。

感谢我的父母、妹妹和女朋友给我一贯的支持和帮助!唐松中国深圳第1章 网络爬虫入门

网络爬虫就是自动地从互联网上获取程序。想必你听说过这个词汇,但是又不太了解,会觉得掌握网络爬虫还是要花一些工夫的,因此这个门槛让你有点望而却步。

我常常觉得计算机和互联网的发明给人类带来了如此大的方便,让人们不用阅读说明书就能知道如何上手,但是偏偏编程的道路又是如此艰辛。因此,本书尽可能地做到浅显易懂,希望能够将网络爬虫学习的门槛降低,大家都能享受到使用网络爬虫编程的快乐。

本书的第1章将介绍网络爬虫的基础部分,包括学习网络爬虫的原因、网络爬虫带来的价值、网络爬虫是否合法以及网络爬虫的基本议题和框架。让读者在开始学习爬虫之前理解为什么学习、要学什么内容。1.1 为什么要学网络爬虫

在数据量爆发式增长的互联网时代,网站与用户的沟通本质上是数据的交换:搜索引擎从数据库中提取搜索结果,将其展现在用户面前;电商将产品的描述、价格展现在网站上,以供买家选择心仪的产品;社交媒体在用户生态圈的自我交互下产生大量文本、图片和视频数据等。这些数据如果得以分析利用,不仅能够帮助第一方企业(拥有这些数据的企业)做出更好的决策,对于第三方企业也是有益的。而网络爬虫技术,则是大数据分析领域的第一个环节。1.1.1 网络爬虫能带来什么好处

大量企业和个人开始使用网络爬虫采集互联网的公开数据。那么对于企业而言,互联网上的公开数据能够带来什么好处呢?这里将用国内某家知名家电品牌举例说明。

作为一个家电品牌,电商市场的重要性日益凸显。该品牌需要及时了解对手的产品特点、价格以及销量情况,才能及时跟进产品开发进度和营销策略,从而知己知彼,赢得竞争。过去,为了获取对手产品的特点,产品研发部门会手动访问一个个电商产品页面,人工复制并粘贴到Excel表格中,制作竞品分析报告。但是这种重复性的手动工作不仅浪费宝贵的时间,一不留神复制少了一个数字还会导致数据错误;此外,竞争对手的销量则是由某一家咨询公司提供报告,每周一次,但是报告缺乏实时性,难以针对快速多变的市场及时调整价格和营销策略。针对上述两个痛点——无法自动化和无法实时获取,本书介绍的网络爬虫技术都能够很好地解决,实现实时自动化获取数据。

上面的例子仅为数据应用的冰山一角。近几年来,随着大数据分析的火热,毕竟有数据才能进行分析,网络爬虫技术已经成为大数据分析领域的第一个环节。

对于这些公开数据的应用价值,我们可以使用KYC框架来理解,也就是Know Your Company(了解你的公司)、Know Your Competitor(了解你的竞争对手)、Know Your Customer(了解你的客户)。通过简单描述性分析,这些公开数据就可以带来很大的商业价值。进一步讲,通过深入的机器学习和数据挖掘,在营销领域可以帮助企业做好4P(Product:产品创新,Place:智能选址,Price:动态价格,Promotion:个性化营销活动);在金融领域,大数据征信、智能选股等应用会让公开数据带来越来越大的价值。1.1.2 能从网络上爬取什么数据

简单来说,平时在浏览网站时,所有能见到的数据都可以通过爬虫程序保存下来。从社交媒体的每一条发帖到团购网站的价格及点评,再到招聘网站的招聘信息,这些数据都可以存储下来。1.1.3 应不应该学爬虫

正在准备继续阅读本书的读者可能会问自己:我应不应该学爬虫?

这也是我之前问自己的一个问题,作为一个本科是商学院的学生,面对着技术创新驱动变革的潮流,我还是自学了Python的网络爬虫技术,从此踏入了编程的世界。对于编程小白而言,入门网络爬虫并没有想象中那么困难,困难的是你有没有踏出第一步。

我认为,对于任何一个与互联网有关的从业人员,无论是非技术的产品、运营或营销人员,还是前端、后端的程序员,都应该学习网络爬虫技术。

一方面,网络爬虫简单易学、门槛很低。没有任何编程基础的人在认真看完本书的爬虫基础内容后,都能够自己完成简单的网络爬虫任务,从网站上自动获取需要的数据。

另一方面,网络爬虫不仅能使你学会一项新的技术,还能让你在工作的时候节省大量的时间。如果你对网络爬虫的世界有兴趣,就算你不懂编程也不要担心,本书将会深入浅出地为你讲解网络爬虫。1.2 网络爬虫是否合法

网络爬虫合法吗?

网络爬虫领域目前还属于早期的拓荒阶段,虽然互联网世界已经通过自身的协议建立起一定的道德规范(Robots协议),但法律部分还在建立和完善中。从目前的情况来看,如果抓取的数据属于个人使用或科研范畴,基本不存在问题;而如果数据属于商业盈利范畴,就要就事而论,有可能属于违法行为,也有可能不违法。1.2.1 Robots协议

Robots协议(爬虫协议)的全称是“网络爬虫排除标准”(Robots Exclusion Protocol),网站通过Robots协议告诉搜索引擎哪些页面可以抓取,哪些页面不能抓取。该协议是国际互联网界通行的道德规范,虽然没有写入法律,但是每一个爬虫都应该遵守这项协议。

下面以淘宝网的robots.txt为例进行介绍。

这里仅截取部分代码,查看完整代码可以访问https://www.taobao.com/robots.txt。User-agent: Baiduspider #百度爬虫引擎Allow: /article #允许访问/article.htm、/article/12345.comAllow: /oshtml Allow: /ershouDisallow: /product/ #禁止访问/product/12345.comDisallow: / #禁止访问除Allow规定页面外的其他所有页面User-Agent: Googlebot #谷歌爬虫引擎Allow: /articleAllow: /oshtmlAllow: /product #允许访问/product.htm、/product/12345.comAllow: /spuAllow: /dianpuAllow: /wenzhangAllow: /overseaDisallow: /

在上面的robots文件中,淘宝网对用户代理为百度爬虫引擎进行了规定。

以Allow项的值开头的URL是允许robot访问的。例如,Allow:/article允许百度爬虫引擎访问/article.htm、/article/12345.com等。

以Disallow项为开头的链接是不允许百度爬虫引擎访问的。例如,Disallow:/product/不允许百度爬虫引擎访问/product/12345.com等。

最后一行,Disallow:/禁止百度爬虫访问除了Allow规定页面外的其他所有页面。

因此,当你在百度搜索“淘宝”的时候,搜索结果下方的小字会出现:“由于该网站的robots.txt文件存在限制指令(限制搜索引擎抓取),系统无法提供该页面的内容描述”,如图1-1所示。百度作为一个搜索引擎,良好地遵守了淘宝网的robot.txt协议,所以你是不能从百度上搜索到淘宝内部的产品信息的。图1-1 百度搜索提示

淘宝的Robots协议对谷歌爬虫的待遇则不一样,和百度爬虫不同的是,它允许谷歌爬虫爬取产品的页面Allow:/product。因此,当你在谷歌搜索“淘宝iphone7”的时候,可以搜索到淘宝中的产品,如图1-2所示。图1-2 谷歌搜索的信息

当你爬取网站数据时,无论是否仅供个人使用,都应该遵守Robots协议。1.2.2 网络爬虫的约束

除了上述Robots协议之外,我们使用网络爬虫的时候还要对自己进行约束:过于快速或者频密的网络爬虫都会对服务器产生巨大的压力,网站可能封锁你的IP,甚至采取进一步的法律行动。因此,你需要约束自己的网络爬虫行为,将请求的速度限定在一个合理的范围之内。

提示 本书中的爬虫仅用于学习、研究用途,请不要用于非法用途。任何由此引发的法律纠纷,请自行负责。

实际上,由于网络爬虫获取的数据带来了巨大的价值,网络爬虫逐渐演变成一场网站方与爬虫方的战争,你的矛长一寸,我的盾便厚一寸。在携程技术微分享上,携程酒店研发部研发经理崔广宇分享过一个“三月爬虫”的故事,也就是每年的三月份会迎来一个爬虫高峰期。因为有大量的大学生五月份交论文,在写论文的时候会选择爬取数据,也就是三月份爬取数据,四月份分析数据,五月份交论文。

因此,各大互联网巨头也已经开始调集资源来限制爬虫,保护用户的流量和减少有价值数据的流失。

2007年,爱帮网利用垂直搜索技术获取了大众点评网上的商户简介和消费者点评,并且直接大量使用。大众点评网多次要求爱帮网停止使用这些内容,而爱帮网以自己是使用垂直搜索获得的数据为由,拒绝停止抓取大众点评网上的内容,并且质疑大众点评网对这些内容所享有的著作权。为此,双方开打了两场官司。2011年1月,北京海淀法院做出判决:爱帮网侵犯大众点评网著作权成立,应当停止侵权并赔偿大众点评网经济损失和诉讼必要支出。

2013年10月,百度诉360违反Robots协议。百度方面认为,360违反了Robots协议,擅自抓取、复制百度网站内容并生成快照向用户提供。2014年8月7日,北京市第一中级人民法院做出一审判决,法院认为被告奇虎360的行为违反了《反不正当竞争法》相关规定,应赔偿原告百度公司70万元。

虽然说大众点评上的点评数据、百度知道的问答由用户创建而非企业,但是搭建平台需要投入运营、技术和人力成本,所以平台拥有对数据的所有权、使用权和分发权。

以上两起败诉告诉我们,在爬取网站的时候需要限制自己的爬虫,遵守Robots协议和约束网络爬虫程序的速度;在使用数据的时候必须遵守网站的知识产权。如果违反了这些规定,很可能会吃官司,并且败诉的概率相当高。1.3 网络爬虫的基本议题

对于网络爬虫技术的学习,其他教学很少有从整体结构来说的,多数是直接放出某部分代码。这样的方法会使初学者摸不着头脑:就好像是盲人摸象,有人摸到的是象腿,以为是一根大柱子;有人摸到的是大象耳朵,以为是一把大蒲扇等。因此,在开始第一个爬虫之前,本书先从宏观角度出发说清楚两个问题:

·Python爬虫的流程是怎样的?

·三个流程的技术实现是什么?

值得说明的是,本书选择了Python 3作为开发语言,现在Python最新版为Python 3.7。熟悉Python 2的读者可以在本书代码的基础上稍加改动,用Python 2运行。值得注意的是,Python 2即将在2020年1月1日停止支持,因此建议初学者直接安装Python 3进行学习。

由于本书的潜在读者多数使用Windows操作系统,因此本书大部分实例都是基于Windows编写和运行的。如果使用的是Linux和Mac OS操作系统,在搭建好Python平台之后也可以直接运行本书中的代码。1.3.1 Python爬虫的流程

网络爬虫的流程其实非常简单,主要可以分为三部分:(1)获取网页;(2)解析网页(提取数据);(3)存储数据。(1)获取网页就是给一个网址发送请求,该网址会返回整个网页的数据。类似于在浏览器中键入网址并按回车键,然后可以看到网站的整个页面。(2)解析网页就是从整个网页的数据中提取想要的数据。类似于你在页面中想找到产品的价格,价格就是你要提取的数据。(3)存储数据也很容易理解,就是把数据存储下来。我们可以存储在csv中,也可以存储在数据库中。1.3.2 三个流程的技术实现

下面列出三个流程的技术实现,括号里是对应的章节。1.获取网页

获取网页的基础技术:requests、urllib和selenium(3&4)。

获取网页的进阶技术:多进程多线程抓取(8)、登录抓取(12)、突破IP封禁(9)和使用服务器抓取(12)。2.解析网页

解析网页的基础技术:re正则表达式、BeautifulSoup和lxml(5)。

解析网页的进阶技术:解决中文乱码(10)。3.存储数据

存储数据的基础技术:存入txt文件和存入csv文件(6)。

存储数据的进阶技术:存入MySQL数据库和MongoDB数据库(6)。

除此之外,第7章介绍Scrapy爬虫框架,第13章也会介绍分布式爬虫。

本书的使用方法:第1章到第7章是网络爬虫的基础,建议大家按顺序读;第8章到第13章是进阶部分,大家可以选择自己感兴趣的内容跳跃阅读。之后可以阅读第14章到第17章,通过项目实践消化和吸收Python爬虫的知识。

如果对于上述技术不熟悉的读者也不必担心,本书将会对其中的技术进行讲解,力求做到深入浅出。第2章 编写第一个网络爬虫

笔者是一个喜欢学习的人,自学了各方面的知识,总结发现:学习的动力来自于兴趣,兴趣则来自于动手做出成果的快乐。因此,笔者特意将动手的乐趣提前。在第2章,读者就可以体会到通过完成一个简单的Python网络爬虫而带来的乐趣。希望这份喜悦能让你继续学习本书的其他内容。

本章主要介绍如何安装Python和编辑器Jupyter、Python的一些基础语法以及编写一个最简单的Python网络爬虫。2.1 搭建Python平台

Python是一种计算机程序语言,由于其简洁性、易学性和可扩展性,已成为最受欢迎的程序语言之一。在2016年最受欢迎的编程语言中,Python已经超过C++排名第3位。另外,由于Python拥有强大而丰富的库,因此可以用来处理各种工作。

在网络爬虫领域,由于Python简单易学,又有丰富的库可以很好地完成工作,因此很多人选择Python进行网络爬虫。2.1.1 Python的安装

Python的安装主要有两种方式:一是直接下载Python安装包安装,二是使用Anaconda科学计算环境下载Python。

根据笔者的经验,这两种方式也对应着用Python来爬虫的两类人群:如果你希望成为Python开发人员或者爬虫工程师,笔者推荐你直接下载Python安装包,配合着Pycharm编辑器,这将提升你的开发效率;如果你希望成为数据分析师或者商业分析师,爬虫只是方便之后做数据分析,笔者推荐你使用Anaconda,配合着自带的Jupyter Notebook,这会提升你的分析效率。

由于网络爬虫需要较多的代码调试,因此我推荐初学者使用Anaconda。因为Anaconda除了包含了Python安装包,还提供了众多科学计算的第三方库,如Numpy、Scipy、Pandas和Matplotlib等,以及机器学习库,如Scikit-Learn等。而且它并不妨碍你之后使用Pycharm开发。

请读者选择一种下载,不要两种都用,不然会带来Python版本管理的混乱。

第一种方法:Anaconda的安装十分简单,只需两步即可完成。下面将介绍在Windows下安装Anaconda的步骤,在Mac下的安装方法与此类似。

步骤01 下载Anaconda。打开Anaconda官方网站下载页面https://www.anaconda.com/download/,下载最新版的Anaconda。如果在国内访问,推荐使用清华大学的镜像https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/。如图2-1所示。图2-1 选择下载的Python版本

步骤02 安装Anaconda。双击打开Anaconda安装文件,就像安装普通软件一样,直接单击Install安装即可。注意,在图2-2所示的对话框中勾选第一个和第二个复选框。按照提示操作后,安装即可。图2-2 安装Anaconda

第二种方法:使用Python安装包方法也非常简单。下面将介绍在Windows下安装的步骤,在Mac下的安装方法类似。

步骤01 下载Python。打开Python下载页面https://www.python.org/downloads/,下载最新版的Python,如图2-3所示。图2-3 点击下载Python

步骤02 安装Python。双击打开Python安装文件,选择Add Python 3.7 to PATH,之后单击InstallNow安装即可。图2-4 安装Python2.1.2 使用pip安装第三方库

pip是Python安装各种第三方库(package)的工具。

对于第三方库不太理解的读者,可以将库理解为供用户调用的代码组合。在安装某个库之后,可以直接调用其中的功能,使得我们不用自己写代码也能实现某个功能。这就像你为计算机杀毒时,会选择下载一个杀毒软件,而不是自己写一个杀毒软件,直接使用杀毒软件中的杀毒功能来杀毒就可以了。这个比方中的杀毒软件就像是第三方库,杀毒功能就是第三方库中可以实现的功能,你可以调用第三方库实现某个功能。

由于Anaconda或者Python安装包自带了pip,因此不用再安装pip。

在下面的例子中,我们将介绍如何用pip安装第三方库bs4,它可以使用其中的BeautifulSoup解析网页。

步骤01 打开cmd.exe,在Windows中为cmd,在Mac中为terminal。在Windows中,cmd是命令提示符,输入一些命令后,cmd.exe可以执行对系统的管理。单击“开始”按钮,在“搜索程序和文件”文本框中输入cmd后按回车键,系统会打开命令提示符窗口,如图2-5所示。在Mac中,可以直接在“应用程序”中打开terminal程序。图2-5 搜索cmd

步骤02 安装bs4的Python库。在cmd中键入pip install bs4后按回车键,如果出现successfully installed,就表示安装成功,如图2-6所示。图2-6 安装bs4库

除了bs4这个库,之后还会用到requests库、lxml库等其他第三方库,帮助我们更好地进行网络爬虫。正因为这些第三方库的存在,才使得Python在爬虫领域越来越方便、越来越活跃。2.1.3 使用编辑器Jupyter编程

如果你使用Anaconda安装的Python,那么可以使用Anaconda自带的Jupyter Notebook编程;如果你使用Python安装包下载的Python,下一节会介绍Pycharm的安装方法。为了方便大家学习和调试代码,本书推荐使用Anaconda自带的Jupyter Notebook。下面将介绍Jupyter Notebook的使用方法。

步骤01 通过cmd打开Jupyter。打开cmd,键入jupyter notebook后按回车键,浏览器启动Jupyter界面,地址默认为http://localhost:8888/tree,如图2-7所示。图2-7 启动Jupyter的主界面

步骤02 创建Python文件。这时浏览器会开启一个页面,在页面中选择想创建文件的文件夹,单击右上角的New按钮,从下拉列表中选择Python 3作为希望启动的Notebook类型,如图2-8所示。图2-8 选择Python 3

步骤03 在新创建的文件中编写Python程序。键入print('hello world!')后,可以按Shift+Enter快捷键执行刚刚的代码,结果如图2-9所示。图2-9 编写Python程序

为什么本书使用Jupyter Notebook学习和编写Python脚本呢?

首先,Jupyter Notebook的交互式编程可以分段运行Python,对于网络爬虫这种分阶段(获取网页-解析网页-存储数据)运行的脚本来说,在写代码和测试阶段可以边看边写,可以加快调试代码的速度,非常适合debug(代码纠错)。

其次是展示,Jupyter Notebook能够把运行和输出的结果保存下来,下次打开这个Notebook时也可以看到之前运行的结果。除了可以编写代码外,Jupyter还可以添加各种元素,比如图片、视频、链接等,同时还支持Markdown。

在完成代码之后,还可以在Jupyter左上角点击File>Download as>Python,下载为.py文件,就可以放到其他编辑器里运行了。

如果你对Python的其他自定义功能有要求的话,推荐下载Jupyter的插件nbextensions。具体指引可以到笔者知乎或本书官网www.santostang.com了解。2.1.4 使用编辑器Pycharm编程

如果你使用Python安装包下载的Python,推荐选择Pycharm编辑器。

步骤01 下载Pycharm。打开Pycharm下载页面https://www.jetbrains.com/pycharm/download,下载Community版本,如图2-10所示。图2-10 点击下载Pycharm

步骤02 安装Pycharm。双击打开Pycharm安装文件,根据自己电脑选择32bit还是64bit,记得在Create Associations勾选.py,安装即可,如图2-11所示。图2-11 安装Pycharm

步骤03 打开Pycharm。在开始页面,选择自己喜欢的主题,如图2-12所示。图2-12 选择Pycharm主题

步骤03 随后点击Create New Project创建一个新的项目,如图2-13所示。图2-13 创建一个Pycharm项目

步骤03 选择好存储项目的位置,这里我给项目起的名称是“WebScraping”,你可以按照自己的需求存放项目地址,如图2-14所示。图2-14 存储Pycharm项目

步骤03 进入Pycharm页面后,会看到如下页面。这时,点击File>New>Python File,并填上python文件名,例如“test”。创建完test.py文件后,打开test.py,键入print('hello world!')。选中代码,右键选择Run‘test’,即可得到结果,如图2-15所示。图2-15 运行Python文件2.2 Python使用入门

本节主要介绍Python的一些基础语法。如果你已经学会使用Python,可以跳过这一节,直接开始编写第一个Python网络爬虫。2.2.1 基本命令

Python是一种非常简单的语言,最简单的就是print,使用print可以打印出一系列结果。例如,键入print("Hello World!"),打印的结果如下(同图2-9):In [1]:print ("Hello World!")

Hello World!

另外,Python要求严格的代码缩进,以Tab键或者4个空格进行缩进,代码要按照结构严格缩进,例如:In [2]:x = 1 if x == 1: print ("Hello World!")

Hello World!

如果需要注释某行代码,那么可以在代码前面加上“#”,例如:In [3]:# 在前面加上#,代表注释 print ("Hello World!")

Hello World!2.2.2 数据类型

Python是面向对象(object oriented)的一种语言,并不需要在使用之前声明需要使用的变量和类别。下面将介绍Python的4种数据类型。1.字符串(string)

字符串是常见的数据类型,一般用来存储类似“句子”的数据,并放在单引号(')或双引号(")中。如果要连接字符串,那么可以简单地加起来。In [4]:string1 = 'Python Web Scraping' string2 = "by Santos" string3 = string1 + " " + string2 print (string3)

Python Web Scraping by Santos

如果字符串包含单引号(')和双引号("),应该怎么办?可以在前面加上右斜杠(\),例如以下案例:In [5]:string = "I\'m Santos. I love \"python\"." print (string3)

I'm Santos.I love"python".2.数字(Number)

数字用来存储数值,包含两种常用的数字类型:整数(int)和浮点数(float),其中浮点数由整数和小数部分组成。两种类型之间可以相互转换,如果要将整数转换为浮点数,就在变量前加上float;如果要将浮点数转换为整数,就在变量前加上int,例如:In [6]:int1 = 7 float1 = 7.5 trans_int = int(float1) print (trans_int)

7

还有其他两种复杂的数据类型,即长整数和复数,由于不常用到,感兴趣的读者可以自己学习。3.列表(list)

如果需要把上述字符串和数字囊括起来,就可以使用列表。列表能够包含任意种类的数据类型和任意数量。创建列表非常容易,只要把不同的变量放入方括号中,并用逗号分隔即可,例如:In [7]:list1 = ['Python', 'Web', 'Scrappy'] list2 = [1, 2, 3, 4, 5] list3 = ["a", 2, "c", 4]

怎么访问列表中的值呢?可以在方括号中标明相应的位置索引进行访问,与一般认知不一样的是,索引从0开始,例如:In [8]:print ("list1[0]: " , list1[0]) print ("list2[1:3]: " , list2[1:3])

list1[0]:Python

list2[1:3]:[2,3]

如何修改列表中的值呢?可以直接为列表中的相应位置赋予一个新值,例如:In [9]:list1[1] = "new" print (list1)

['Python','new','Scrappy']

如果想要给列表添加值呢?可以用append()方法,例如:In [10]:list1.append("by Santos") print (list1)

['Python','new','Scrappy','by Santos']4.字典(Dictionaries)

字典是一种可变容器模型,正如其名,字典含有“字”(直译为键值,key)和值(value),使用字典就像是自己创建一个字典和查字典的过程。每个存储的值都对应着一个键值key,key必须唯一,但是值不需要唯一。值也可以取任何数据类型,例如:In [11]:namebook = {"Name": "Alex", "Age": 7, "Class": "First"} print (namebook["Name"]) #可以把相应的键值放入方括号,提取值 print (namebook) #也可以直接输出整个字典

Alex

{'Name':'Alex','Age':7,'Class':'First'}

如何遍历访问字典中的每一个值呢?这里需要用到字典和循环的结合,例如:In [12]:#循环提取整个dictionary的key和value for key, value in namebook.items(): print (key, value)

Name Alex

Age 7

Class First

如果想修改字典中的值或者加入新的键值呢?可以直接修改和加入,例如:In [13]: # 直接修改值和添加一个键值 namebook["Name"] = "Tom" namebook ["Gender"] = "M" print (namebook)

{'Name':'Tom','Age':7,'Class':'First','Gender':'M'}2.2.3 条件语句和循环语句

条件语句可以使得当满足条件的时候才执行某部分代码。条件为布尔值,也就是只有True和False两个值。当if判断条件成立时才执行后面的语句;当条件不成立的时候,执行else后面的语句,例如:In [14]:book = "python" #定义字符串book if book == "python": #判断变量是否为'python' print ("You are studying python.") #条件成立时输出 else: print ("Wrong.") #条件不成立时输出

You are studying python.

如果需要判断的有多种条件,就需要用到elif,例如:In [15]:book = "java" #定义字符串book if book == "python": #判断变量是否为'python' print ("You are studying python.") #条件成立时输出 elif book == "java": #判断变量是否为'java ' print ("You are studying java.") #条件成立时输出 else: print ("Wrong.") #条件不成立时输出

You are studying java.

Python的条件语句注意不要少了冒号(:)。

循环语句能让我们执行一个代码片段多次,循环分为for循环和while循环。

for循环能在一个给定的顺序下重复执行,例如:In [16]:citylist = ["Beijing", "Shanghai", "Guangzhou"] for eachcity in citylist: print (eachcity)

Beijing

Shanghai

Guangzhou

除了对列表进行直接循环,有时我们还会使用range()进行循环,首先用len(citylist)得到列表的长度为3,然后range(3)会输出列表[0,1,2],从而实现循环,得到和上面一样的结果。例如:In [17]:citylist = ["Beijing", "Shanghai", "Guangzhou"] for i in range(len(citylist)): print (citylist[i])

Beijing

Shanghai

Guangzhou

while循环能不断重复执行,只要能满足一定条件,例如:In [18]:count = 0 while count < 3: print (count) #打印出 0,1,2 count += 1 #与 count = count + 1 一样

0

1

22.2.4 函数

在代码很少的时候,我们按照逻辑写完就能够很好地运行。但是如果代码变得庞大复杂起来,就需要自己定义一些函数(Functions),把代码切分成一个个方块,使得代码易读,可以重复使用,并且容易调整顺序。

其实Python就自带了很多函数,例如下面的sum()和abs()函数,我们可以直接调用。In [19]: print (sum([1,2,3,4])) #对系列进行求和计算 print (abs(-1)) # 返回数字的绝对值

10

1

此外,我们也可以自己定义函数。一个函数包括输入参数和输出参数,Python的函数功能可以用y=x+1的数学函数来理解,在输入x=2的参数时,y输出3。但是在实际情况中,某些函数输入和输出参数可以不用指明。下面定义一个函数:In [20]:#定义函数 def calulus (x): y = x + 1 return y #调用函数 result = calulus(2) print (result)

3

参数必须要正确地写入函数中,函数的参数也可以为多个,也可以是不同的数据类型,例如可以是两个参数,分别是字符串和列表型的。In [21]:#定义函数 def fruit_function (fruit1, fruit2): fruits = fruit1 + " " + fruit2[0] + " " + fruit2[1] return fruits #调用函数 result = fruit_function("apple", ["banana", "orange"]) print (result)

apple banana orange2.2.5 面向对象编程

在介绍面向对象编程之前先说明面向过程编程。面向过程编程的意思是根据业务逻辑从上到下写代码,这个容易被初学者接受,按照逻辑需要用到哪段代码写下来即可。

随着时间的推移,在编程的方式上又发展出了函数式编程,把某些功能封装到函数中,需要用时可以直接调用,不用重复撰写。这也是上面提到的函数式编程,函数式的编程方法好处是节省了大量时间。

接下来,又出现了面向对象编程。面向对象编程是把函数进行分类和封装后放入对象中,使得开发更快、更强。例如:In [22]:class Person: # 创建类 #__init__ ()方法称为类的构造方法,注意是左右各是两个下划线 def __init__ (self, name, age): self.name = name self.age = age def detail(self): #通过self调用被封装的内容 print (self.name) print (self.age) obj1 = Person('santos', 18) obj1.detail() # Python将obj1传给self参数,即: # obj1.detail(obj1),此时内部self=obj1

santos

18

看到这里,也许你有疑问,要实现上述代码的结果,使用函数式编程不是比面向对象编程更简单吗?例如,如果我们使用函数式编程,可以写成:In [23]:def detail(name,age): print (name) print (age) obj1 = detail('santos', 18)

santos

18

此处确实是函数式编程更容易。使用函数式编程,我们只需要写清楚输入和输出变量并执行函数即可;而使用面向对象的编程方法,首先要创建封装对象,然后还要通过对象调用被封装的内容,岂不是很麻烦?

但是,在某些应用场景下,面向对象编程能够显示出更大的优势。

如何选择函数式编程和面向对象编程呢?可以这样进行选择,如果各个函数之间独立且无共用的数据,就选用函数式编程;如果各个函数之间有一定的关联性,那么选用面向对象编程比较好。

下面简单介绍面向对象的两大特性:封装和继承。1.封装

封装,顾名思义就是把内容封装好,再调用封装好的内容。封装分为两步:

第一步为封装内容。

第二步为调用被封装的内容。(1)封装内容

下面为封装内容的示例。In [24]:class Person: # 创建类 def __init__ (self, name, age): self.name = name self.age = age obj1 = Person('santos', 18) #将"santos"和 18 分别封装到 obj1及 self的 name和age属性

self在这里只是一个形式参数,当执行obj1=Person('santos',18)时,self等于obj1,此处将santos和18分别封装到obj1及self的name和age属性中。结果是obj1有name和age属性,其中name="santos",age=18。(2)调用被封装的内容

调用被封装的内容时有两种方式:通过对象直接调用和通过self间接调用。

通过对象直接调用obj1对象的name和age属性,代码如下:In [25]:class Person: # 创建类 def __init__ (self, name, age): self.name = name self.age = age obj1 = Person('santos', 18) #将"santos"和 18 分别封装到 #obj1 及 self的 name和age属性 print (obj1.name) # 直接调用obj1对象的name属性 print (obj1.age) # 直接调用obj1对象的age属性

santos

18

通过self间接调用时,Python默认会将obj1传给self参数,即obj1.detail(obj1)。此时方法内部的self=obj1,即self.name='santos',self.age=18,代码如下:In [26]:class Person: # 创建类 def __init__ (self,name,age): self.name = name self.age = age def detail(self): #通过self调用被封装的内容 print (self.name) print (self.age) obj1 = Person('santos', 18) obj1.detail() # Python将obj1传给self参数,即obj1.detail(obj1), # 此时内部self=obj1

santos

18

上述例子定义了一个Person的类。在这个类中,可以通过各种函数定义Person的各种行为和特性,要让代码显得更加清晰有效,就要在调用Person类各种行为的时候也可以随时提取。这比仅使用函数式编程更加方便。

面对对象的编程方法不会像平时按照执行流程去思考,在这个例子中,是把Person这个类型视为一个对象,它拥有name和age两个属性,在调用过程中,让自己把自己打印出来。

综上所述,对于面向对象的封装来说,其实就是使用构造方法将内容封装到对象中,然后通过对象直接或self间接获取被封装的内容。2.继承

继承是以普通的类为基础建立专门的类对象。面向对象编程的继承和现实中的继承类似,子继承了父的某些特性,例如:

猫可以:喵喵叫、吃、喝、拉、撒

狗可以:汪汪叫、吃、喝、拉、撒

如果我们要分别为猫和狗创建一个类,就需要为猫和狗实现他们所有的功能,代码如下,这里为伪代码,无法在python执行:In [ ]:class 猫: def 喵喵叫(self): print ('喵喵叫') def 吃(self): # do something def 喝(self): # do something def 拉(self): # do something def 撒(self): # do something class 狗: def 汪汪叫(self): print ('汪汪叫') def 吃(self): # do something def 喝(self): # do something def 拉(self): # do something def 撒(self): # do something

从上述代码不难看出,吃、喝、拉、撒是猫狗共同的特性,我们没有必要在代码中重复编写。如果用继承的思想,就可以写成:

动物:吃喝拉撒

猫:喵喵叫(猫继承动物的功能)

狗:汪汪叫(狗继承动物的功能)In [27]:class Animal: def eat(self): print ("%s 吃 " %self.name) def drink(self): print ("%s 喝 " %self.name) def shit(self): print ("%s 拉 " %self.name) def pee(self): print ("%s 撒 " %self.name) class Cat(Animal): def __init__(self, name): self.name = name def cry(self): print ('喵喵叫') class Dog(Animal): def __init__(self, name): self.name = name def cry(self): print ('汪汪叫') c1 = Cat('小白家的小黑猫') c1.eat() c1.cry() d1 = Dog('胖子家的小瘦狗') d1.eat() d1.eat() d1.cry()

小白家的小黑猫吃

喵喵叫

胖子家的小瘦狗吃

汪汪叫

对于继承来说,其实就是将多个类共有的方法提取到父类中,子类继承父类中的方法即可,不必一一实现每个方法。2.2.6 错误处理

在编程过程中,我们不免会遇到写出来的程序运行错误,所以程序员经常戏称自己是在“写bug(错误)而非写程序”。这些错误一般来说会使得整个程序停止运行,但是在Python中,我们可以用try/except语句来捕获异常。

try/except使用try来检测语句块中的错误,如果有错误的话,except则会执行捕获异常信息并处理。以下是一个实例:In [28]: try: result = 5/0 #除以0会产生运算错误 except Exception as e: #出现错误会执行except print (e) #把错误打印出来

division by zero

上述代码首先执行try里面的语句,除以0产生运算错误后,会执行except里的语句,将错误打印出来。在网络爬虫中,它可以帮我们处理一些无法获取到数据报错的情况。

此外,如果我们并不想打印错误,就可以用pass空语句。In [29]: try: result = 5/0 #除以0会产生运算错误 except: #出现错误会执行except pass #空语句,不做任何事情2.3 编写第一个简单的爬虫

当了解了Python的基础语法后,就算你是编程小白,也可以轻松爬取一些网站了。

为了方便大家练习Python网络爬虫,笔者专门搭建了一个博客网站用于爬虫的教学,本书教学部分的爬虫全部基于爬取笔者的个人博客网站(www.santostang.com)。一方面,由于这个网站的设计和框架不会更改,因此本书的网络爬虫代码可以一直使用;另一方面,由于这个网站由笔者拥有,因此避免了一些法律上的风险。

下面以爬取笔者的个人博客网站为例获取第一篇文章的标题名称,教大家学会一个简单的爬虫。2.3.1 第一步:获取页面#!/usr/bin/python# coding: utf-8import requests #引入包requestslink = "http://www.santostang.com/" #定义link为目标网页地址# 定义请求头的浏览器代理,伪装成浏览器headers = {'User-Agent' : 'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6'} r = requests.get(link, headers= headers) #请求网页print (r.text) #r.text是获取的网页内容代码

上述代码就能获取博客首页的HTML代码,HTML是用来描述网页的一种语言,也就是说网页呈现的内容背后都是HTML代码。如果你对HTML不熟悉的话,可以先去w3school(http://www.w3school.com.cn/html/index.asp)学习一下,大概花上几个小时就可以了解HTML。

在上述代码中,首先import requests引入包requests,之后获取网页。(1)首先定义link为目标网页地址。(2)之后用headers来定义请求头的浏览器代理,进行伪装。(3)r是requests的Response回复对象,我们从中可以获取想要的信息。r.text是获取的网页内容代码。

运行上述代码得到的结果如图2-16所示。图2-16 获取页面2.3.2 第二步:提取需要的数据#!/usr/bin/python# coding: utf-8import requestsfrom bs4 import BeautifulSoup #从bs4这个库中导入BeautifulSouplink = "http://www.santostang.com/"headers = {'User-Agent' : 'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6'} r = requests.get(link, headers= headers)soup = BeautifulSoup(r.text, "html.parser") #使用BeautifulSoup解析#找到第一篇文章标题,定位到class是"post-title"的h1元素,提取a,提取a里面的字符串,strip()去除左右空格title = soup.find("h1", class_="post-title").a.text.strip()print (title)

在获取整个页面的HTML代码后,我们需要从整个网页中提取第一篇文章的标题。

这里用到BeautifulSoup这个库对页面进行解析,BeautifulSoup将会在第4章进行详细讲解。首先需要导入这个库,然后把HTML代码转化为soup对象,接下来用soup.find("h1",class_="post-title").a.text.strip()得到第一篇文章的标题,并且打印出来。

soup.find("h1",class_="post-title").a.text.strip()的意思是,找到第一篇文章标题,定位到class是"post-title"的h1元素,提取a元素,提取

试读结束[说明:试读内容隐藏了图片]

下载完整电子书


相关推荐

最新文章


© 2020 txtepub下载