爬虫
1.爬虫介绍
2.requests模块
一.爬虫介绍
本质:
1.就是向网站发送http请求,就会拿回一些页面/json格式数据(request) 2.处理数据,解析出有用的东西(re,bs4) 3.存储(mysql,文件,cvs,redis,mongodb,es) 4.分析(这个一般有专们的人去做数据分析,我们不需要学)
-- cookie池和代理池
每次发请求时拿随机的cookie和代理ip,每次拿一堆代理ip,ip和地址都不一样,
这就相当于不同机器,好多人往那发请求,我不知道你是机器还是人,这样就不能禁止你爬,所以出现了cookie池和代理池。
-- 正向代理和反向代理
正向代理:代理我自己
反向代理:代理服务器
举例子:
正向代理:比如说你访问谷歌你是访问不了的,需要FQ,就是这里有一台服务器能访问到谷歌,
他去拿到数据,然后我去拿,他把数据给我。
就比如我去买票,但是票没有了,通过黄牛来买,他把票给我
反向代理:谷歌也不可能就一台机器,他可能后面有一千台机器,但是他把我屏蔽掉了,只需要访问他那一个ip地址就可以。
就比如我去租房子,我只要找中介,中介有很多房子,他吧房子给我就好了
爬虫的基本流程:
#1、发起请求 使用http库向目标站点发起请求,即发送一个Request Request包含:请求头、请求体等 #2、获取响应内容 如果服务器能正常响应,则会得到一个Response Response包含:html,json,图片,视频等 #3、解析内容 解析html数据:正则表达式,第三方解析库如Beautifulsoup,pyquery等 解析json数据:json模块 解析二进制数据:以b的方式写入文件 #4、保存数据 数据库 文件
请求与响应:
#http协议:http://www.cnblogs.com/linhaifeng/articles/8243379.html #Request:用户将自己的信息通过浏览器(socket client)发送给服务器(socket server) #Response:服务器接收请求,分析用户发来的请求信息,然后返回数据(返回的数据中可能包含其他链接,如:图片,js,css等) #ps:浏览器在接收Response后,会解析其内容来显示给用户,而爬虫程序在模拟浏览器发送请求然后接收Response后,是要提取其中的有用数据。
Request:
1 #1、请求方式: 2 常用的请求方式:GET,POST 3 其他请求方式:HEAD,PUT,DELETE,OPTHONS 4 5 ``` 6 ps:用浏览器演示get与post的区别,(用登录演示post) 7 8 post与get请求最终都会拼接成这种形式:k1=xxx&k2=yyy&k3=zzz 9 post请求的参数放在请求体内: 10 可用浏览器查看,存放于form data内 11 get请求的参数直接放在url后 12 ``` 13 14 #2、请求url 15 url全称统一资源定位符,如一个网页文档,一张图片 16 一个视频等都可以用url唯一来确定 17 18 ``` 19 url编码 20 https://www.baidu.com/s?wd=图片 21 图片会被编码(看示例代码) 22 ``` 23 24 ``` 25 网页的加载过程是: 26 加载一个网页,通常都是先加载document文档, 27 在解析document文档的时候,遇到链接,则针对超链接发起下载图片的请求 28 ``` 29 30 #3、请求头 31 User-agent:请求头中如果没有user-agent客户端配置, 32 服务端可能将你当做一个非法用户 33 host 34 cookies:cookie用来保存登录信息 35 36 ``` 37 一般做爬虫都会加上请求头 38 ``` 39 40 #4、请求体 41 如果是get方式,请求体没有内容 42 如果是post方式,请求体是format data 43 44 ``` 45 ps: 46 1、登录窗口,文件上传等,信息都会被附加到请求体内 47 2、登录,输入错误的用户名密码,然后提交,就可以看到post,正确登录后页面通常会跳转,无法捕捉到post 48 ```
Response:
#1、响应状态 200:代表成功 301:代表跳转 404:文件不存在 403:权限 502:服务器错误 #2、Respone header set-cookie:可能有多个,是来告诉浏览器,把cookie保存下来 #3、preview就是网页源代码 最主要的部分,包含了请求资源的内容 如网页html,图片 二进制数据等
总结:
#1、总结爬虫流程: 爬取--->解析--->存储 #2、爬虫所需工具: 请求库:requests,selenium 解析库:正则,beautifulsoup,pyquery 存储库:文件,MySQL,Mongodb,Redis #3、爬虫常用框架: scrapy
二.requests模块
请求库之requests库
#介绍:使用requests可以模拟浏览器的请求,比起之前用到的urllib,requests模块的api更加便捷(本质就是封装了urllib3) #注意:requests库发送请求将网页内容下载下来以后,并不会执行js代码,这需要我们自己分析目标站点然后发起新的request请求 #安装:pip3 install requests #各种请求方式:常用的就是requests.get()和requests.post() >>> import requests >>> r = requests.get('https://api.github.com/events') >>> r = requests.post('http://httpbin.org/post', data = {'key':'value'}) >>> r = requests.put('http://httpbin.org/put', data = {'key':'value'}) >>> r = requests.delete('http://httpbin.org/delete') >>> r = requests.head('http://httpbin.org/get') >>> r = requests.options('http://httpbin.org/get') #建议在正式学习requests前,先熟悉下HTTP协议 http://www.cnblogs.com/linhaifeng/p/6266327.html
get携带的参数:
#通常我们在发送请求时都需要带上请求头,请求头是将自身伪装成浏览器的关键,常见的有用的请求头如下 Host Referer #大型网站通常都会根据该参数判断请求的来源 User-Agent #客户端 Cookie #Cookie信息虽然包含在请求头里,但requests模块有单独的参数来处理他,headers={}内就不要放它了
带参数的get请求cookies
#登录github,然后从浏览器中获取cookies,以后就可以直接拿着cookie登录了,无需输入用户名密码 #用户名:egonlin 邮箱378533872@qq.com 密码lhf@123 import requests Cookies={ 'user_session':'wGMHFJKgDcmRIVvcA14_Wrt_3xaUyJNsBnPbYzEL6L0bHcfc', } response=requests.get('https://github.com/settings/emails', cookies=Cookies) #github对请求头没有什么限制,我们无需定制user-agent,对于其他网站可能还需要定制 print('378533872@qq.com' in response.text) #True
基于post
#GET请求 HTTP默认的请求方法就是GET * 没有请求体 * 数据必须在1K之内! * GET请求数据会暴露在浏览器的地址栏中 GET请求常用的操作: 1. 在浏览器的地址栏中直接给出URL,那么就一定是GET请求 2. 点击页面上的超链接也一定是GET请求 3. 提交表单时,表单默认使用GET请求,但可以设置为POST #POST请求 (1). 数据不会出现在地址栏中 (2). 数据的大小没有上限 (3). 有请求体 (4). 请求体中如果存在中文,会使用URL编码! #!!!requests.post()用法与requests.get()完全一致,特殊的是requests.post()有一个data参数,用来存放请求体数据
案例:
抓取百度页面:
1 # requests模块使用,基于urllib 2 # urllib python内置的模块,也是模拟发送http请求的库 3 # 模拟http请求,get,post,put,delete ... 4 5 import requests 6 res = requests.get('https://ww.baidu.com') 7 res.encoding = 'utf-8' # 指定一下编码,不然会乱码显示 8 print(res.text) # text响应的内容 9 # 可以把请求的回来的资源写入文件 10 with open('a.html','w') as f: 11 f.write(res.text)
get请求携带参数:
# get请求携带参数 # 1.携带参数可以直接写在网址后面,但是如果参数太多了就不行了。 # 2.这个时候就需要用到get请求里面自带的参数params,采用key,value的形式来写,网址后面别忘了加/s #这些都是需要你自己去分析页面的,看这个网站需要哪些规则 # 3.但是现在还是爬不了,因为百度有反爬措施,你需要表明你是什么浏览器发出来的 # 4.表明我是用什么浏览器发出来的:User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.70 Safari/537.36 # 5.现在还是不行,因为百度更新了措施,还需要其他的规则了,这里就需要你一个个的去调试了
# get请求携带参数 # 1.携带参数可以直接写在网址后面,但是如果参数太多了就不行了。 # 2.这个时候就需要用到get请求里面自带的参数params,采用key,value的形式来写,网址后面别忘了加/s #这些都是需要你自己去分析页面的,看这个网站需要哪些规则 # 3.但是现在还是爬不了,因为百度有反爬措施,你需要表明你是什么浏览器发出来的 # 4.表明我是用什么浏览器发出来的:User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.70 Safari/537.36 # 5.现在还是不行,因为百度更新了措施,还需要其他的规则了,这里就需要你一个个的去调试了 import requests res = requests.get('https://ww.baidu.com/s', params={'wd':"美女"}, # 请求头的信息 headers={ 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.70 Safari/537.36' }, cookie="这是我的cookie信息" ) res.encoding = 'utf-8' # 指定一下编码,不然会乱码显示 print(res.text) # text响应的内容 # 可以把请求的回来的资源写入文件 with open('a.html','w') as f: f.write(res.text)
post请求:
# post请求 #params是拼在get请求后的 #data是post请求boyd体中的内容 import requests requests.post('http://httpbin.org/post', data={''} )
案例:
模拟登陆华华手机网站:
1 headers = { 2 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.70 Safari/537.36', 3 'Referer':'http://www.aa7a.cn/user.php?&ref=http%3A%2F%2Fwww.aa7a.cn%2F' 4 } 5 6 res = requests.post('http://www.aa7a.cn/user.php', 7 headers=headers, 8 data={ 9 'username': '填你的账号', 10 'password': '填你的密码', 11 'captcha': '23YK', # 验证码 12 'remember': 1, 13 'ref': 'http://www.aa7a.cn/', 14 'act': 'act_login', 15 }, 16 ) 17 # 如果登陆成功,cookie会存在于res对象中 18 cookie = res.cookies.get_dic() 19 # 像首页发送请求 20 res = requests.get('http://www.aa7a.cn/',headers=headers, 21 cookies=cookie, 22 ) 23 # 判断我那个登陆的账号在不在请求内容中,如果在就打印登陆成功 24 if '我的账号' in res.text: 25 print('登陆成功')
案例:爬取梨视频
# 爬取视频 # https://www.pearvideo.com/category_loading.jsp?reqType=5&categoryId=1&start=36&mrd=0.5367939499528871&filterIds=1625830,1625746,1625846,1626092,1626166,1625984,1626194,1625848,1626167,1626163,1626160,1626078,1626155,1626067,1626153 # #https://www.pearvideo.com/category_loading.jsp?reqType=5&categoryId=1&start=0 # start 就是代表从第几个视频开始往下排 # 获取视频 import re import requests res = requests.get('https://www.pearvideo.com/category_loading.jsp?reqType=5&categoryId=1&start=0') # 用正则去匹配 reg_text = ' <a href="(.*?)" class="vervideo-lilink actplay">' # 怎么把.*?那里面的视频地址号全部拿出来 , obj = re.findall(reg_text,res.text) # print(obj) # 然后需要把后面的域名拼上去 for url in obj: url = 'https://www.pearvideo.com/'+url # 拿到页面 res1 = requests.get(url) obj1 = re.findall('srcUrl="(.*?)"',res1.text) print(obj1[0])# 不取0号位就是一个列表,索引0号位就是把里面一个个循环取出来 # 我们需要给拿出来的电影起个名字,可以直接用域名,用切分的方式,遇到第一个斜杠就停止,1就是代表切分一次 # 但是切完以后就是2个了,需要用索引1获取我需要的名字 name = obj1[0].rsplit('/',1)[1] print(name) # 拿过来真正的响应res2,然后一行一行往里面写 res2 = requests.get(obj1[0]) with open(name,'wb') as f: # iter_content获取二进制数据 for line in res2.iter_content(): f.write(line)