这是结合网易云课堂爬虫相关内容的讲解和我自己觉得重要的理解,写的博客,以后我还会分享很多别的专栏,因为感觉这样确实有助于自己的理解,如果能绑上别人,我也很开心。


什么是网络爬虫:

  1. 通俗理解:爬虫是一个模拟人类请求网站行为的程序。可以自动请求网页、并数据抓取下来,然后使用一定的规则提取有价值的数据。
  2. 专业介绍:百度百科

    什么是http和https协议:

    HTTP协议:全称是HyperText Transfer Protocol,中文意思是超文本传输协议,是一种发布和接收HTML页面的方法。服务器端口号是80端口。 HTTPS协议:是HTTP协议的加密版本,在HTTP下加入了SSL层。服务器端口号是443端口。

    url详解:

    URLUniform Resource Locator的简写,统一资源定位符。 一个URL由以下几部分组成:
    1. 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请求。

  1. get请求:一般情况下,只从服务器获取数据下来,并不会对服务器资源产生任何影响的时候会使用get请求。
  2. post请求:向服务器发送数据(登录)、上传文件等,会对服务器资源产生影响的时候会使用post请求。 以上是在网站开发中常用的两种方法。并且一般情况下都会遵循使用的原则。但是有的网站和服务器为了做反爬虫机制,也经常会不按常理出牌,有可能一个应该使用get方法的请求就一定要改成post请求,这个要视情况而定。

    请求头常见参数:

    http协议中,向服务器发送一个请求,数据分为三部分,第一个是把数据放在url中,第二个是把数据放在body中(在post请求中),第三个就是把数据放在head中。这里介绍在网络爬虫中经常会用到的一些请求头参数:

  3. User-Agent:浏览器名称。这个在网络爬虫中经常会被使用到。请求一个网页的时候,服务器通过这个参数就可以知道这个请求是由哪种浏览器发送的。如果我们是通过爬虫发送请求,那么我们的User-Agent就是Python,这对于那些有反爬虫机制的网站来说,可以轻易的判断你这个请求是爬虫。因此我们要经常设置这个值为一些浏览器的值,来伪装我们的爬虫。

  4. Referer:表明当前这个请求是从哪个url过来的。这个一般也可以用来做反爬虫技术。如果不是从指定页面过来的,那么就不做相关的响应。
  5. Cookiehttp协议是无状态的。也就是同一个人发送了两次请求,服务器没有能力知道这两个请求是否来自同一个人。因此这时候就用cookie来做标识。一般如果想要做登录后才能访问的网站,那么就需要发送cookie信息了。(可以请求cookies)

    常见响应状态码:

  6. 200:请求正常,服务器正常的返回数据。

  7. 301:永久重定向。比如在访问www.jingdong.com的时候会重定向到www.jd.com
  8. 302:临时重定向。比如在访问一个需要登录的页面的时候,而此时没有登录,那么就会重定向到登录页面。
  9. 400:请求的url在服务器上找不到。换句话说就是请求url错误。
  10. 403:服务器拒绝访问,权限不够。
  11. 500:服务器内部错误。可能是服务器出现bug了。

urllib库

urllib库是Python中一个最基本的网络请求库。可以模拟浏览器的行为,向指定的服务器发送一个请求,并可以保存服务器返回的数据。现在没啥用了,所以不介绍了。

ProxyHandler处理器(代理设置)

很多网站会检测某一段时间某个IP的访问次数(通过流量统计,系统日志等),如果访问次数多的不像正常人,它会禁止这个IP的访问。
所以我们可以设置一些代理服务器,每隔一段时间换一个代理,就算IP被禁止,依然可以换个IP继续爬取。
urllib中通过ProxyHandler来设置使用代理服务器,下面代码说明如何使用自定义opener来使用代理:

  1. from urllib import request
  2. # 这个是没有使用代理的
  3. # resp = request.urlopen('http://httpbin.org/get')
  4. # print(resp.read().decode("utf-8"))
  5. # 这个是使用了代理的
  6. handler = request.ProxyHandler({"http":"218.66.161.88:31769"})
  7. opener = request.build_opener(handler)
  8. req = request.Request("http://httpbin.org/ip")
  9. resp = opener.open(req)
  10. 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可以非常方便的安装:

  1. pip install requests

中文文档:http://docs.python-requests.org/zh_CN/latest/index.html

