学习 python 爬虫的路线
学习Python有个学习方向能够少走点弯路,就像在实习的时候,能够遇到一个好老大,给你稍微指一下方向,比你自己瞎jb琢磨的结果肯定结果相差很大。毕竟人家认知比你高上一截。
基本的 Python 语法
要用 Python 来写爬虫,当然是需要 Python 的基本语法了。Python的基本语法不难,之前我就写了一个小教程,讲的是 Python3 的一些基本使用,可以看看这里:python3入门基础有趣的教程
抓包工具
爬虫要去抓取网页上的内容,一些请求参数和返回数据信息,需要去分析和抓取,熟悉一下抓包工具的使用还是很有必要的,这不,我也写了一个关于 Fiddler 的使用:Fiddler抓包工具完全使用教程,还顺便装了个逼!
爬虫常用到的模块
Python 有一些内置的库,专门对一些网页数据的请求和解析使用的,比如urllib,>
正则表达式
抓包获取到的数据,有很多数据是你不想要的,我们只需要拿到我们想要的数据就可以了,那么这个时候呢,正则表达式就派上用场了,常用的有:re,Xpath,BeautifulSoup。
反爬机制
有些网站被爬取怕了,做了一些爬虫的限制,要学点反爬机制才行,header,robot,时间间隔,ip代理,UA限制,Cookie限制等。
数据存储
爬取到的数据要存储下来吧,那么就要会数据库的 *** 作,比如mysql。还要会数据去重 *** 作。
爬虫效率
提高爬取数据的效率,就需要使用多线程,分布式。
爬虫的框架
站在巨人的肩膀上尿尿,那么就需要知道框架怎么使用,比如Scrapy,PySpider,简直牛逼。
Python爬虫可以爬取的东西有很多,Python爬虫怎么学?简单的分析下:
如果你仔细观察,就不难发现,懂爬虫、学习爬虫的人越来越多,一方面,互联网可以获取的数据越来越多,另一方面,像 Python这样的编程语言提供越来越多的优秀工具,让爬虫变得简单、容易上手。
利用爬虫我们可以获取大量的价值数据,从而获得感性认识中不能得到的信息,比如:
知乎:爬取优质答案,为你筛选出各话题下最优质的内容。
淘宝、京东:抓取商品、评论及销量数据,对各种商品及用户的消费场景进行分析。
安居客、链家:抓取房产买卖及租售信息,分析房价变化趋势、做不同区域的房价分析。
拉勾网、智联:爬取各类职位信息,分析各行业人才需求情况及薪资水平。
雪球网:抓取雪球高回报用户的行为,对股票市场进行分析和预测。
爬虫是入门Python最好的方式,没有之一。Python有很多应用的方向,比如后台开发、web开发、科学计算等等,但爬虫对于初学者而言更友好,原理简单,几行代码就能实现基本的爬虫,学习的过程更加平滑,你能体会更大的成就感。
掌握基本的爬虫后,你再去学习Python数据分析、web开发甚至机器学习,都会更得心应手。因为这个过程中,Python基本语法、库的使用,以及如何查找文档你都非常熟悉了。
对于小白来说,爬虫可能是一件非常复杂、技术门槛很高的事情。比如有人认为学爬虫必须精通 Python,然后哼哧哼哧系统学习 Python 的每个知识点,很久之后发现仍然爬不了数据;有的人则认为先要掌握网页的知识,遂开始 HTMLCSS,结果入了前端的坑,瘁……
但掌握正确的方法,在短时间内做到能够爬取主流网站的数据,其实非常容易实现,但建议你从一开始就要有一个具体的目标。
在目标的驱动下,你的学习才会更加精准和高效。那些所有你认为必须的前置知识,都是可以在完成目标的过程中学到的。这里给你一条平滑的、零基础快速入门的学习路径。
1学习 Python 包并实现基本的爬虫过程
2了解非结构化数据的存储
3学习scrapy,搭建工程化爬虫
4学习数据库知识,应对大规模数据存储与提取
5掌握各种技巧,应对特殊网站的反爬措施
6分布式爬虫,实现大规模并发采集,提升效率
后羿采集器数据爬取断啦,重启动如何接下去一页开始,不从头开始,直接在启动任务时进行数据去重设置,选择“当所有字段都重复时,跳过继续采集”。该方案设置简单,但是效率较低,设置之后任务仍然会从第一页开始采集,然后逐个跳过所有已经采集到的数据。
pythonweb
其实在很早之前,Python就已经在Web开发领域被广泛使用,产生了Django、Flask、Tornado等Web开发框架。其简洁的语法和动态语言特性,使Python的开发效率很高。
自动化运维
在自动化运维领域,Python则是必备技能。灵活的功能和丰富的类库使其成为运维工程师的首选语言。大量自动化运维工具和平台或以Python开发,或提供Python的配置接口。
网络爬虫
对于很多数据相关公司来说,爬虫和反爬虫技术都是其赖以生存的重要保障。尽管很多语言都可以编写爬虫,但灵活的Python无疑也是当前的首选。
这个星球上最大的“爬虫”公司--Google一直力推Python
数据分析
当通过爬虫获取了海量数据之后,需要对数据进行清洗、去重、存储、展示、分析,在这方面Python有许多优秀的类库:NumPy、Pandas、Matplotlib可以让你的数据分析工作事半功倍。
人工智能
Python在人工智能大范畴领域内的数据挖掘、机器学习、神经网络、深度学习等方面都是主流的编程语言,得到广泛的支持和应用。
胶水语言
Python简洁、灵活、通用,几乎可以在各种场景与各种平台、设备、语言进行连接,因此被称为胶水语言。
上述只是简单介绍,python的功能强大,真正要了解python能做什么,不如深入学习,才能真正了解python的价值。
爬虫:
提到爬虫,不少人会第一时间想到Python,对的,Python十分适合实现爬虫的功能,比如有一些手动完成十分麻烦的工作,可能需要一星期甚至更久,学完Python后,可以在半天甚至更短的时间内完成工作,十分有效地提高工作效率。
技能要求:前端基础、Python爬虫库、数据库、JS反爬等。
数据分析:
学会爬虫后,我们就有了各种各样的数据,使用这些数据以及爬虫库和excel表,就可以进行简单的数据分析了,在大量数据的基础之上,结合科学计算、机器学习等技术,对数据进行清洗、去重和针对性的分析是大数据行业的基石。
技能要求:统计学基础、Python数据分析库、数据库、机器学习框架
Web开发:
Python有很多优秀的Web开发框架,可以帮助你快速搭建一个网站,像知乎、小米等大厂,最早的网站也都是用Python搭建的。
技能要求:前端基础、Python基础、主流Python Web框架、数据库等
人工智能:
是近几年发展良好的新行业,在Python语言的基础上做开发、研究,开发用于模拟、延伸和扩展人智能的理论、方法、技术及应用系统的新兴技术。
技能要求:统计学基础、Python、数据分析表、机器学习、深度学习框架
自动化运维:
运维工程师经常要监控上百台机器的运行,或同时部署的情况,使用Python可以自动化批量管理服务器,自动化运维也是Python的主要应用方向之一,在系统管理、文档管理方面都有很强大的功能。
技能要求:Python、Shell、Linux、数据库、openpyxl库等。
言归正传。
所谓的Url去重(我一直没找到对应的英文,URL Filtering ),就是爬虫将重复抓取的URL去除,避免多次抓取同一网页。爬虫一般会将待抓取的URL放在一个队列中,从抓取后的网页中提取到新的URL,在他们被放入队列之前,首先要确定这些新的URL没有被抓取过,如果之前已经抓取过了,就不再放入队列。
最直观的做法 – hash表
为了尽快把整个爬虫搭建起来,最开始的URL去重采用方案是一个内存中的HashSet,这是最直观的方法,所有人都能想得到。HashSet中放置的就是URL的字符串,任何一个新的URL首先在HashSet中进行查找,如果HashSet中没有,就将新的URL插入HashSet,并将URL放入待抓取队列。
这个方案的好处是它的去重效果精确,不会漏过一个重复的URL。它的缺点是,我的爬虫第二天早上就挂了,Out Of Memory。因为随着抓取网页的增加,HashSet会一直无限制的增长。另外,网络中的很多URL其实是很长的,有大量的URL长度达到上百个字符。当然,因为我的爬虫是跑在一个小服务器上,JVM的内存本来就不多,否则它应该能再多撑1-2天。
简单估算一下,假设单个URL的平均长度是100 byte(我觉着这已经非常保守了),那么抓取1000万的URL就需要:
100 byte 10 000 000 = 1 GB
而1000万URL在整个互联网中实在是沧海一粟。可以了解,需要多大的内存才能装下所有URL的HashSet。
压缩URL
为了我的爬虫能再多撑几天,同时不想改动太多的代码,第二个版本增加了一个小功能,就是HashSet中不存储原始的URL,而是将URL压缩后再放进去。貌似有不少paper中讨论过如何对URL进行压缩,包括新浪微博中的短URL其实也是个不错的方案,可惜这些方法我都不会。为了偷懒,我直接用MD5对URL做编码。
MD5的结果是128 bit也就是16 byte的长度。相比于之间估计的URL平均长度100byte已经缩小了好几倍,可以多撑好多天了。
当然,哪怕找个一个可以压缩到极致的算法,随着URL越来越多,终有一天会Out Of Memory。所以,这个方案不解决本质问题。
MD5另外一个问题是,有可能两个相同的URL被映射成同一个MD5值,这样的话,它们中有一个就永远不会被抓取了。我不太确定的是,这个概率会有多大。如果非常小的话,这微小的误差倒也不会有太大影响。
Bloom Filter
基于内存的HashSet的方法存在一个本质的问题,就是它消耗的内存是随着URL的增长而不断增长的。除非能够保证内存的大小能够容纳下所有需要抓取的URL,否则这个方案终有一天会到达瓶颈。
这时候就会想,要找一个类似于HashSet的但所消耗的内存相对固定而不会不断增长的方案,于是自然想到了Bloom Filter。关于Bloom Filter的概念这里就不多谈了,网上随处可以找到。我简单尝试了一下Bloom Filter,但是很快就放弃了。基于Bloom Filter的方案有几个问题:
第一个是理论上的。Bloom Filter会将一些正常的样本(在我这就是没有抓取过的URL)过滤掉,即所谓的False Positive。当然,这概率有多大,取决于Bloom Filter的参数设置。但这引出了下一个问题;
第二个是实践中的,即Bloom Filter的那几个参数应该如何设置?m,k,n应该设置成多少才合适,这个我没有经验,而且可能需要反复的实验和测试才能够比较好的确定下来;
以上两个问题还不是我放弃Bloom Filter的根本原因,真实的原因是我在做的是一个爬虫框架,上面可以会启动很多的爬虫任务,每个任务可能抓取自己特定的URL,而且任务之间是独立的。这样,对于每个任务都需要有一个Bloom Filter,虽然对于单一任务它使用Bloom Filter所消耗的内存是固定的,但是任务的增多会导致更多的Bloom Filter,从而导致更多的内存消耗。仍然存在内存溢出的可能。
但如果只是一个抓取任务,那么采用Bloom Filter应该是一个非常不错的选择。
BerkeleyDB
我终于明白我所需要的其实是一个可以放在disk上的去重方案,这样,内存溢出将永远成不了可能。很早就知道有BerkeleyDB这么一个东西,但第一次真正了解还是在Amazon的Dynamo那篇论文中提到过采用了BerkeleyDB作为单机上的底层存储。当时觉着这东西真另类,原来还有叫做“DB”的东西却不支持SQL。那时候还没有NOSQL这词,把这样的东西叫做non-relational database。
BerkeleyDB是一个key-value database,简单的说,就是一个在disk上的hash表,这也是为什么它可以被用来做URL去重的原因。它另外一个另类的地方是,它是和程序运行在同一个进程空间中的,而不像一般的db,是做为单独的程序运行。
这里附上Heritrix中使用BerkeleyDB做URL去重的代码,一探究竟:(代码位于Heritrix源代码的orgarchivecrawlerutilBdbUriUniqFilter)
有一堆做初始化和配置的函数就直接忽略了,真正相关的函数就只有两个:
[java] view plaincopy
/
Create fingerprint
Pubic access so test code can access createKey
@param uri URI to fingerprint
@return Fingerprint of passed <code>url</code>
/
public static long createKey(CharSequence uri) {
String url = uritoString();
int index = urlindexOf(COLON_SLASH_SLASH);
if (index > 0) {
index = urlindexOf('/', index + COLON_SLASH_SLASHlength());
}
CharSequence hostPlusScheme = (index == -1) url: urlsubSequence(0, index);
long tmp = FPGeneratorstd24fp(hostPlusScheme);
return tmp | (FPGeneratorstd40fp(url) >>> 24);
}
[java] view plaincopy
/
value: only 1 byte
/
private static DatabaseEntry ZERO_LENGTH_ENTRY = new DatabaseEntry(
new byte[0]);
protected boolean setAdd(CharSequence uri) {
DatabaseEntry key = new DatabaseEntry();
LongBindinglongToEntry(createKey(uri), key);
long started = 0;
OperationStatus status = null;
try {
if (loggerisLoggable(LevelINFO)) {
started = SystemcurrentTimeMillis();
}
status = alreadySeenputNoOverwrite(null, key, ZERO_LENGTH_ENTRY);
if (loggerisLoggable(LevelINFO)) {
aggregatedLookupTime +=
(SystemcurrentTimeMillis() - started);
}
} catch (DatabaseException e) {
loggersevere(egetMessage());
}
if (status == OperationStatusSUCCESS) {
count++;
if (loggerisLoggable(LevelINFO)) {
final int logAt = 10000;
if (count > 0 && ((count % logAt) == 0)) {
loggerinfo("Average lookup " +
(aggregatedLookupTime / logAt) + "ms");
aggregatedLookupTime = 0;
}
}
}
if(status == OperationStatusKEYEXIST) {
return false; // not added
} else {
return true;
}
}
简单解释一下:
第一个函数createKey是在做URL的压缩,它将任意长度的URL转换成一个long型的值。long型的取值范围有2^64,因此两个URL映射成同一个long型值的概率应该挺低的。但我也没太细看这个函数,所以它的效果到底如何不确定。
第二个函数setAdd就是将被压缩的URL写入到BerkeleyDB。之前说过,BerkeleyDB是一个key-value database,它的每条记录都包括了一个key和一个value。但是在URL去重中,value不重要(比如我们之前内存中用的也是HashSet而不是HashMap),因此这里统一用一个byte长度的值来表示value,就是这个static变量ZERO_LENGTH_ENTRY。
别看setAdd有这么多行,真正有用的就这一行:
[java] view plaincopy
status = alreadySeenputNoOverwrite(null, key, ZERO_LENGTH_ENTRY);
将压缩后得到的long型值作为key,ZERO_LENGTH_ENTRY作为value插入到BerkeleyDB中,如果db中已经有了这个long型值,就会返回OperationStatusKEYEXIST,表示对应的URL之前已经抓取到了,那么这个URL就不会放入待抓取队列中。
最后
比较遗憾的是,我还没抽出空对BerkeleyDB这个方案做性能测试,不确定它每秒能执行多少次setAdd *** 作,是否足够满足我们性能的要求。以后补上。
另外,虽然我不了解,但我认为像百度这样专业的搜索引擎,它的爬虫的URL去重方案可能比这里列举的要复杂的多,毕竟那个的各方面的要求也要更高。
爬虫脑缺陷是指在编写爬虫程序时出现的一种错误,通常是由于程序设计不当或代码实现有误而导致的。以下是爬虫脑缺陷的几个常见表现形式:
1 内存泄漏:爬虫程序需要频繁地请求网络数据,并将其存储在内存中。如果程序中没有正确地释放不再需要的内存,就会导致内存泄漏,最终导致程序崩溃或系统崩溃。
2 死循环:在编写爬虫程序时,可能会出现死循环的情况。这种情况通常是由于程序中的逻辑错误或循环条件设置错误导致的,如果没有及时发现和修复,程序将一直运行下去,占用系统资源,甚至导致系统崩溃。
3 超时和阻塞:网络爬虫程序需要频繁地请求网络数据,如果程序设计不当,可能会出现超时和阻塞的情况。这种情况通常是由于网络请求过度、线程阻塞等原因导致的,如果没有及时发现和处理,会导致请求失败或程序崩溃。
4 重复请求:在爬虫程序中,可能会出现重复请求的情况,这种情况通常是由于程序中的逻辑错误或数据处理不当导致的。如果没有及时处理,会浪费系统资源,降低程序效率。
为了避免爬虫脑缺陷,编写爬虫程序时需要注意以下几点:
1 设计良好的程序架构,采用模块化的设计思路,降低程序耦合度,便于维护和升级。
2 合理设置请求频率,不要过度请求网络数据,避免被封IP或被服务器屏蔽。
3 采用多线程或异步请求的方式,避免阻塞和超时。
4 对数据进行去重和过滤处理,避免重复请求和数据冗余。
5 定期检查程序,及时发现和修复错误,保证程序稳定运行。
以上就是关于爬虫工程师要学什么技术全部的内容,包括:爬虫工程师要学什么技术、Python中怎么用爬虫爬、后羿采集器数据爬取断啦,重启动如何接下去一页开始,不从头开始等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)