一, request 入门
之前写过一个 urllib 的爬虫方法, 这个库是 python 内建的, 从那篇文章也可以看到, 使用起来很繁琐. 现在更流行的一个爬虫库就是 requests, 他是基于 urllib3 封装的, 也就是将之前比较繁琐的步骤封装到一块, 更适合人来使用.
该库中主要有 7 个方法: request() get() head() post() put() patch() delete() 他们的作用也就是他们的字面意思(例如: get 获取网页信息, post 提交信息等等), 具体的可以自行查询.
下面先从最简单的使用开始, 尽可能的用例子展示他都可以干什么.
- import requests
- r = requests.get("https://www.icourse163.org/home.htm?userId=1021614219#/home/course") # get 方法, 从网页上获取信息
- r.status_code # http 请求的返回状态, 为 200 时表示正常访问
- print(r.encoding) # 从 HTTPheader 中猜测的响应内容编码方式
- print(r.apparent_encoding) # 从内容分析出响应内容编码方式(备选编码方式)
上面使用 get 方法就已经得到了网页信息, 返回值时 200.r 字母代表着 response, 也就是访问网页的响应. 网页内的信息可能会有汉字等等, 为了方便以后使用, 在开始就先说明一下这个, encoding 和 apparent_encoding 在上面解释了, 最后是为了使用一个可以把网页正确解析的编码格式.
一般来说, 可以使用 r.encoding = 'utf-8'或者 r.encoding = r.apparent_encoding.
- # 已经访问到了网页, 那么就要看一下提取到的内容
- r.text # http 响应内容的字符串形式, url 对应的页面内容
- r.headers # 返回响应的头部信息
- r.content # http 响应内容的二进制形式
- r.JSON # 返回 JSON 格式, 需要提前导入 JSON 包
其中二进制格式, 可以方便的存储一些图片格式等等的数据, 例如需要下载一个照片, 可以使用'wb'格式写到文件当中, 当然也可以直接使用库中的方法.
二, 异常处理
在我们爬取一些网页的时候, 经常会遇到一系列的问题, 访问不到页面, 禁止访问之类的, 或者一些自身代码的一些问题. 如果代码量很多, 或者具体一点, 比如正在从网站爬取一些照片. 当跑到其中一张图片时没有正常的访问到, 那么整个程序就卡在这里了. 后续的照片也就无法爬取了. 这当然不是我们想要的, 因此就需要一些对异常的处理, 让他出现异常时, 继续执行后续的程序. 异常捕获在 python 的基础里面已经有了, 就是用那个在这里应用一下.
- import requests
- from requests.exceptions import ReadTimeout, ConnectionError, RequestException
- try:
- response = requests.get("http://httpbin.org/get", timeout = 0.5)
- print(response.status_code)
- except ReadTimeout:
- print('Timeout')
- except ConnectionError:
- print('Connection error')
- except RequestException:
- print('Error')
如果是刚接触的人可能看到这么多长串的字符有些记不清, 其实也可以先不去管他是什么样的异常, 只要是异常就反馈回来.
response.raise_for_status() 这个方法可以捕获异常, 使得出现异常时就会跳到 except 中执行, 而不影响整体进程. 下面是一个通用的格式来捕获异常.
- import requests
- def gethtmlText(url):
- try:
- r = requests.get(url)
- r.raise_for_status() # 如果状态不是 200, 引发 HTTPError 异常
- r.encoding = r.apparent_encoding # 不论 headers 中是否要求编码格式, 都从内容中找到实际编码格式, 确保顺利解码
- return r.text
- except:
- return '产生异常'
- if __name__ == "__main__":
- url = "http://baidu.com"
- print(getHtmlText(url))
三, 插一个小栗子
爬取京东上面商品的页面. 理一下思路:
首先要导入网络请求的包 (requests)--> 通过 get 方法访问网页 -->捕获一下异常看看是否正常访问到页面 -->如果返回 200, 确定编码格式 -->通过 response.text 查看一下得到的内容是不是想要的.
- import requests
- url = "https://item.jd.com/8578888.html"
- try:
- r = requests.get(url)
- r.raise_for_status()
- r.encoding = r.apparent_encoding
- print(r.text[:500]) # 由于网页内容比较多,[:500] 表示只看其从 0 到 500 个字节的内容
- except:
- print("爬取失败")
四, 模拟浏览器
上面访问的网站并没有什么防护, 但是现在越来越多的网站都是有各种各样的反爬虫机制, 其中一种简单的方法就是通过发送请求时头文件中的内容来判断. 通过 response.headers 可以找到访问时候的 User-Agent 为 requests, 也就是告诉网站是通过爬虫来访问的. 这么明显, 当然有些网站会阻止访问. 这时候有一个办法, 就是用一个浏览器来模拟一下, 替换掉 User-Agent 中的内容. 网上搜会有很多, 或者直接从你电脑上的浏览器中检查, 来查看你的浏览器在访问网页时显示的 User-Agent 是什么样的.
通过 headers, 传入一个字典, 例如:{"User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) ApplewebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36 OPR/26.0.1656.60"}
其实, 如果还不放心的话, 可以搜一些 User-Agent, 每次通过随机抽取其中的一个来访问网页, 来避免被网站发现.
下面套用上面给出的框架来写这个爬虫:
- # 模拟浏览器爬取信息
- import requests
- url = "https://www.amazon.cn/dp/B074BNFY1H/ref=cngwdyfloorv2_recs_0?pf_rd_p=d0690322-dfc8-4e93-ac2c-8e2eeacbc49e&pf_rd_s=desktop-2&pf_rd_t=36701&pf_rd_i=desktop&pf_rd_m=A1AJ19PSB66TGU&pf_rd_r=2JDNVB7YD5ZF07YQSRQ6&pf_rd_r=2JDNVB7YD5ZF07YQSRQ6&pf_rd_p=d0690322-dfc8-4e93-ac2c-8e2eeacbc49e"
- try:
- headers = {"User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36 OPR/26.0.1656.60"}
- r = requests.get(url, headers = headers)
- print(r.request.headers) # 起初发现 503 错误, 因为亚马逊会限制爬虫, 当使用爬虫时, 会在头部显示 request 代理. 因此用一个新的 user-agent 代替原来的
- r.raise_for_status()
- r.encoding = r.apparent_encoding
- print(r.text[:500])
- except:
- print("爬取失败")
五, 超时设置
- # 当访问长时间未响应时就不再等待, 因为毕竟爬虫时为了提高效率
- import requests
- from requests.exceptions import ReadTimeout
- try:
- response = requests.get("http://httpbin.org/get", timeout = 0.5)
- response.raise_for_status()
- except:
- print('Timeout')
六, IP 代理
- 1 # 在访问网站时有可能你没有遵守该 robots 协议, 面临被封 IP 的风险, 这样该 IP 就不能再访问了, 大概过段时间才把你从黑名单中拿出来, 这时候就用到了 IP 代理, 这个大概介绍一下, 因为本人也是初学, 能力有限
- 2
- 3 import requests
- 4
- 5 proxies = {
- 6 "http": "***************" 7 }
- 8
- 9 response = requests.get("https://www.taobao.com", proxies=proxies)
- 10 print(response.status_code)
七, cookie
这是浏览器缓存, 就是我们在之前访问过该网站后, 后留下一下脚印, 例如之前请求到的一些信息, 或者提交, 比如需要登录的网站, 短时间内再次进入时候不需要再次输入账户密码. 因此 http 请求要从很远的服务器中拉取你要的信息, 当然效率不会很高, 所以, 他就会在本地的浏览器中暂且保留一段时间的信息, 这段时间内登录就是从本地来得到网页响应, 也会相对快一些.
在爬虫的时候, 尤其是需要登录才能访问的页面, 为了让他可以自动化的一直爬取信息, 就可以预先找到登录后在该网页留下的脚印, 来放到你的爬虫里, 让其自动登录爬取.
- import requests
- response = requests.get("https://www.baidu.com")
- print(response.cookies) # 可以直接调用方法得到当前访问页面时的 cookie
在需要登录的网页时, 我们需要同时请求多个端口来实现, 可以用到 requests.session(), 看一个例子体会一下.
- import requests
- s = requests.Session()
- s.get('http://httpbin.org/cookies/set/****/*****')
- response = s.get('http://httpbin.org/cookies') # 在访问页面的同时打开之前的 cookie 请求. 如果使用 requests 的 get 方法的话, 你会发现, 第一次请求之后, 第二次的 get 是开启的一个新的请求, 而不是针对同一个对象, 因此不能实现
- print(response.text)
这点东西并没有讲清楚, 待我再好好学一下再解释.
来源: https://www.cnblogs.com/yudanqu/p/9847048.html