版权声明:本文为作者原创文章,可以随意转载,但必须在明确位置表明出处!!!
通过上一遍文章我们对python的基础语法和正则表达式有了一定的了解,从这边文章开始我们将进入实战,大家不要害怕,学习爬虫我们首先要做的是定一个目标,要相信没有爬不下来的东西,毕竟网页都是人写得,它们也遵循html规则,关于html标签语言可以到菜鸟教材·去稍微了解一下。这里我们通过爬取糗事百科的段子来作为python3爬虫系列的第一个教程,因为糗事百科基本上是静态网页,所以这类网页是是最好爬取的网页,非常适合爬虫的入门教程。
urllib和re(正则表达式模块)
爬虫,爬虫,就是把网上的内容爬到本地来,urllib模块的作用就是把网页上的内容去回到本地来,urllib是封装了http协议,至于http协议是怎么回事本篇内容不做讨论,http协议会在该系列之后的文章中对它做出详细的讲解。这里我们只需要知道urllib的作用是将网页上的内容取回到本地。取回到本地后它就是文本信息了,而要从文本信息中提取我们需要的信息就需要我们使用re模块(正则表达式模块)。
查看页面元素
首先我们来看一下糗事百科的主页长什么样子
从主页上可以看到每一个用户发表的一条段子都是一块,一块的分割开的。这就是html标签语言<\div>…<\/div>的作用,如果你对htm标签语言不熟习,可以花个半天时间去了解了解,了解html标签语言有助于更好的理解网页的布局,当然对你编写正则表达式规则也有莫大的帮助。
F12开发则工具
浏览器上都自带了开发则工具,只要你是web开发人员,这个工具你肯定会使用到,不管你是调试JS,还是css都会用到此工具。当然我们爬虫程序更需要用到此工具了,下面我们在糗事百科的页面按下键盘上的F12将会出现下面界面。
当然你看到的界面可能和我的不一样,这是浏览器不同造成的,我使用的是Chrome浏览器,如果你们使用的是IE或者Firefox浏览器按下F12肯定和我的是不一样的。
Elements、Network
按下F12后在出现的界面中有一行菜单栏,这里我们主要用到Elements、Network两个菜单
- Elements: 元素,指的是当前网页元素(如果是静态网页那么在当前页面右键鼠标–>查看网页源代码所看到的页面元素和这里看到的页面元素是一样的,只是这里的看到的元素是格式化了的,方便开发人员查看)
- Network: 网络,指的是浏览器和web服务器发生的所有网络交互
快速定位元素
在Elements菜单下移动鼠标到
项,可以看到页面上有“遇奸”这个用户的块区域被选中了。
可以看到Elements菜单下有很多类是\
快速的定位到发表的段子
- 点击菜单栏最左边的按钮。
- 滑动鼠标到发表的段子上。
是的只需要两步,你可以看到开发则工具界面就定位到发布的段子上了。
是时候表演真正的技术了
通过上面的介绍我们对页面的基本元素已经有所了解了,那么如何从页面元素中获取用户发表的段子呢,这里我们定一个目标,我们需要获取用户名、用户ID、段子、好笑数、如果用户发表的是图片我们还需要获取图片的url地址,下面正则表达式这位英雄就要登场了。
获取段子
当然最重要的就是段子了,我们的目的不就是为了爬取段子吗。首先我们在糗百页面右键鼠标–>产看页面源代码,然后Ctrl + a(全选), Ctrl + c(复制), 然后粘贴到正则表达式在线测试工具中。
我们先通过在线工具来测试我们写的正则表达式是否正确。
爬取思想
在解决一个事情之前我们首先要做的是先在脑子里想一想该怎么去解决这个问题,第一步做什么、第二步做什么、最后做什么、爬虫也一样我们首先要去想一想怎么去爬到我们需要的信息。从文章的前半部分开发者工具截图的Elements可以看出每个用户的信息都是包含在一对
- 第一步:取出包含在…中的所有信息
- 第二步:从第一步的结果中取出该用户发布的段子、用户名、用户ID、url图片地址、好笑数
首先取出包含在
|
|
鼠标点击[测试匹配]发现匹配结果为[没有匹配],如下图
这是怎么回事呢,点符号表示匹配任何字符除换行符外,星号表示匹配前面出现的正则表达式零次或多次,问号表示非贪婪匹配,非贪婪匹配的意思是尽可能少的匹配,我会在后面的章节中详细说明。按理说我们的正则表达式是没有问题的啊?这里需要特别主要了从上一篇聚沙成塔–爬虫系列(三)(正则表达式)文章介绍我们知道点符号匹配任何字符串(除换行符外),所以这里我们不能用点符号来匹配了,我们需要用到特殊符号\s表示匹配所有的空白符,\S表示匹配左右的非空白符,所以这两个符号的组合就表示匹配所以字符包括换行符,下面我们改写正则如下:
|
|
鼠标点击[测试匹配]发现匹配结果为[没有匹配],如下图
结果显示了我们匹配到了25个结果,这25个结果正好是糗百一页发布的数量,也表示一页上有25个用户, 但是这个时候我们查看结果的时候发现并没有包含段子内容,为什么呢?是因为我们的正则表达式匹配到结束,但是在最外层的…之中还有类似的div对,所以就不会匹配到最外层的结束标记,修改正则表达式如下:
|
|
取用户名、用户ID、段子、图片url地址
通过上一步我们已经取到了25个用户的所有信息,那么用户名和用户ID等等需要从这25个用户信息中获取到。这里我们又要回到开发者工具,通过上面所讲的操作,可以轻松定位到用户名,用户ID,段子
可以发现用户ID是在herf后面,用户名是在
…
之间,段子是在…之间的,所以我们需要的正则表达式如下:
|
|
代码实现
|
|
运行结果
|
|
代码解读
- import: 关键字,是导入python库文件的,当然也可以导入你自己写得文件,它的意思是要引用哪个模块,这里我们需要引用两个模块,一个是urllib模块,一个是re(正则表达式模块),引用了这两个模块后我们就能使用这两个模块提供的方法
- url: 变量,这里的变量赋值为糗事百科的网址
user_agent: 用户代理,这个参数很关键,爬虫所有的动作都需要模拟人怎么去操作,这样服务器才不会拦截你的访问,user_agent表示我们使用的是什么浏览器去访问的,这里需要说明一下反爬策略,常见的反爬策略是服务器端会监测你的user_agent,ip, 访问频率,如果你同一个ip地址短时间内访问过多,服务器端会认为你不是人为操作,它会认为你是个机器人,因为人为操作没有这么频繁。所以爬和反爬是一对天敌,后面我会讲爬虫的高级应用,所谓“道高一尺,魔高一丈”是也。user_agent参数可以通过开发者工具Network菜单下的Headers查看
Request(…):该函数是创建一个请求实例,我们可以看看开发文档的描述
- urlopen(…): 打开一个url,该函数的定义如下
urllib.request.urlopen(url, data=None, [timeout, ]*, cafile=None, capath=None, cadefault=False, context=None)
url参数可以是一个字符串也可以是一个Request对象,更多的介绍可以查看开发文档 - read(): 读取页面返回的内容。
- decode():解码,我们读取回来的内容是经过编码后的字符串,如果不解码就看不明白都会来的字符串,如何查看页面是什么编码呢?我们可以通过开发者工具查看,也可以通过查看页面源代码查看网页编码。
- compile(): 编译正则表达式模块,这个函数将返回一个匹配模式对象,这里推荐大家写正则表达式的时候先把正则表达式预编译成一个对象,这样在查找的时候程序就不需要每次都再去编译一次正则表达式了,特别是对于在海量文本中查找的时候预编译正则规则尤为重要,预编译正则规则能提高你的代码执行效率
findall,sub等函数上一篇聚沙成塔–爬虫系列(三)(正则表达式)文章已经介绍过了,这里不在累诉。
note: 这里我们用到了前面章节介绍到的python的两种数据结果,列表和元组,还有for循环语法,函数findall返回的是一个list(列表),所以我们需要循环列表里的每个元素,每个元素代表一个被匹配上的用户信息,正则表达式中用()括号括起来的表示你要取的元素,它将会以元组的形式方法。到这里我们就完成了一个最基本的爬虫程序了,你是不是可以收集海量段子了,时不时的给妹子发个段子,是不是可以在妹子面前展示一下你的幽默诙谐了,哈哈。。。。,骚年这还不够,继续努力吧。。。。
更多的文章可以关注我的blog:http://www.gavinxyj.com