这是结合网易云课堂爬虫相关内容的讲解和我自己觉得重要的理解,写的博客,以后我还会分享很多别的专栏,因为感觉这样确实有助于自己的理解,如果能绑上别人,我也很开心。
什么是网络爬虫:
- 通俗理解:爬虫是一个模拟人类请求网站行为的程序。可以自动请求网页、并数据抓取下来,然后使用一定的规则提取有价值的数据。
- 专业介绍:百度百科。
什么是http和https协议:
HTTP协议:全称是HyperText Transfer Protocol,中文意思是超文本传输协议,是一种发布和接收HTML页面的方法。服务器端口号是80端口。 HTTPS协议:是HTTP协议的加密版本,在HTTP下加入了SSL层。服务器端口号是443端口。url详解:
URL是Uniform Resource Locator的简写,统一资源定位符。 一个URL由以下几部分组成:scheme://host:port/path/?query-string=xxx#anchor
- scheme:代表的是访问的协议,一般为
http或者https以及ftp等。 - host:主机名,域名,比如
www.baidu.com。 - port:端口号。当你访问一个网站的时候,浏览器默认使用80端口。
- path:查找路径。比如:
www.jianshu.com/trending/now,后面的trending/now就是path。 - query-string:查询字符串,比如:
www.baidu.com/s?wd=python,后面的wd=python就是查询字符串。 - anchor:锚点,后台一般不用管,前端用来做页面定位的。
在浏览器中请求一个url,浏览器会对这个url进行一个编码。除英文字母,数字和部分符号外,其他的全部使用百分号+十六进制码值进行编码。
常用的请求方法:
在Http协议中,定义了八种请求方法。这里介绍两种常用的请求方法,分别是get请求和post请求。
get请求:一般情况下,只从服务器获取数据下来,并不会对服务器资源产生任何影响的时候会使用get请求。post请求:向服务器发送数据(登录)、上传文件等,会对服务器资源产生影响的时候会使用post请求。 以上是在网站开发中常用的两种方法。并且一般情况下都会遵循使用的原则。但是有的网站和服务器为了做反爬虫机制,也经常会不按常理出牌,有可能一个应该使用get方法的请求就一定要改成post请求,这个要视情况而定。请求头常见参数:
在
http协议中,向服务器发送一个请求,数据分为三部分,第一个是把数据放在url中,第二个是把数据放在body中(在post请求中),第三个就是把数据放在head中。这里介绍在网络爬虫中经常会用到的一些请求头参数:User-Agent:浏览器名称。这个在网络爬虫中经常会被使用到。请求一个网页的时候,服务器通过这个参数就可以知道这个请求是由哪种浏览器发送的。如果我们是通过爬虫发送请求,那么我们的User-Agent就是Python,这对于那些有反爬虫机制的网站来说,可以轻易的判断你这个请求是爬虫。因此我们要经常设置这个值为一些浏览器的值,来伪装我们的爬虫。Referer:表明当前这个请求是从哪个url过来的。这个一般也可以用来做反爬虫技术。如果不是从指定页面过来的,那么就不做相关的响应。Cookie:http协议是无状态的。也就是同一个人发送了两次请求,服务器没有能力知道这两个请求是否来自同一个人。因此这时候就用cookie来做标识。一般如果想要做登录后才能访问的网站,那么就需要发送cookie信息了。(可以请求cookies)常见响应状态码:
200:请求正常,服务器正常的返回数据。301:永久重定向。比如在访问www.jingdong.com的时候会重定向到www.jd.com。302:临时重定向。比如在访问一个需要登录的页面的时候,而此时没有登录,那么就会重定向到登录页面。400:请求的url在服务器上找不到。换句话说就是请求url错误。403:服务器拒绝访问,权限不够。500:服务器内部错误。可能是服务器出现bug了。
urllib库
urllib库是Python中一个最基本的网络请求库。可以模拟浏览器的行为,向指定的服务器发送一个请求,并可以保存服务器返回的数据。现在没啥用了,所以不介绍了。
ProxyHandler处理器(代理设置)
很多网站会检测某一段时间某个IP的访问次数(通过流量统计,系统日志等),如果访问次数多的不像正常人,它会禁止这个IP的访问。
所以我们可以设置一些代理服务器,每隔一段时间换一个代理,就算IP被禁止,依然可以换个IP继续爬取。
urllib中通过ProxyHandler来设置使用代理服务器,下面代码说明如何使用自定义opener来使用代理:
from urllib import request# 这个是没有使用代理的# resp = request.urlopen('http://httpbin.org/get')# print(resp.read().decode("utf-8"))# 这个是使用了代理的handler = request.ProxyHandler({"http":"218.66.161.88:31769"})opener = request.build_opener(handler)req = request.Request("http://httpbin.org/ip")resp = opener.open(req)print(resp.read())
常用的代理有:
- 西刺免费代理IP:http://www.xicidaili.com/
- 快代理:http://www.kuaidaili.com/
- 代理云:http://www.dailiyun.com/
什么是cookie:
在网站中,http请求是无状态的。也就是说即使第一次和服务器连接后并且登录成功后,第二次请求服务器依然不能知道当前请求是哪个用户。cookie的出现就是为了解决这个问题,第一次登录后服务器返回一些数据(cookie)给浏览器,然后浏览器保存在本地,当该用户发送第二次请求的时候,就会自动的把上次请求存储的cookie数据自动的携带给服务器,服务器通过浏览器携带的数据就能判断当前用户是哪个了。cookie存储的数据量有限,不同的浏览器有不同的存储大小,但一般不超过4KB。因此使用cookie只能存储一些小量的数据。
requests库
虽然Python的标准库中 urllib模块已经包含了平常我们使用的大多数功能,但是它的 API 使用起来让人感觉不太好,而 Requests宣传是 “HTTP for Humans”,说明使用更简洁方便。
安装和文档地址:
利用pip可以非常方便的安装:
pip install requests
中文文档:http://docs.python-requests.org/zh_CN/latest/index.html
发送GET请求:
最简单的发送
get请求就是通过requests.get来调用:response = requests.get("http://www.baidu.com/")
添加headers和查询参数:
如果想添加 headers,可以传入headers参数来增加请求头中的headers信息。如果要将参数放在url中传递,可以利用 params 参数。相关示例代码如下:import requestskw = {'wd':'中国'}headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"}# params 接收一个字典或者字符串的查询参数,字典类型自动转换为url编码,不需要urlencode()response = requests.get("http://www.baidu.com/s", params = kw, headers = headers)# 查看响应内容,response.text 返回的是Unicode格式的数据print(response.text)# 查看响应内容,response.content返回的字节流数据print(response.content)# 查看完整url地址print(response.url)# 查看响应头部字符编码print(response.encoding)# 查看响应码print(response.status_code)
发送POST请求:
最基本的POST请求可以使用
post方法:response = requests.post("http://www.baidu.com/",data=data)
传入data数据:
这时候就不要再使用urlencode进行编码了,直接传入一个字典进去就可以了。比如请求拉勾网的数据的代码:import requestsurl = "https://www.lagou.com/jobs/positionAjax.json?city=%E6%B7%B1%E5%9C%B3&needAddtionalResult=false&isSchoolJob=0"headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36','Referer': 'https://www.lagou.com/jobs/list_python?labelWords=&fromSearch=true&suginput='}data = {'first': 'true','pn': 1,'kd': 'python'}resp = requests.post(url,headers=headers,data=data)# 如果是json数据,直接可以调用json方法print(resp.json())
使用代理:
使用
requests添加代理也非常简单,只要在请求的方法中(比如get或者post)传递proxies参数就可以了。示例代码如下:import requestsurl = "http://httpbin.org/get"headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36',}proxy = {'http': '171.14.209.180:27829'}resp = requests.get(url,headers=headers,proxies=proxy)with open('xx.html','w',encoding='utf-8') as fp:fp.write(resp.text)
cookie:
如果在一个响应中包含了
cookie,那么可以利用cookies属性拿到这个返回的cookie值: ```python import requests url = “http://www.renren.com/PLogin.do“ data = {“email”:”970138074@qq.com”,’password’:”pythonspider”} resp = requests.get(‘http://www.baidu.com/‘) print(resp.cookies) print(resp.cookies.get_dict())
如何使用cookies
import requests url = ‘https://movie.douban.com/‘ r = requests.get(url)
RequestsCookieJar转换字典
cookies_dict = requests.utils.dict_from_cookiejar(mycookies)
写入文件
f = open(‘cookies.txt’, ‘w’, encoding=’utf-8’) f.write(str(cookies_dict)) f.close()
读取文件
f = open(‘cookies.txt’, ‘r’) dict_value = f.read() f.close()
eval(dict_value)将字符串转换字典
print(eval(dict_value)) r = requests.get(url, cookies=eval(dict_value)) print(r.status_code)
简单的方法得到cookies
<a name="78GyY"></a>### session:之前使用`urllib`库,是可以使用`opener`发送多个请求,多个请求之间是可以共享`cookie`的。那么如果使用`requests`,也要达到共享`cookie`的目的,那么可以使用`requests`库给我们提供的`session`对象。注意,这里的`session`不是web开发中的那个session,这个地方只是一个会话的对象而已。还是以登录人人网为例,使用`requests`来实现。示例代码如下:```pythonimport requestsurl = "http://www.renren.com/PLogin.do"data = {"email":"970138074@qq.com",'password':"pythonspider"}headers = {'User-Agent': "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36"}# 登录session = requests.session()session.post(url,data=data,headers=headers)# 访问大鹏个人中心resp = session.get('http://www.renren.com/880151247/profile')print(resp.text)
处理不信任的SSL证书:
对于那些已经被信任的SSL整数的网站,比如https://www.baidu.com/,那么使用requests直接就可以正常的返回响应。示例代码如下:
resp = requests.get('http://www.12306.cn/mormhweb/',verify=False)print(resp.content.decode('utf-8'))
超时设置:
可以设置等待时长,时间超过就产生异常。requests.get(url,timeout = 0.1)
下载与上传
import requestsurl = 'https://www.python.org/static/img/python-logo.png'r = requests.get(url)f = open('python.jpg', 'wb')# r.content获取响应内容(字节流)f.write(r.content)f.close()##上传url = 'https://weibo.cn/mblog/sendmblog?rl=0&st=bd6702'cookies = {'xxx': 'xxx'}files = {'content': (None, 'Python爬虫'),'pic': ('pic', open('test.png', 'rb'), 'image/png'),'visible': (None, '0')}r = requests.post(url, files=files, cookies=cookies)print(r.status_code)
