当前位置: 首页 > 科技观察

一个合格的数据分析师分享Python网络爬虫趣闻

时间:2023-03-14 21:44:35 科技观察

一、前言作为一个合格的数据分析师,其完整的技术知识体系必须贯穿数据采集、数据存储、数据抽取、数据分析、数据挖掘、数据可视化等。在此,作为一个初出茅庐的数据小白,我将自己在学习数据科学过程中遇到的一些问题记录下来,以供后续参考,也希望能与各界同学交流,共同进步。前段时间刚学Python网络爬虫,所以这里对网络爬虫做一个总结。2、什么是网络爬虫?1.爬虫场景我们先想象一下通常去天猫商城(PC端)购物的步骤,可能是:打开浏览器==”搜索天猫商城==”点击链接进入天猫商城==”选择想要的产品分类(站内搜索)==》浏览产品(价格、详细参数、评论等)==》点击链接==进入下一个产品页面……如此周而复始。当然,搜索也是爬虫的应用之一。简单的说,网络爬虫就是一种与上述场景类似但又有所不同的程序。2.爬虫的分类(1)分类与关系最常用的爬虫类型有通用爬虫和聚焦爬虫。聚焦爬虫分为浅聚焦和深聚焦。三者的关系如下:(2)通用爬虫和专注爬虫的区别爬虫的区别在于是否对信息进行过滤,保证只爬取与主题相关的网页信息。(3)聚焦爬虫过滤方式浅聚焦爬虫选择与目标主题相匹配的种子URL。例如,如果我们将抓取的信息定义为招聘信息,则可以使用招聘网站(拉勾网、大街网等)的URL作为种子URL。这样可以确保爬取的内容与我们定义的主题一致。深度聚焦爬虫一般有两种,一种针对内容,一种针对URL。其中,页面等内容上的超链接大部分都有锚文本,我们可以根据锚文本进行过滤。3.爬虫原理爬虫一般来说是一种程序,从一个种子URL开始,通过HTTP请求获取页面内容,通过各种技术手段从页面内容中解析出更多的URL,递归请求获取页面。主要原理总结如下图(其中红色部分为重点爬虫相对于一般爬虫所需的额外步骤):4.爬虫应用网络爬虫可以做很多事情,如下所列:搜索引擎收集数据(金融、金融、商品、竞品)等)广告过滤……其实是我们个人的兴趣所在。学习爬虫后,我们可以看看当当网哪些技术书籍卖得比较火(销量、评论等),在线教育网站哪些在线课程比较成功,看双十一天猫活动等,如只要我们对数据感兴趣,一般都可以爬取,但是有些网站比较狡猾,设置了各种防抓取机制。总而言之,网络爬虫可以帮助我们做很多有趣的事情。3.网络爬虫基础我个人建议除了3.3,本章的其他内容可以先粗略看一遍,可以有一点印象。当你完成了一些简单的爬虫之后,或者在写爬虫的过程中遇到了一些问题,你可以回过头来巩固一下。这可能有助于我们进一步了解互联网上的爬虫。1、HTTP协议HTTP协议是爬虫的基础。通过封装TCP/IP协议链路,简化了网络请求的过程,使用户无需关注三向握手、丢包、超时等底层交互。2、作为前端技术的新手,个人感觉入门的话,懂一点HTML和JavaScript就可以实现基本的爬虫项目。HTML主要是辅助我们处理静态页面。事实上,很多数据是无法通过简单的右键查看网页源代码来查看的。但是,它存储在JSON(JavaScript对象表示法)文件中。这时候我们就需要进行抓包分析,详见《5.2 爬取基于Ajax技术网页数据》。3.正则表达式和XPath爬虫必不可少的一步就是解析。正则表达式是文本匹配和抽取的强大工具,被多种语言所支持。XPath是XML路径语言,类似于Windows的文件路径,不同的是XPath应用在网页中,定位我们需要的内容的精确位置。四、网络爬虫常见问题解答1、爬虫工具——pythonPython是一种非常方便的脚本语言,广泛应用于各种爬虫框架中。Python提供了urllib、re、json、pyquery等模块,同时前人用Python造了很多轮子,比如Scrapy框架、PySpider爬虫系统等,所以Python是爬虫的一大利器.注:本章开发环境详述如下系统环境:windows8.1开发语言:Python3.5开发工具:Spyder、Pycharm辅助工具:Chrome浏览器二、编码格式Python3中只有Unicode编码为str,其他gbk、utf-8、gb2312等编码格式都是字节。在编解码过程中,先通过解码方法decode()将字节解码成字符串str,再通过编码方法encode()将字符串str编码成字节。关系如下:实战-爬取当当网爬取网页In[5]:importurllib.request...:data=urllib.request.urlopen("http://www.dangdang.com/")。read()#抓取数据中标签的内容如下:<title>\xb5\xb1\xb5\xb1\xa1\xaa\xcd\xf8\xc9\xcf\xb9\xba\xce\xef\xd6\xd0\xd0\xc4\xa3\xba\xcd\xbc\xca\xe9\xa1\xa2\xc4\xb8\xd3\xa4\xa1\xa2\xc3\xc0\xd7\xb1\xa1\xa2\xbc\xd2\xbe\xd3\xa1\xa2\xca\xfd\xc2\xeb\xa1\xa2\xbc\xd2\xb5\xe7\xa1\xa2\xb7\xfe\xd7\xb0\xa1\xa2\xd0\xac\xb0\xfc\xb5\xc8\xa3\xac\xd5\xfd\xc6\xb7\xb5\xcd\xbc\xdb\xa3\xac\xbb\xf5\xb5\xbd\xb8\xb6\xbf\xee查看编码格式In[5]:importchardet...:chardet.detect(data)Out[5]:{'confidence':0.99,'encoding':'GB2312'}可见抓取的网页是GB2312编码,是国家标准的汉字编码,专门用来表示汉字。DecodingIn[5]:decodeData=data.decode("gbk")#此时bytes已经解码成str,标签内容解码结果如下:<title>当当网—网上商城:图书、母婴、美妆、家居、数码、家电、服装鞋包等,正品低价,货到付款recodedataEncode=decodeData.encode("utf-8","忽略")#重新编码结果<标题>\xe5\xbd\x93\xe5\xbd\x93\xe2\x80\x94\xe7\xbd\x91\xe4\xb8\x8a\xe8\xb4\xad\xe7\x89\xa9\xe4\xb8\xad\xe5\xbf\x83\xef\xbc\x9a\xe5\x9b\xbe\xe4\xb9\xa6\xe3\x80\x81\xe6\xaf\x8d\xe5\xa9\xb4\xe3\x80\x81\xe7\xbe\x8e\xe5\xa6\x86\xe3\x80\x81\xe5\xae\xb6\xe5\xb1\x85\xe3\x80\x81\xe6\x95\xb0\xe7\xa0\x81\xe3\x80\x81\xe5\xae\xb6\xe7\x94\xb5\xe3\x80\x81\xe6\x9c\x8d\xe8\xa3\x85\xe3\x80\x81\xe9\x9e\x8b\xe5\x8c\x85\xe7\xad\x89\xef\xbc\x8c\xe6\xad\xa3\xe5\x93\x81\xe4\xbd\x8e\xe4\xbb\xb7\xef\xbc\x8c\xe8\xb4\xa7\xe5\x88\xb0\xe4\xbb\x98\xe6\xac\xbe3.超时设置允许超时data=urllib.request.urlopen(“http://www.dangdang.com/”,timeout=3).read()线程延迟(秒)importtimetime.sleep(3)4.异常处理每程序必然要处理异常,爬虫也不例外。如果不异常处理可能导致爬虫程序直接崩溃一、网络爬虫中异常处理的种类和关系(一)URLError通常,URLError发生在没有网络连接(没有到特定服务器的路由),或者服务器不存在的情况下.(2)HTTPError首先我们要明白,服务器上的每个HTTP响应对象response都包含一个数字“状态码”,表示HTTP协议返回的响应的状态,即HTTPError。例如,当生成“404NotFound”时,表示“没有找到相应的页面”。可能是网址输入错误,也可能是IP被网站封了。在这种情况下,必须使用代理IP来爬取数据。关于ProxyIP设置我们将在下面讨论。(3)两者的关系是父类和子类的关系,即HTTPError是URLError的子类,HTTPError有异常状态码和异常原因,而URLError没有异常状态码。所以我们在处理的时候不能直接用URLError来代替HTTPError。同时,Python中所有的异常都是基类Exception的成员,所有的异常都继承自这个基类,定义在exceptions模块中。如果要替换,必须判断是否有状态码属性。2.Python中有一套异常处理机制语法(1)try-except语句try:blockexceptExceptionase:blockelse:blocktry语句:捕获异常except语句:处理不同的异常,Exception是异常的类型,在爬虫中常见为上面说了。e:异常信息,后面可以打印出来else:表示如果没有异常发生,try执行完后,else(2)try-except-finally语句try:blockexceptionase:blockfinally:blockiftryisnotcatchederror消息,跳过except语句并改为执行finally语句。其实finally语句无论是否捕获到异常都会被执行,所以一般我们都会把一些释放资源的工作放在这一步,比如关闭文件句柄或者关闭数据库连接。等待。4、自动模拟HTTP请求一般情况下,客户端需要通过HTTP请求与服务器进行通信。常见的HTTP请求包括POST和GET。比如我们打开淘宝网页后HTML加载完毕,浏览器会发送GET请求获取图片等,这样我们就可以看到一个完整的动态页面。如果我们浏览后需要下单,还需要将登录信息传递给服务器。.(1)GET方法向服务器发送数据请求,将请求数据整合到URL中,在URL中可以看到数据。(2)POST是向服务器提交数据的请求,数据放在HTMLHEADER中提交。在安全性方面,POST方式比GET方式更安全。毕竟GET方法是直接将URL中的请求数据以明文形式显示出来的。5、Cookies处理Cookies是一些网站为了识别用户身份和跟踪会话而存储在用户本地终端上的数据(通常是加密的)。6.浏览器伪装(1)原理浏览器伪装是反屏蔽方法之一。简而言之,其原理就是在客户端向服务器发送的请求中加入头信息,告诉服务器“我是浏览器”(2)如何查看客户端信息?通过Chrome浏览器按F12==“SelectNetwork==”刷新点击Name下的任意地址,即可看到请求报文和对应的报文信息。以下是百度搜索简书的请求消息信息。在爬虫中,我们只需要在header中添加User-Agent即可实现浏览器伪装。7.代理服务器(1)原理代理服务器的原理如下图所示,使用代理服务器可以很好的解决IP限制问题。我个人认为IP限制对爬虫影响很大。毕竟我们一般不会花钱去买正规的代理IP。我们通常会使用网络上提供的一些免费代理IP进行爬取,而这些免费IP的产品质量参差不齐,出错在所难免,所以我们在使用前需要测试其效果。(2)实战-代理服务器爬取百度首页importurllib.requestdefuse_proxy(url,proxy_addr,iHeaders,timeoutSec):'''功能:伪装成浏览器,使用代理IP反屏蔽@url:targetURL@proxy_addr:代理IP地址@iHeaders:浏览器头信息@timeoutSec:超时设置(单位:秒)'''proxy=urllib.request.ProxyHandler({"http":proxy_addr})opener=urllib.request.build_opener(proxy,urllib.request.HTTPHandler)urllib.request.install_opener(opener)try:req=urllib.request.Request(url,headers=iHeaders)#伪装成浏览器封装requestdata=urllib.request.urlopen(req).read().decode("utf-8","ignore")exceptExceptionaser:print("抓取过程中出现错误,详细信息如下:")print(er)returndataurl="http://www.baidu.com"proxy_addr="125.94.0.253:8080"iHeaders={"User-Agent":"Mozilla/5.0(WindowsNT6.1;WOW64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/49.0.2623.22Safari/537.36SE2.XMetaSr1.0"}timeoutSec=10data=use_proxy(url,proxy_addr,iHeaders,timeoutSec)print(len(data))8.抓包分析(1)Ajax(异步加载)技术网站中用户需要的数据,如联系人列表,可以从独立于实际获取网页的网站获取由服务器,可以动态简单来说,写入网页就是打开网页,先显示部分内容,然后再慢慢加载其余内容。显然,这样的网页加载速度非常快,因为它不需要一次加载所有内容,但是对于我们的爬虫来说比较麻烦。我们不可能总能爬到我们想要的内容,所以这时候就需要对包进行分析。(2)抓包工具推荐Fiddler和Chrome(3)实战请前往《5.2 爬取基于Ajax技术网页数据》。9、多线程爬虫一般我们的程序都是单线程运行的,但是多线程可以充分利用资源,优化爬虫效率。其实Python中的多线程并行并不是真正的并行,但是多线程还是可以在一定程度上提高爬虫的执行效率。接下来我们对比一下单线程和多线程的时间。(1)实战-爬取豆瓣科幻电影网页'''多线程'''importurllibfrommultiprocessing.dummyimportPoolimporttimedefgetResponse(url):'''获取响应信息'''try:req=urllib.request.Request(url)res=urllib.request.urlopen(req)exceptExceptionaser:print("爬取过程中出现错误,详情如下:")print(er)returnresdefgetURLs():'''获取所有需要爬取的url'''urls=[]foriinrange(0,101,20):#每翻一页,起始值增加20keyword="sciencefiction"keyword=urllib.request.quote(keyword)newpage="https://movie.douban.com/tag/"+keyword+"?start="+str(i)+"&type=T"urls.append(newpage)returnurlsdefsingleTime(urls):'''单进程计时'''timetime1=time.time()foriinurls:print(i)getResponse(i)timetime2=time.time()returnstr(time2-time1)defmultiTime(urls):'''多进程计时'''pool=Pool(processes=4)#开启四个进程timetime3=time.time()pool.map(getResponse,urls)pool.close()pool.join()#等待进程池中的worker进程完成timetime4=time.time()returnstr(time4-time3)if__name__=='__main__':urls=getURLs()singleTimesingleTimes=singleTime(urls)#单线程计时multiTimemultiTimes=multiTime(urls)#多线程计时print('单线程耗时:'+singleTimes+'s')print('多线程耗时:'+multiTimes+'s')(2)结果:单线程耗时:3.850554943084717s多线程耗时:1.3288819789886475s10。数据存储在本地文件(excel、txt)数据库(如MySQL)备注:详见5.111。验证码处理我们在登录过程中经常会遇到验证码问题,需要我们进行处理(1)简单验证码识别使用pytesser识别简单的图形验证码。(2)复杂的验证码识别相对困难。可以调用第三方接口(比如码兔),使用SVM等数据挖掘算法继续下一篇《一名合格的数据分析师分享Python网络爬虫二三事(综合实战案例)》【本文为栏目组织《奇安科技》原创文章,转载请联系原作者微信公众号(bigsec)】点此阅读更多作者好文