浅谈网络爬虫——基于Python实现

概述

       一个爬虫从网上爬取数据的大致过程可以概括为:向特定的网站服务器发出请求,服务器返回请求的网页数据,爬虫程序收到服务器返回的网页数据并加以解析提取,最后把提取出的数据进行处理和存储。因此,一个爬虫程序可以主要分为三大部分:向服务器请求并获取网页数据、解析网页数据、数据处理和存储。

获取网页数据

       一个爬虫程序中,这部分其实是最关键也是最容易出问题的部分。爬虫可以分为善意的和恶意的,善意的爬虫一般会自觉遵守某些协议,只爬取对方愿意让你爬的数据,并且不会对对方的服务器造成太大影响;当然,一般这样爬取的到的数据以及爬取效率都会受限,所以就自然会滋生很多的恶意爬虫,这种爬虫不但想方设法的爬取对方不想泄露的信息,而且也会多进程高速度的爬取,给对方带来很多无效访问,造成服务器资源浪费,也由此很多网站也开发了反爬虫策略来抵制这些恶意爬虫。一般的,大部分反爬虫策略是针对这一环节开发的,比如身份识别、特定IP的访问频率识别、验证码输入等,反爬虫和用户体验网站效率等之间很多时候是不可兼得的,因此这是一个需要权衡和评估的关键点。而且对于有些网页数据,是需要用户登录后才可以获取的,这时爬虫程序就也需要进行相应的登录操作后才可以请求需要的网页信息。此外,还有一些网站使用了一种叫做异步加载的技术,因此无法直接获取网页数据,还需要通过逆向工程等方式进一步分析。因此,一个爬虫程序相对最关键的部分就是如何获取到网页数据,这也是爬取数据过程中最灵活,也是最让人头疼的地方。

       下面主要简单讲述下获取网页数据的大致过程,然后再介绍几种Python中获取网页数据的几种主要的方法。

       获取网页的数据过程描述起来很简单,就是终端通过对应网页资源的特定标识(比如url、表单参数等)向服务器发起一个请求,然后服务器解析并响应这个请求,返回相应的网页数据。

       在Python中,一般爬虫主要是通过一个python的第三方库requests来实现这个过程的,requests库提供了两种发起请求的方法,分别为get()何post(),这也是大部分网站都会实现的两个接口。一般地,get()方法直接通过url参数(有时候还需要请求头参数)便可以发起有效请求;post()方法除此之外还需要一些额外的表单参数,才可以发起有效请求。在一个爬虫中具体用哪种方法取决于要爬取的网站实现了哪个接口,这个可以通过在浏览器(推荐chrome浏览器)的开发者工具(F12)查看。此外,还有一种方法是通过selenium库实现这个过程。selenium也是python的第三方库,其需要和第三方浏览器配合,可以在爬虫程序中模拟浏览器的操作,从而直接获取在实际浏览器中对应的操作可以获得的页面信息,由于PhantomJS已经停止开发,这里推荐的是chrome或者Firefox的无头浏览器。

       在获取网页数据的这个过程中,常遇到的问题是网站运用了异步加载技术(AJAX)和需要用户登录才可以进入相应的页面。所谓异步加载就是一种通过只和服务器交换少量的每页不同的数据就可以实现页面更新的技术,而不是每次都需要重新加载整个页面,这个可以更小的消耗服务器资源,也更高效快速。但是用了异步加载技术的网站的一个特点就是无法通过网页的显式url(即显示在网页顶部的链接)直接获取网页信息,因为一般的,对于采用了异步加载技术的网站,要么是用户可以通过不断的下滑页面实现分页,要么是通过点击网页显式的换页标签进行分页,而这些过程中分页时网站的显式url都是不变的,即说明一个显式的url对应着很多的分页,但是这些分页并不是一下子加载的,而是每次通过和服务器交换少量的分页特异性信息异步加载的,因此,我们可以把这个显式的url看作是分页的顶层逻辑,但是并不包含什么实质内容,这也就意味着我们无法通过一个显式的url来获取分页的数据。但是每个分页具有特定的标识,这个可以在浏览器的开发者工具的XHR项下看到,因此,当我们面对采用了异步加载技术的网站时,我们是通过XHR项下的分页标识进行爬取,而不是网页显式的url。

       (图1)

       (图2)

