这是结合网易云课堂爬虫相关内容的讲解和我自己觉得重要的理解,写的博客,以后我还会分享很多别的专栏,因为感觉这样确实有助于自己的理解,如果能绑上别人,我也很开心。
什么是网络爬虫:
- 通俗理解:爬虫是一个模拟人类请求网站行为的程序。可以自动请求网页、并数据抓取下来,然后使用一定的规则提取有价值的数据。
- 专业介绍:百度百科。
什么是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 requests
kw = {'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 requests
url = "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 requests
url = "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`来实现。示例代码如下:
```python
import requests
url = "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 requests
url = '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)