什么是爬虫|Python爬虫的原理是什么?,这些代码被浏览器解析和渲染,将五颜六色的网页呈现在我们眼前;1、什么是爬虫?如果我们把互联网比作一张大蜘蛛网,数据存储在蜘蛛网的每个节点中,而爬虫就是一只小蜘蛛,它沿着网络抓取自己的猎物(数据)。Request,获取资源后分析提取有用数据的程序;从技术角度,它通过程序模拟浏览器请求站点的行为,将站点返回的HTML代码/JSON数据/二进制数据(图片、视频)抓取到本地,然后提取你需要的数据,存储并使用它;2、爬虫的基本流程:用户获取网络数据的方式:方法一:浏览器提交请求--->下载网页代码--->解析成页面方法二:模拟浏览器发送请求(获取网页代码)->提取有用数据->存储在数据库或文件中。爬虫需要做的是方法2;1、发起请求使用http库向目标站点发起请求,即发送一个RequestRequest,包含:请求头、请求体等Request模块的缺陷:无法执行JS、CSS代码2、获取响应内容如果服务器能正常响应,会得到一个ResponseResponse,包含:html、json、图片、视频等。3.解析内容解析html数据:正则表达式(RE模块),第三方解析库如Beautifulsoup、pyquery、etc.解析json数据:json模块解析二进制数据:以wb形式写入文件4.保存数据数据库(MySQL、Mongdb、Redis)文件3.http协议请求和响应请求:用户将自己的信息发送给服务器(socket服务器)通过浏览器(socket客户端)响应:服务器接收到请求,解析用户发送的请求信息,然后返回数据(返回的数据可能包含其他链接,如:图片、js、css、等)ps:眉毛后er收到Response,解析其内容显示给用户,爬虫程序模拟浏览器发送请求后提取有用数据,然后接收Response。4.request1,请求方式:常见的请求方式:GET/POST2,请求的URLurl全局统一资源定位符,用于定义互联网上唯一的资源例如:a通过url编码https://www.baidu.com/s?wd=pictures可以唯一确定一张图片,一个文件,或者一个视频,并对图片进行编码(见示例代码)一个网页的加载过程是:load一个网页,通常先加载文档文件。在解析文档文件时,如果遇到链接,则对该超链接发起图片下载请求。3、请求头User-agent:如果请求头中没有user-agent客户端配置,服务器可能会认为你是非法用户主机;cookies:cookies用于保存登录信息注意:一般爬虫会在requestheader请求头中加入需要注意的参数:(1)Referrer:访问源来自哪里(一些大型网站,会使用Referrer做反-leechingstrategy;所有爬虫也要注意模拟)(2)User-Agent:访问的浏览器(添加它,否则会被认为是爬虫程序)(3)cookie:注意携带请求头4,请求体request如果body是get方法,则请求体没有内容(get请求的请求体放在url后面的参数中,可以直接看到)如果是post方法,则请求体isformatdataps:1.登录窗口,文件上传等,信息会附在requestbody2.登录,输入错误的用户名和密码,然后提交,就可以看到帖子了。正确登录后,页面通常会跳转,无法抓取帖子。5、响应Response1,响应状态码200:代表成功 301:代表跳转 404:文件不存在 403:无权限访问 502:ServerError2.ResponeheaderResponseheader需要注意的参数:(1)Set-Cookie:BDSVRTM=0;path=/:可能不止一个,告诉浏览器保存cookie(2)Content-Location:服务器响应头中包含Location返回给浏览器后,浏览器会重新访问另一个页面3.预览是网页源码JSO数据,如网页html、图片二进制数据等六、总结1、爬虫过程总结:抓取--->分析--->存储2、爬虫需要的工具:请求库:requests、selenium(可以驱动浏览器解析渲染CSS和JS,但有性能劣势(有用和无用的网页都会被加载);)解析库:regular、beautifulsoup、pyquery存储库:file、MySQL、Mongodb,Redis3,爬到小花。最后再给大家送点福利。基础版:importreimportrequestsrespose\=requests.get('http://www.xiaohuar.com/v/')#print(respose.status\_code)#响应状态码#print(respose.content)#返回字节information#print(respose.text)#返回文本内容urls=re.findall(r'class="items".\*?href="(.\*?)"',respose.text,re.S)#re.S将文本信息转换成1行匹配url=urls\[5\]result\=requests.get(url)mp4\_url\=re.findall(r'id="media".\*?src="(.\*?)"',result.text,re.S)\[0\]video\=requests.get(mp4\_url)withopen('D:\\\\a.mp4','wb')asf:f.write(video.content)查看代码函数封装版本importreimportrequestsimporthashlibimporttime#respose=requests.get('http://www.xiaohuar.com/v/')##print(respose.status\_code)#响应状态码##print(respose.content)#返回字节信息##print(respose.text)#返回文本内容#urls=re.findall(r'class="items".\*?href="(.\*?)"',respose.text,re.S)#re.S将文本信息转换成一行匹配#url=urls\[5\]#result=requests.get(url)#mp4\_url=re.findall(r'id="media".\*?src="(.\*?)"',result.text,re.S)\[0\]##video=requests.get(mp4\_url)##withopen('D:\\\\a.mp4','wb')asf:#f.write(video.content)#defget\_index(url):respose\=requests.get(url)如果respose.status\_code==200:returnrespose.textdefparse\_index(res):urls\=re.findall(r'class="items".\*?href="(.\*?)"',res,re.S)#re.S将文本信息转换为1行匹配returnurlsdefget\_detail(urls):forurlinurls:ifnoturl.startswith('http'):url\='http://www.xiaohuar.com%s'%urlresult\=requests.get(url)ifresult.status\_code==200:mp4\_url\_list\=re.findall(r'id="media".\*?src="(.\*?)"',result.text,re.S)如果mp4\_url\_list:mp4\_url\=mp4\_url\_list\[0\]print(mp4\_url)#save(mp4\_url)defsave(url):video\=requests.get(url)ifvideo.status\_code==200:m\=hashlib.md5()m.updata(url.encode('utf-8'))m.updata(str(time.time()).encode('utf-8'))文件名\=r'%s.mp4'%m.hexdigest()文件路径\=r'D:\\\\%s'%filenamewithopen(filepath,'wb')asf:f.write(video.content)defmain():foriinrange(5):res1\=get\_index('http://www.xiaohuar.com/list-3-%s.html'%i)res2\=parse\_index(res1)get\_detail(res2)if\_\_name\_\_=='\_\_main\_\_':main()查看代码并发版本(如果总共需要爬取30个视频,就开30个threads来做,用的时间是最慢的耗时)importreimportrequestsimporthashlibimporttimefromconcurrent.futuresimportThreadPoolExecutorp\=ThreadPoolExecutor(30)#创建一个30个线程的进程池;defget\_index(url):响应\=请求。get(url)如果响应。status\_code==200:返回respose。textdefparse\_index(res):res\=res.result()#过程执行后得到1个对象urls=re.findall(r'class="items".\*?href="(.\*?)"',res,re.S)#re.S将文本信息转换为匹配urlinurls的行:p.submit(get\_detail(url))#获取详情页提交给线程pooldefget\_detail(url):#如果没有只下载1个视频url.startswith('http'):url\='http://www.xiaohuar.com%s'%urlresult\=requests.get(url)如果result.status\_code==200:mp4\_url\_list\=re.findall(r'id="media".\*?src="(.\*?)"',result.text,re.S)ifmp4\_url\_list:mp4\_url\=mp4\_url\_list\[0\]print(mp4\_url)#save(mp4\_url)defsave(url):video\=请求。get(url)ifvideo.status\_code==200:m\=hashlib.md5()m.updata(url.encode('utf-8'))m.updata(str(time.time()).encode('utf-8'))文件名\=r'%s.mp4'%m.hexdigest()文件路径\=r'D:\\\\%s'%文件名withopen(filepath,'wb')作为f:f。写e(video.content)defmain():foriinrange(5):p.submit(get\_index,'http://www.xiaohuar.com/list-3-%s.html'%i).add\_done\_callback(parse\_index)#1。将爬取首页(get\_index)的任务异步提交给线程池#2。get\_index任务执行后,会通过回调add\_done\_callback()通知主线程任务完成;#2。传递get\_index的执行结果(注意线程执行结果是一个对象,调用res=res.result()方法得到真正的执行结果),作为参数传递给parse\_index#3。执行parse\_index任务后,#4。通过循环,再次将get\_detail()任务提交给线程池执行if\_\_name\_\_=='\_\_main\_\_':main()查看代码涉及知识:multi-线程和多进程计算密集型任务:使用多进程,因为Python有GIL,多进程可以发挥CPU多核的优势;IO密集型任务:使用多线程,做IO切换节省任务执行时间(并发)线程池不管怎样,非常感谢你阅读我的文章!有问题可以后台私信我,我会一一解答!