上面的两个图片对应的都是采用了异步加载技术的网站,图1中的General下的Request Method显示为GET,因此只需要url参数,这里的分页标识就是General下的Request URL,只需要把这个URL作为参数传给get方法即可。图2对应的Request Method为POST,因此必须用requests库中的post方法爬取,除了General下的Request URL参数,还需要图中的Form Data作为表单参数传给post,实际上,图2中尽管是不同的positionA...文件,里面的Request URL也是一样的,只有下面的Form Data不一样,这说明这里的分页标识不是Request URL,而是下面的Form Data。

       以上说的是异步加载的问题,那么如果遇到登录问题该怎么办呢?一般的,需要登录的网站实现的接口是post,需要用户填入账号密码登录,所以爬虫程序中,也是通过requests库中的post方法提交表单,需要提交的表单数据可以通过查看Form Data下面的项(如图2)。此外,由于有些网站的表单构造比较困难,因此还可以通过cookie信息来模拟登录。cookie信息记录了用户身份和网站行为,服务器会根据cookie信息把正常用户加入白名单,因此爬虫程序就可以通过用户的cookie信息模拟登录,服务器会自动识别cookie信息,识别用户的身份,予以相应的信息权限。

       当我们需要爬取很多页面时,我们不可能手动输入url和其他一些参数,因此解析url的构造规律就显得很重要,这时候一般是通过逆向工程(即通过不同分页的url和参数特征来猜测规律并加以验证)来解决。

       最后需要注意的几点:1、爬取数据时,最好控制一下爬取的频率,防止爬取频率过高从而被识别为恶意爬虫被封IP;2、请妥善使用IP代理池;3、关于验证码的问题,需要结合图形识别等技术,或者第三方人工打码平台;4、请尽量做一只友好善良的虫子。

解析网页数据

       当我们获取到网页数据之后,接下来就是对此进行解析并从中提取需要的数据。网站返回的数据格式有三种:HTML、XML、JSON,但是一般我们从网站上爬取到的从服务器中返回的是HTML格式的,有些从网站提供的API返回的数据格式是JSON,下面我们只针对HTML格式的数据进行分析。

       要解析HTML格式的数据,python中一般有三种方法,分别对应三个库:BeautifulSoup库、re库、Lxml库。

       BeautifulSoup库可以很方便的解析Requests库请求的网页,并把网页源代码解析为Soup对象,以便过滤提取数据。BeautifulSoup库除了支持HTML,也支持XML。可以通过该库中的find()、find_all()、selector()方法定位提取需要的数据,其中的参数以及定位原则可以查看文档。

       re库是python中关于正则表达式的库,支持全部的正则表达式功能,可以利用该库通过正则表达式来匹配提取HTML文档中的数据。一般可以通过该库中的search()、findall()函数来匹配提取。当然关于正则表达式需要读者额外的去学习,虽然在学习上会比较灵活,但是同时其也是功能相对最强大和效率最高的方法之一。

       Lxml是XML解析库,但是对HTML也有很好的支持,该模块使用c语言的python封装,因此解析速度比BeautifulSoup快。Lxml库使用Xpath语法解析定位网页数据,因此读者需要自行学习Xpath语法以便知道如何定位提取数据,学习难度不大,功能也强大。一般利用该库中的etree模块对网页进行解析,然后再利用解析后返回的对象中的xpath()方法结合Xpath语法提取需要的数据。

       这三种方法都可以实现对网页数据的解析和提取,但是性能上有差异。一般的,正则表达式和Lxml库的性能较高,但是正则表达式使用难度较大,Lxml一般是比较推荐的;BeautifulSoup库的性能相对较低,但是使用起来简单,在爬取小规模数据时可以使用。

数据处理和存储

       数据处理其实没啥多说的,其本身内容庞杂,即用即查,多用多学,但python对数据处理是有先天优势的。

       数据存储一般取决于数据量的大小,小规模的数据一般以csv的格式储存,这可以利用python的第三方库csv实现,该库的利用也比较简单。对于大规模的数据,则一般储存在数据库里面,无论是关系型数据库还是非关系型数据库,python对这两者主流的数据库都有第三方库的支持。比如对于非关系型数据库MongoDB,python有第三方库pymongo;关系型数据库MySQL,python有第三方库pymysql。如果是将数据储存在本地,则需要下载本地数据库,最好也下载数据库图形管理界面方便查看;如果是远程数据库,则同样的最好自己下载好图形界面的数据库管理器以便查看。

Scrapy爬虫框架

       最后简单介绍一下python中一个专门用来编写爬虫的框架scrapy。scrapy是Python的一个爬虫框架,既然是框架,说明对爬虫的结构逻辑具有严格的定义和拆分。里面将需要的数据条目、爬虫主体、数据储存三部分分别用不同的文件分隔,使得爬虫逻辑更为的清晰,并且也预写好了很多的细节,用户只需要编写和定义一些关键字段就行,这也大大的提高了爬虫的开发效率。具体的使用方法还需要用户自己查看文档或者相关的教材。

       由于scrapy有很多的依赖库,所以在安装的时候,如果已经下载了anaconda的读者,建议直接用conda命令进行安装,conda命令会自行安装该库的依赖库,这也是conda命令相比于pip命令的一个优势;如果没有下载anaconda,则最好下载一下,或者先下载好Lxml、zope.interface、twisted、pyOpenSSL、pywin32这些依赖库,然后再通过pip命令下载scrapy。

总结

       做一只善良友好的小虫子!

猜你喜欢

转载自blog.csdn.net/S_o_l_o_n/article/details/81952273
今日推荐