先检查是否有API
API是网站官方提供的数据接口,如果通过调用API采集数据,则相当于在网站允许的范围内采集,这样既不会有道德法律风险,也没有网站故意设置的障碍;不过调用API接口的访问则处于网站的控制中,网站可以用来收费,可以用来限制访问上限等。整体来看,如果数据采集的需求并不是很独特,那么有API则应优先采用调用API的方式。
数据结构分析和数据存储
爬虫需求要十分清晰,具体表现为需要哪些字段,这些字段可以是网页上现有的,也可以是根据网页上现有的字段进一步计算的,这些字段如何构建表,多张表如何连接等。值得一提的是,确定字段环节,不要只看少量的网页,因为单个网页可以缺少别的同类网页的字段,这既有可能是由于网站的问题,也可能是用户行为的差异,只有多观察一些网页才能综合抽象出具有普适性的关键字段——这并不是几分钟看几个网页就可以决定的简单事情,如果遇上了那种臃肿、混乱的网站,可能坑非常多。
对于大规模爬虫,除了本身要采集的数据外,其他重要的中间数据(比如页面Id或者url)也建议存储下来,这样可以不必每次重新爬取id。
数据库并没有固定的选择,本质仍是将Python里的数据写到库里,可以选择关系型数据库MySQL等,也可以选择非关系型数据库MongoDB等;对于普通的结构化数据一般存在关系型数据库即可。sqlalchemy是一个成熟好用的数据库连接框架,其引擎可与Pandas配套使用,把数据处理和数据存储连接起来,一气呵成。
数据流分析
对于要批量爬取的网页,往上一层,看它的入口在哪里;这个是根据采集范围来确定入口,比如若只想爬一个地区的数据,那从该地区的主页切入即可;但若想爬全国数据,则应更往上一层,从全国的入口切入。一般的网站网页都以树状结构为主,找到切入点作为根节点一层层往里进入即可。
值得注意的一点是,一般网站都不会直接把全量的数据做成列表给你一页页往下翻直到遍历完数据,比如链家上面很清楚地写着有24587套二手房,但是它只给100页,每页30个,如果直接这么切入只能访问3000个,远远低于真实数据量;因此先切片,再整合的数据思维可以获得更大的数据量。显然100页是系统设定,只要超过300个就只显示100页,因此可以通过其他的筛选条件不断细分,只到筛选结果小于等于300页就表示该条件下没有缺漏;最后把各种条件下的筛选结果集合在一起,就能够尽可能地还原真实数据量。
明确了大规模爬虫的数据流动机制,下一步就是针对单个网页进行解析,然后把这个模式复制到整体。对于单个网页,采用抓包工具可以查看它的请求方式,是get还是post,有没有提交表单,欲采集的数据是写入源代码里还是通过AJAX调用JSON数据。
同样的道理,不能只看一个页面,要观察多个页面,因为批量爬虫要弄清这些大量页面url以及参数的规律,以便可以自动构造;有的网站的url以及关键参数是加密的,这样就悲剧了,不能靠着明显的逻辑直接构造,这种情况下要批量爬虫,要么找到它加密的js代码,在爬虫代码上加入从明文到密码的加密过程;要么采用下文所述的模拟浏览器的方式。
数据采集
之前用R做爬虫,不要笑,R的确可以做爬虫工作;但在爬虫方面,Python显然优势更明显,受众更广,这得益于其成熟的爬虫框架,以及其他的在计算机系统上更好的性能。scrapy是一个成熟的爬虫框架,直接往里套用就好,比较适合新手学习;requests是一个比原生的urllib包更简洁强大的包,适合作定制化的爬虫功能。requests主要提供一个基本访问功能,把网页的源代码给download下来。一般而言,只要加上跟浏览器同样的Requests Headers参数,就可以正常访问,status_code为200,并成功得到网页源代码;但是也有某些反爬虫较为严格的网站,这么直接访问会被禁止;或者说status为200也不会返回正常的网页源码,而是要求写验证码的js脚本等。
下载到了源码之后,如果数据就在源码中,这种情况是最简单的,这就表示已经成功获取到了数据,剩下的无非就是数据提取、清洗、入库。但若网页上有,然而源代码里没有的,就表示数据写在其他地方,一般而言是通过AJAX异步加载JSON数据,从XHR中找即可找到;如果这样还找不到,那就需要去解析js脚本了。
解析工具
源码下载后,就是解析数据了,常用的有两种方法,一种是用BeautifulSoup对树状HTML进行解析,另一种是通过正则表达式从文本中抽取数据。
BeautifulSoup比较简单,支持Xpath和CSSSelector两种途径,而且像Chrome这类浏览器一般都已经把各个结点的Xpath或者CSSSelector标记好了,直接复制即可。以CSSSelector为例,可以选择tag、id、class等多种方式进行定位选择,如果有id建议选id,因为根据HTML语法,一个id只能绑定一个标签。
正则表达式很强大,但构造起来有点复杂,需要专门去学习。因为下载下来的源码格式就是字符串,所以正则表达式可以大显身手,而且处理速度很快。
对于HTML结构固定,即同样的字段处tag、id和class名称都相同,采用BeautifulSoup解析是一种简单高效的方案,但有的网站混乱,同样的数据在不同页面间HTML结构不同,这种情况下BeautifulSoup就不太好使;如果数据本身格式固定,则用正则表达式更方便。比如以下的例子,这两个都是深圳地区某个地方的经度,但一个页面的class是long,一个页面的class是longitude,根据class来选择就没办法同时满足2个,但只要注意到深圳地区的经度都是介于113到114之间的浮点数,就可以通过正则表达式"11[3-4]\d+"来使两个都满足。
数据整理
一般而言,爬下来的原始数据都不是清洁的,所以在入库前要先整理;由于大部分都是字符串,所以主要也就是字符串的处理方式了。
字符串自带的方法可以满足大部分简单的处理需求,比如strip可以去掉首尾不需要的字符或者换行符等,replace可以将指定部分替换成需要的部分,split可以在指定部分分割然后截取一部分。
如果字符串处理的需求太复杂以致常规的字符串处理方法不好解决,那就要请出正则表达式这个大杀器。
Pandas是Python中常用的数据处理模块,虽然作为一个从R转过来的人一直觉得这个模仿R的包实在是太难用了。Pandas不仅可以进行向量化处理、筛选、分组、计算,还能够整合成DataFrame,将采集的数据整合成一张表,呈现最终的存储效果。
写入数据库
如果只是中小规模的爬虫,可以把最后的爬虫结果汇合成一张表,最后导出成一张表格以便后续使用;但对于表数量多、单张表容量大的大规模爬虫,再导出成一堆零散的表就不合适了,肯定还是要放在数据库中,既方便存储,也方便进一步整理。
写入数据库有两种方法,一种是通过Pandas的DataFrame自带的to_sql方法,好处是自动建表,对于对表结构没有严格要求的情况下可以采用这种方式,不过值得一提的是,如果是多行的DataFrame可以直接插入不加索引,但若只有一行就要加索引否则报错,虽然这个认为不太合理;另一种是利用数据库引擎来执行SQL语句,这种情况下要先自己建表,虽然多了一步,但是表结构完全是自己控制之下。Pandas与SQL都可以用来建表、整理数据,结合起来使用效率更高。
这篇的内容是一系列针对在Python中从零开始运用机器学习能力工作流的辅导第一部分,覆盖了从小组开始的算法编程和其他相关工具。最终会成为一套手工制成的机器语言工作包。这次的内容会首先从数据准备开始。
—— 来自Matthew Mayo, KDnuggets
似乎大家对机器学习能力的认知总是简单到把一系列论据传送到越来越多的数据库和应用程序界面中,接着就期待能有一些神奇的结果出现。可能你对在这些数据库里究竟发生了什么有自己很好的理解—— 从数据准备到建模到结果演示呈现等等,但不得不说你依然需要依赖于这些纷繁的工具去完成自己的工作。
这其实很正常。我们用被准确检验证明过能运行的工具来完成一些日常的任务是无可厚非的。重新发明使用那些不能有效滚动的轮子不是最好的办法。这样会有很多局限,也会浪费很多的不必要的时间。无论你是使用开放源代码还是被授权的工具来完成你工作,这些代码工具已经被很多人反复试用升级以确保当你上手使用的时候能够以最好的质量完成你的工作。
然而,有些苦活累活你自己做也是有价值的,即便是作为一种教育性的努力。我不是要推荐你们从零开始通过自己深度学习练习写出一个程序框架,至少不能一直这样,但哪怕只有一次通过不断的试验和失败,从头开始写出和自己的算实现它们的支持工具也是非常好的。我可能说的不对,但我认为如今在学习机器学习能力、数据科学、人工智能等方面的大多数人都没有在这么做。
所以让我们从头开始,来学习在Python里建立一些机器学习能力的相关知识。
“From Scratch” 究竟是什么意思?
首先,我先申明:当我提到“From Scratch”,我的意思是尽可能少的借助外界的帮助。当然这也是相对的,但是为了达成我们的目标,我会划定界限,当我们在写自己的矩阵模型、数据框或者构建自己的数据库时,我们会分别使用Python中的numpy、panda和matplotlib库。在某些情况下,我们甚至不会使用这些库的全部功能。我们稍后会讨论,让我们先暂时放一放它们的名字以便大家更好的理解。在Python自带的库中自带的功能原则上都是可以使用的,但除此之外,我们就要自己来写了。
我们需要从一个点入手,那就让我们从一些简单的数据准备任务开始吧。开始的时候我们会慢一点,但当我们对(要学习的东西)有了一点感觉以后,我们会逐渐加快速度。除了数据准备,我们还需要数据转换、结果演示和呈现工具——更不必说机器学习能力算法了——来达成我们我们即将要完成的目标。
我们的想法是手动拼接任何我们需要的重大功能,以便完成我们的机器学习能力任务。当序列展开的时候,我们可以添加新的工具和算法,同时我们也能重新思考我们以前的假设(是否正确),使整个过程尽可能重复迭代,就像它会渐近一样。慢慢的,我们会集中精力在我们的目标上,制定策略来完成目标,把它们运用到Python里,再检验它们是否能够运行。
最终的结果,就想我们现在预期的一样,会是有序排列在我们自己的简易的机器学习数据库中的一系列简单的Python模型。对于初学者,我相信这是理解机器学习过程、工作流和算法如何运行的非常宝贵的经验。
工作流(workflow)究竟是什么意思?
工作流对不同的人意味着不同的意思,但是我们这里说的工作流指的是机器学习项目中的一部分。我们有很多过程框架来帮助我们追踪我的工作进程,但现在让我们简化到一下的这些:
获取数据
处理/准备数据
建立模型
解释呈现结果
在我们真正做的时候我们可以拓展,但是这是我们现在自己设计的简单的机器学习的过程框架。同时,“输送管(小箭头)”暗含了把工作流中各功能聚集在一起的能力,所以让我们把这些记住然后继续向前。
获得数据
在我们建立自己的模型之前,我们需要一些数据,还需要确认这些数据与我们合理的期望相符合。为了检测的目的(而不是训练或测试,但只是测试我们自己的设备),我们会使用虹膜数据集,你可以从这里下载。尽管我们可以在网上找到很多版本的数据集,但我建议我们都使用相同的原始数据,以确保我们的准备工作正常运行。
让我们来看一看:
既然我们已经知道了这个简单的数据集和它对应的文件,我们先来想一想我们需要做什么使原始数据演变成我们想要的结果:
数据需要储存成CSV格式的文件
实例大部分由有数字属性的值组成
组别是经过分组的内容
到目前为止,以上没有一种是对所有的数据集都适用的,但是也没有任何一个是只能适用于某一种数据集的。这使得我们能够有机会编写我们可以以后重复使用的代码。好的编程练习会让我们集中于重复利用性和模块性。
一些简单的探索性数据分析被罗列如下:
(上图为具体数值,下图为图像化数据)
准备数据
虽然数据准备在我们现在这个特定的情境中需要的很少,但是有时还是会需要。尤其是我们需要确认我们解释了标题行,去除了任何pandas呈现出来的参数,并且把我们的每一次组的值从名字型的转化成数值型的。因为在我们使用模型时已经没有名字性数值了,所以到此为止至少就没有更复杂的转化了。
最终,我们也需要一个对我们自己的算法的更好的数据呈现,所以我们在继续向前进行之前会确保我们最终呈现的是一个矩阵——或者numpy nadarry。我们的数据准备工作流接下来会做一下的表格:
同时,我们需要主要我们没有理由相信所有有趣的数据都会被储存在被逗号分开的文件里。我们可能希望能够从一个SQL数据库里或者直接从网上获取数据,从这两个地方找到的数据我们以后还能返回去回看。
首先,让我们写一个简单的函数,把一个CSV文件上传到DataFrame。当然,这在内网做很容易,但是再往前想一步我们可能想再加一些额外的步骤到我们自己的数据集里以便我们以后上载函数。
这个编码是相当直接的。一行一行的读数据文件就完成了一些额外的预先加工,比如忽略了那些内容非数据的行(我们认为在数据文件中评价是由井号键开始的,尽管这很荒谬。)我们可以详细说明这个数据集文件是否包括标题,我们也可以接受csv和tsv文件,csv文件是默认的设置。
有一些错误检查存在,但它还并不是很健全,所以我们或许可以晚一点再回来说这个话题。此外,逐条读文件再逐条决定要对这些行做什么,比直接用内置功能把处理干净的一致的cs一文件直接读到DataFrame中要慢,但权衡之后我们发现允许更多的灵活性,在这一阶段是值得的(但读大的文件可能会发花费很久的时间)。不要忘了,如果一部分内置 *** 作不是最好的方法,我们可以晚一些再做调整。
在我们尝试运行自己的编码之前,我们需要来写一个函数,把名字类数值转化成数字类数值。为了推广函数,我们需要使它能够用于数据集中的任何属性的数值,不仅仅是运用于不同的类别。我们还应该跟踪属性名称最终是否成为了整数。有了之前把csv或ts me的数据文件上传pandas的DataFrame的步骤经验,这个函数应该同时接受一个pandas DataFrames以及被转化为数字的属性名称。
我们还要注意,我们回避了关于使用单热编码的话题,这涉及到分类的非分类属性,但我认为我们以后还会回到这个话题。
上述的函数又是一个简单的,但是能帮助我们完成目标函数。我们可以用很多不同的方式来完成这个任务,包括使用pandas内置的功能,但是让你从一些会让你有些累的苦差事开始做就是这个函数的意义。
现在我们可以从文件中加载一个数据集,然后把分类属性值转换成数字属性值(我们也可以保留这些映像在字典中供以后使用)。就像之前提到的,我们希望我们的数据集最终是以numpy ndarry的形式存在,这样我们可以在自己的算法中很简单的使用。同样的,这是一个简单的任务,但写一个函数会让我们在以后需要的时候还可以以此为准。
即使以前任何的功能都没有过度的杀伤力,但这个功能有可能有。但请忍耐我,我们遵守非常全面的编程准则--如果过于谨慎的话。在我们继续往下讲的过程中会有很好的机会让我们对已有的功能做改变或添加。这些变化如果能在一个地方实施并且记录在案,从长远来看非常有意义。
测试数据准备的工作流
我们的工作流迄今为止可能仍然是构建板块的形式,但让我们给自己的编码一个测试。
我们的代码正在按我们希望的方式工作,让我们做一些简单的房屋清理工作。一旦开始滚动,我们将为我们的编码提供一个更全面的组织结构,但是现在我们需要把所有这些功能加到一个单独的文件中,并保存成为datasetpy的格式。这会让我们以后的使用更方便,下次我们会学到。
未来计划
之后我们会学习简单的分类算法,k最近邻算法。我们会学习如何在简单的工作流中构建分类和聚类模型。毫无疑问,这需要编写一些限额外的工具来帮助我们完成项目,并且我确定我们还将对已经做完的部分进行修改。
练习机器学习就是理解机器学习的最好方法。运用我们的工作流中需要的算法和支持工具最终会被证明是有用的。
以上就是关于Python爬虫如何写全部的内容,包括:Python爬虫如何写、如何用Python做数据准备、等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)