requests库(爬虫)

时间:2023-03-09 19:17:13
requests库(爬虫)

北京理工大学嵩天老师的课程:http://www.icourse163.org/course/BIT-1001870001

官方文档:http://docs.python-requests.org/en/master/

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

安装

pip install requests

Requests库的七个主要方法

requests库(爬虫)

get方法

r = requests.get(url)

右边构造一个向服务器请求资源的Requests对象,左边返回一个包含服务器资源的Response对象给r,完整参数:

r = requests.get(url,params=None,**kwargs)

如果我们打开requests库get方法源代码,我们可以看到get方法实际上使用了request方法来封装,requests库的其他方法也都是通过调用request方法来封装的:

def get(url, params=None, **kwargs):
    kwargs.setdefault('allow_redirects', True)
    return request('get', url, params=params, **kwargs)  

Resonse对象的属性

requests库(爬虫)

r.encoding:如果header中不存在charset字段,默认编码为ISO-8859-1,此时的编码输出r.text中的中文将是乱码。

r.apparent_encoding:会根据HTTP网页的内容分析出应该使用的编码。

>>> r.encoding
'ISO-8859-1'
>>> r.apparent_encoding
'utf-8'

解决中文乱码方法修改r.encoding值:

>>> r.encoding=r.apparent_encoding

爬取网页的通用代码框架

Requests库爬取网页时可能会遇到的异常

requests库(爬虫)

使用r.raise_for_status()方法构建通用代码框架:

import requests

def getHTMLText(url):
    try:
        r = requests.get(url, timeout=30)
        r.raise_for_status()
        r.encoding = r.apparent_encoding
        return r.text
    except:
        return "产生异常"

if __name__ == '__main__':
    url = 'https://www.baidu.com/'
    print(getHTMLText(url))

HTTP协议及request方法

HTTP(Hypertext Transfer Protocol,超文本传输协议)是一个基于"请求与响应"模式的/无状态的应用层协议。

URL是通过HTTP协议存取资源的Internet路径。

HTTP协议对资源的操作:

requests库(爬虫)

request方法

requests.request(method,url,**kwargs)

详情参参考官方文档:http://docs.python-requests.org/en/master/api/

这是中文的文档:http://docs.python-requests.org/zh_CN/latest/api.html

method(请求方式7个)包括:
GET、HEAD、POST、PUT、PATCH、delete、OPTIONS

**kwargs(控制访问参数13个,均为可选)包括:
params、data、json/headers、cookies、auth、files、timeout/proxies、allow_redirects、stream、verify、cert

params:字典或字节序列,作为参数增加到url中:

>>> import requests
>>> kv={"k1":"v1","k2":"v2"}
>>> r=requests.request('GET','https://www.baidu.com/',params=kv)
>>> r.url
'https://www.baidu.com/?k1=v1&k2=v2'

data:字典、字节序列或文件对象,作为Request的内容

json:JSON格式的数据,作为Request的内容

headers:字典,HTTP定制头

cookies:字典或CookieJar,Request中的cookie

auth:元祖,支持HTTP认证功能

files:字典,传输文件

>>> fs={'file':open('data.xls','rb')}
>>> r=requests.request('POST','https://www.baidu.com/',files=fs)

timeout:设定的超时时间,以秒为单位。超时时间内没有返回结果则抛出超时的异常

>>> r=requests.request('GET','https://www.baidu.com/',timeout=10)

proxies:字典类型,设定访问代理服务器,可以增加的登陆认证,有效隐藏用户爬取网站的源IP地址信息。

>>> r=requests.request('GET','https://www.baidu.com/',timeout=10)
>>> pxs={'http':'http://user:pass@10.10.10.1:1234',
...      'http':'https://10.10.10.1:4321'}
>>> r=requests.request('GET','https://www.baidu.com/',proxies=pxs)

allow_redirects:True/Flase,默认为True,重定向开关

stream:True/Flase,默认为True,获取内容立即下载开关

verify:True/Flase,默认为True,认证SSL证书开关

cert:本地SSL证书路径

除了reques之外的其他六个主要方法

requests.get(url, params=None, **kwargs)
requests.head(url, **kwargs)
requests.post(url, data=None, json=None, **kwargs)
requests.put(url, data=None, **kwargs)
requests.patch(url, data=None, **kwargs)
requests.delete(url, **kwargs)

除了url其他的参数与访问控制参数就是跟方法request中的一样。

网络爬虫爬亦有道之策略与限制

网路爬虫的规模

requests库(爬虫)

网络爬虫的限制

限制原因:

  • 网络爬虫可能会给Web服务器带来巨大的资源开销
  • 网络爬虫获取数据后可能会带来法律风险
  • 网络爬虫可能会造成隐私泄露