发送GET请求:

  1. 最简单的发送get请求就是通过requests.get来调用:

    1. response = requests.get("http://www.baidu.com/")
  2. 添加headers和查询参数:
    如果想添加 headers,可以传入headers参数来增加请求头中的headers信息。如果要将参数放在url中传递,可以利用 params 参数。相关示例代码如下:

    1. import requests
    2. kw = {'wd':'中国'}
    3. 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"}
    4. # params 接收一个字典或者字符串的查询参数,字典类型自动转换为url编码,不需要urlencode()
    5. response = requests.get("http://www.baidu.com/s", params = kw, headers = headers)
    6. # 查看响应内容,response.text 返回的是Unicode格式的数据
    7. print(response.text)
    8. # 查看响应内容,response.content返回的字节流数据
    9. print(response.content)
    10. # 查看完整url地址
    11. print(response.url)
    12. # 查看响应头部字符编码
    13. print(response.encoding)
    14. # 查看响应码
    15. print(response.status_code)

    发送POST请求:

  3. 最基本的POST请求可以使用post方法:

    1. response = requests.post("http://www.baidu.com/",data=data)
  4. 传入data数据:
    这时候就不要再使用urlencode进行编码了,直接传入一个字典进去就可以了。比如请求拉勾网的数据的代码:

    1. import requests
    2. url = "https://www.lagou.com/jobs/positionAjax.json?city=%E6%B7%B1%E5%9C%B3&needAddtionalResult=false&isSchoolJob=0"
    3. headers = {
    4. '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',
    5. 'Referer': 'https://www.lagou.com/jobs/list_python?labelWords=&fromSearch=true&suginput='
    6. }
    7. data = {
    8. 'first': 'true',
    9. 'pn': 1,
    10. 'kd': 'python'
    11. }
    12. resp = requests.post(url,headers=headers,data=data)
    13. # 如果是json数据,直接可以调用json方法
    14. print(resp.json())

    使用代理:

    使用requests添加代理也非常简单,只要在请求的方法中(比如get或者post)传递proxies参数就可以了。示例代码如下:

    1. import requests
    2. url = "http://httpbin.org/get"
    3. headers = {
    4. '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',
    5. }
    6. proxy = {
    7. 'http': '171.14.209.180:27829'
    8. }
    9. resp = requests.get(url,headers=headers,proxies=proxy)
    10. with open('xx.html','w',encoding='utf-8') as fp:
    11. 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

  1. <a name="78GyY"></a>
  2. ### session:
  3. 之前使用`urllib`库,是可以使用`opener`发送多个请求,多个请求之间是可以共享`cookie`的。那么如果使用`requests`,也要达到共享`cookie`的目的,那么可以使用`requests`库给我们提供的`session`对象。注意,这里的`session`不是web开发中的那个session,这个地方只是一个会话的对象而已。还是以登录人人网为例,使用`requests`来实现。示例代码如下:
  4. ```python
  5. import requests
  6. url = "http://www.renren.com/PLogin.do"
  7. data = {"email":"970138074@qq.com",'password':"pythonspider"}
  8. headers = {
  9. '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"
  10. }
  11. # 登录
  12. session = requests.session()
  13. session.post(url,data=data,headers=headers)
  14. # 访问大鹏个人中心
  15. resp = session.get('http://www.renren.com/880151247/profile')
  16. print(resp.text)

处理不信任的SSL证书:

对于那些已经被信任的SSL整数的网站,比如https://www.baidu.com/,那么使用requests直接就可以正常的返回响应。示例代码如下:

  1. resp = requests.get('http://www.12306.cn/mormhweb/',verify=False)
  2. print(resp.content.decode('utf-8'))

超时设置:

可以设置等待时长,时间超过就产生异常。requests.get(url,timeout = 0.1)

下载与上传

  1. import requests
  2. url = 'https://www.python.org/static/img/python-logo.png'
  3. r = requests.get(url)
  4. f = open('python.jpg', 'wb')
  5. # r.content获取响应内容(字节流)
  6. f.write(r.content)
  7. f.close()
  8. ##上传
  9. url = 'https://weibo.cn/mblog/sendmblog?rl=0&st=bd6702'
  10. cookies = {'xxx': 'xxx'}
  11. files = {'content': (None, 'Python爬虫'),
  12. 'pic': ('pic', open('test.png', 'rb'), 'image/png'),
  13. 'visible': (None, '0')}
  14. r = requests.post(url, files=files, cookies=cookies)
  15. print(r.status_code)