爬虫介绍
爬虫定义
爬虫是请求网站并提取自己所需要数据的过程。通过我们的程序,可以代替我们向服务器发送请求,然后进行批量的数据下载。
爬虫基本流程
- 发起请求
通过url向服务器发送requests请求,请求可以包含额外的header信息。 - 获取响应内容
如果服务器正常响应,那么将受到一个response,response即为我们所请求的网页内容,可能包含html\json\二进制数据(图片、视频)等。 - 解析内容
如果是html代码则可以使用网页解析器进行解析;如果是json数据则可以转换成json对象进行解析;如果是二进制数据则可以保存到文件进行进一步的处理。 - 保存数据
可以保存到本地文件,也可以保存到数据库(mysql\redis\mongodb等)。requests请求
当我们通过浏览器向服务器发送requests请求时,这个request包含什么内容?可以通过chrome浏览器的开发人员工具(F12)查看。 - 请求方式
最常用的请求方式包括get请求和post请求。
post请求在开发中最常见的是通过表单进行提交,从用户角度来讲最常见的就是登陆验证。当你需要输入一些信息进行登陆的时候,这次请求就是post请求。
get请求最常见的就是搜索回车之后,信息将以?间隔添加在url后面。类似于https://www.baidu.com/s?wd=python3%20requests
。而且get请求是用来获取数据,是幂等的。
其他还包括put请求(向服务端发送信息从而改变内容)和delete请求(删除资源)。
对于资源的操作,其实都可以通过post/get完成,不需要用到put/delete,实际中put/delete也很少用。 - uri统一资源定位符
一个网址、一个视频、一个图片都可以用uri去定义 - requests headers
请求头,包括这次请求的类型,cookie信息以及浏览器类型等。
请求头在我们进行网页抓取的时候,服务器会通过解析请求头来进行信息的审核,判断请求是否为合法请求。所以当我们通过程序伪装浏览器进行请求的时候可以设置请求头的信息。 - 请求体
post请求会把用户信息包装在form-data里面进行提交,因此相比于get请求,post请求的Headers标签的内容会多出Form Data这个信息包。response
- 响应状态
通过Headers中的General可以看到status code
,使用数字代码表示对于状态,200表示成功,301跳转,404找不到网页,502服务器错误等。 - 响应头
包括内容的类型,cookie信息等。 - 响应体
请求的目的就是为了得到响应体,包括html代码,json及二进制数据等。
二、Ruquest模块
pip install requests
在学习爬虫之前,我们先来了解http定义的与服务器交互的七个主要方法:
方法 | 解释 |
---|---|
requests.request() | 构造一个请求,支持以下各种方法 |
requests.get() | 获取html的主要方法 |
requests.head() | 获取html头部信息的主要方法 |
requests.post() | 向html网页提交post请求的方法 |
requests.put() | 向html网页提交put请求的方法 |
requests.patch() | 向html提交局部修改的请求 |
requests.delete() | 向html提交删除请求 |
import requests
requests.get("http://www.baidu.com")
requests.post("http://www.jd.com")
requests.put("http://www.jd.com")
requests.delete("http://www.jd.com")
get方式:
r=requests.get(url,params,**kwargs)
url: 需要爬取的网站地址。
params: 翻译过来就是参数, url中的额外参数,字典或者字节流格式,可选。
**kwargs : 12个控制访问的参数
**kwargs有以下的参数,对于requests.get,其第一个参数被提出来了。
- params:字典或字节序列, 作为参数增加到url中,使用这个参数可以把一些键值对以?key1=value1&key2=value2的模式增加到url中 例如:
kv = {‘key1: ’ values’, ‘key2’: ‘values’}
r = requests.request(‘GET’, ‘http:www.python123.io/ws’, params=kw)
- data:字典,字节序或文件对象,重点作为向服务器提供或提交资源是提交,,作为request的内容,与params不同的是,data提交的数据并不放在url链接里, 而是放在url链接对应位置的地方作为数据来存储。,它也可以接受一个字符串对象。
- json:json格式的数据, json合适在相关的html,http相关的web开发中非常常见, 也是http最经常使用的数据格式, 他是作为内容部分可以向服务器提交。 例如:
kv = {”key1’: ‘value1’}
r = requests.request(‘POST’, ‘http://python123.io/ws‘, json=kv)
- headers:字典是http的相关语,对应了向某个url访问时所发起的http的头i字段, 可以用这个字段来定义http的访问的http头,可以用来模拟任何我们想模拟的浏览器来对url发起访问。 例子:
hd = {‘user-agent’: ‘Chrome/10’}
r = requests.request(‘POST’, ‘http://python123.io/ws‘, headers=hd)
- cookies:字典或CookieJar,指的是从http中解析cookie
- auth:元组,用来支持http认证功能
- files:字典, 是用来向服务器传输文件时使用的字段。 例子:fs = {‘files’: open(‘data.txt’, ‘rb’)} r = requests.request(‘POST’, ‘http://python123.io/ws‘, files=fs)
- timeout: 用于设定超时时间, 单位为秒,当发起一个get请求时可以设置一个timeout时间, 如果在timeout时间内请求内容没有返回, 将产生一个timeout的异常。
- proxies:字典, 用来设置访问代理服务器。
- allow_redirects: 开关, 表示是否允许对url进行重定向, 默认为True。
- stream: 开关, 指是否对获取内容进行立即下载, 默认为True。
- verify:开关, 用于认证SSL证书, 默认为True。
- cert: 用于设置保存本地SSL证书路径
其中response对象有以下属性:
属性 | 说明 |
---|---|
r.status_code | http请求的返回状态,若为200则表示请求成功。 |
r.text | http响应内容的字符串形式,即返回的页面内容 |
r.encoding | 从http header 中猜测的相应内容编码方式 |
r.apparent_encoding | 从内容中分析出的响应内容编码方式(备选编码方式) |
r.content | http响应内容的二进制形式 |
实例一:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2018/6/13 12:44
# @Author : zhdya
# @File : demon1.py
import requests
paramss = {'key1': "hello", 'key2': "world"}
urll = 'https://www.baidu.com'
result = requests.get(url= urll , params= paramss )
print(result.url)
结果:
https://www.baidu.com/?key1=hello&key2=world
我们也可以直接
requests.get('https://www.baidu.com/?key1=hello&key2=world')
requests库的异常
注意requests库有时会产生异常,比如网络连接错误、http错误异常、重定向异常、请求url超时异常等等。所以我们需要判断r.status_codes是否是200,在这里我们怎么样去捕捉异常呢?
这里我们可以利用 r.raise_for_status() 语句去捕捉异常,该语句在方法内部判断r.status_code是否等于200,如果不等于,则抛出异常。
于是在这里我们有一个爬取网页的通用代码框架:
try:
r=requests.get(url,timeout=30) #请求超时时间为30秒
r.raise_for_status() #如果状态不是200,则引发异常
r.encoding=r.apparent_encoding #配置编码
r.text
except:
return "产生异常"
实例二:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2018/6/13 12:44
# @Author : zhdya
# @File : demon1.py
import requests
urll = "http://www.okay686.cn"
try:
result = requests.get(url=urll, timeout = 3)
result.raise_for_status()
result.apparent_encoding
print(result.text)
except:
print("产生异常")
post方式:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2018/6/13 12:44
# @Author : zhdya
# @File : demon1.py
import requests
paramss = {'key1': "hello" , 'key2':"world"}
result = requests.post("http://httpbin.org/post", data=paramss)
print(result.text)
http://httpbin.org/post是requests提供的官网地址,通过json的方式给大家返回。可以看到我们返回的数据。Post的数据参数是data,都是字典的类型,但是urllib就没法接受字典类型,必须是字符串。
结果:
{"args":{},"data":"","files":{},"form":{"key1":"hello","key2":"world"},"headers":{"Accept":"*/*","Accept-Encoding":"gzip, deflate","Connection":"close","Content-Length":"21","Content-Type":"application/x-www-form-urlencoded","Host":"httpbin.org","User-Agent":"python-requests/2.18.4"},"json":null,"origin":"222.92.90.18","url":"http://httpbin.org/post"}
三、requests模块的使用实例
1、京东商品信息的爬取
不需要对头部做任何修改,即可爬网页:
import requests
url='http://item.jd.com/2967929.html'
try:
r=requests.get(url,timeout=30)
r.raise_for_status()
r.encoding=r.apparent_encoding
print(r.text[:1000]) #部分信息
except:
print("爬取失败")
2、亚马逊商品信息的爬取
该网页中对爬虫进行的爬取做了限制,因此我们需要伪装自己为浏览器发出的请求。
urll = 'https://www.amazon.cn/gp/product/B01M8L5Z3Y'
try:
params = {'user_agent':'Mozilla/5.0'}
r = requests.get(url=urll, headers = params) #改变自己的headers
r.raise_for_status()
r.encoding = r.apparent_encoding
print(r.text[1000:2000]) ##部分信息
except Exception as e:
print("Faild to get the info...")
raise e
3、百度搜索关键字提交
百度的关键字接口: https://www.baidu.com/s?wd=keyword
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2018/6/13 13:27
# @Author : zhdya
# @File : demon2.py
import requests
keywords = input("pls input sth you wanna search: ")
try:
paramas = {'wd': keywords}
r = requests.get('https://www.baidu.com/s', params=paramas)
r.raise_for_status()
r.encoding = r.apparent_encoding
print(r.url)
except Exception as e:
print("Faild to search, the error as follow:")
raise e
输出:
pls input sth you wanna search: python
https://www.baidu.com/s?wd=python
修改为搜索:
keywords = input("pls input sth you wanna search: ")
try:
paramas = {'wd': keywords}
r = requests.get('http://www.baidu.com/s', params=paramas)
r.raise_for_status()
r.encoding = r.apparent_encoding
print(r.text)
except Exception as e:
print("Faild to search, the error as follow:")
raise e
输出了很多主页的源码。。(自己试试吧)
4、网络图片的爬取(可爱的猫咪)
import requests
import os
try:
url = 'https://b-ssl.duitang.com/uploads/item/201508/07/20150807101946_EzSmP.jpeg'
dir = 'D:/pic/'
path = dir + url.split("/")[-1]
if not os.path.exists(dir):
os.mkdir(dir)
if not os.path.exists(path):
r = requests.get(url, timeout = 30)
f = open(path,"wb")
f.write(r.content)
f.close()
print("already download...")
else:
print("Faild to download...")
except Exception as e:
print("Faild to get the info, the error as follow: ")
raise e