限制方法:

1.来源审查:判断User-Agent进行限制。

审查来访HTTP协议头的User-Agent域,只响应浏览器或友好爬虫的访问。

2.发布公告:Robots协议。

告知所有爬虫网站的爬虫策略,要求爬虫遵守。

 Robots协议

Robots Exclusion Standard 网络爬虫排除标准

作用:告知网络爬虫哪些可抓取哪些不行。

形式:网站的根目录下的robots.txt文件。

以京东的为例:

https://www.jd.com/robots.txt

User-agent: *
Disallow: /?*
Disallow: /pop/*.html
Disallow: /pinpai/*.html?*
User-agent: EtaoSpider
Disallow: /
User-agent: HuihuiSpider
Disallow: /
User-agent: GwdangSpider
Disallow: /
User-agent: WochachaSpider
Disallow: /

User-agent: * :表示无论什么爬虫都应该遵守如下协议

Disallow:表示不允许爬取符合后面的通配符表示的路径

其余四个User-agent不允许爬取任何资源,被京东认为是恶意爬虫。

Rebots协议的使用

网络爬虫:自动或人工识别rebots.txt,再进行内容爬取。

约束性:建议但非约束性,网络爬虫可以不遵守,但是存在法律风险。

遵守原则:

requests库(爬虫)

爬取实例

京东商品页面的爬取

import requests

url = "http://item.jd.com/2967929.html"
try:
    r = requests.get(url)
    r.raise_for_status()
    r.encoding = r.apparent_encoding
    print(r.text[:1000])
except:
    print("爬取失败")

亚马逊商品页面的爬取

按实例1的步骤去做发现出现了错误:

requests库(爬虫)

发现是由于亚马逊有自身的头部审查,故我们模拟浏览器访问:

import requests
url = "http://www.amazon.cn/gp/product/B01M8L5Z3Y"
try:
    kv = {'user-agent':'Mozilla/5.0'}
    r= requests.get(url,headers = kv)
    r.raise_for_status()
    r.encoding=r.apparent_encoding
    print(r.text[1000:2000])
except:
    print("爬取失败")

百度/360搜索关键词提交

首先我们需要知道搜索关键词的提交接口:

百度:http://www.baidu.com/s?wd=keyword
360:http://www.so.com/s?q=keyword

接下来我们可以利用params参数将关键词加入,代码如下:

import requests

keyword = "Python"
try:
    kv = {'wd': keyword}
    r = requests.get("http://www.baidu.com/s", params=kv)
    print(r.url)
    r.raise_for_status()
    print(len(r.text))
except:
    print("爬取失败")

网络图片的爬取和存储

网络图片链接的格式:https://pic.cnblogs.com/avatar/1054809/20171230220706.png

import requests
import os

url = "https://pic.cnblogs.com/avatar/1054809/20171230220706.png"
root = "D://pics//"
path = root + url.split('/')[-1]
try:
    if not os.path.exists(root):
        os.mkdir(root)
    if not os.path.exists(path):
        r = requests.get(url)
        with open(path, 'wb') as f:
            f.write(r.content)
            f.close()
            print("文件保存成功")
    else:
        print("文件已存在")
except:
    print("爬取失败")

IP地址归属地的查询

我们python没有这样的库,但是网上有这样的资源,一个网站http://www.ip38.com/有这样的功能

requests库(爬虫)

import requests

url = "http://m.ip138.com/ip.asp?ip="
try:
    r = requests.get(url + '202.204.80.112')
    r.raise_for_status()
    r.encoding = r.apparent_encoding
    print(r.text[-500:])
except:
    print("爬取失败")

爬取页面图片

import requests
import os
import re
from bs4 import BeautifulSoup

def getHTMLText(url):
    r = requests.get(url)
    html = r.text
    return html

def getImgURL(html):
    soup = BeautifulSoup(html, 'html.parser')
    imgs = soup.find_all('img')
    li = []
    for img in imgs:
        src = img.attrs['src']
        li.append(src)
    return li

def getImg(urls):
    for url in urls:
        root = "D://images//"
        path = root + url.split('/')[-1]
        try:
            if not os.path.exists(root):
                os.mkdir(root)
            if not os.path.exists(path):
                r = requests.get(url)
                with open(path, 'wb') as f:
                    f.write(r.content)
                    f.close()
                    print("文件保存成功")
            else:
                print("文件已存在")
        except:
            print("爬取失败")

def main():
    url = 'http://www.feizl.com/html/65323.htm'  # 带爬取网页URL
    html = getHTMLText(url)
    urls = getImgURL(html)
    getImg(urls)

if __name__ == '__main__':
    main()