python爬虫_urllib&requests

简介

  • 网络爬虫(又被称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者),是一种按照一定的规 则,自动地抓取万维网信息的程序或者脚本。另外一些不常使用的名字还有蚂蚁、自动索引、模拟程序或者蠕虫。
  • 其实通俗的讲就是通过程序去获取web页面上自己想要的数据,也就是自动抓取数据。

用途

  • 可以抓取到 任何你想要抓取的内容,前提是你的浏览器访问得到

本质

  • 爬虫的本质就是模拟浏览器打开网页,获取网页中我们想要的那部分数据。
  • 浏览器打开网页的过程:
  1. 在浏览器的输入地址栏,输入想要访问的网址。
  2. 经过DNS服务器找到服务器主机,向服务器发送一个请求
  3. 服务器经过解析处理后返回给用户结果(包括html,js,css文件等等内容)
  4. 浏览器接收到结果,进行解释通过浏览器屏幕呈现给用户结果
  • 爬虫的关键点:模拟请求,解析处理,自动化。

基本流程

  1. 发起请求
    通过HTTP库向目标站点发起请求(request),请求可以包含额外的header等信息,等待服务器响应
  2. 获取响应内容
    如果服务器能正常响应,会得到一个Response,Response的内容便是所要获取的页面内容,类型可能是HTML,Json字符串,二进制数据(图片或者视频)等类型
  3. 解析内容
    得到的内容可能是HTML,可以用正则表达式,页面解析库进行解析,可能是Json,可以直接转换为Json对象解析,可能是二进制数据,可以做保存或者进一步的处理
  4. 保存数据
    保存形式多样,可以存为文本,也可以保存到数据库,或者保存特定格式的文件

urllib

  • urllib 是 Python 标准库中用于网络请求的库。该库有四个模块,分别是urllib.request,urllib.error,urllib.parse,urllib.robotparser。

urllib.request

  • urllib.request 模块提供了最基本的构造 HTTP请求方法,可以模拟浏览器的一个请求发起过程。同时它还带有处理authenticaton(授权验证),redirections(重定向),cookies(浏览器Cookies)以及其它内容。

urllib.request.urlopen()

urllib.request.urlopen(url, data=None, [timeout, ]*, cafile=None, capath=None, cadefault=False, context=None)
参数说明

在这里插入图片描述

  • 该方法也可以单独传入urllib.request.Request对象
  • 该函数返回结果是一个http.client.HTTPResponse对象
    1. response.read()得到返回的网页内容,可使用decode(“utf-8”)解码字符串;
    2. response.status得到返回结果的状态码,200代表请求成功, 404代表网页未找到
发起请求
import urllib.request as ur

# 获取CSDN学院的静态页面
response = ur.urlopen('https://edu.csdn.net/')
print(response)    # <http.client.HTTPResponse object at 0x000001F61B3BEF98>

html = response.read()  # bytes类型 b'\n<!DOCTYPE html>\n<html>\n<head>\n  ......
print(html)

with open('csdn.html', 'wb') as f:
    f.write(html)  # 浏览器打开这个文件,显示与爬取网页一致

html_utf8 = html.decode('utf-8')  # 转换一下
print(html_utf8)
设置请求超时
  • 有些请求可能因为网络原因无法得到响应。因此,我们可以手动设置超时时间。当请求超时,我们可以采取进一步措施,例如选择直接丢弃该请求或者再请求一次。
import urllib.request as ur

# 这里设置超时时间极短,会导致没有在时间内获取到数据,会抛出异常 socket.timeout: timed out,urllib.error.URLError: <urlopen error timed out>
try:
    response = ur.urlopen(url='https://edu.csdn.net/', timeout=0.001).read().decode('utf-8')
    print(response)
except Exception as e:
    print(e)       # <urlopen error timed out>
提交数据
import urllib.request as ur
import urllib.parse as up
import json

# 提交数据
# 1、在url地址后面添加数据 url?data

# 访问贴吧中动漫主题的第2页
# 分析网址发现规律 https://tieba.baidu.com/f?kw=主题关键字&ie=utf-8&pn=(第几页-1)*50
# 将地址复制 https://tieba.baidu.com/f?kw=%E5%8A%A8%E6%BC%AB&ie=utf-8&pn=50,发现中文被编码了,所以在请求是同样要做编码处理
data = {
    'kw': '动漫',
    'ie': 'utf-8',
    'pn': '50'
}

url_data = up.urlencode(data)  # 需要对data进行url编码
print(url_data)  # kw=%E5%8A%A8%E6%BC%AB&ie=utf-8&pn=50

url_data_ret = up.unquote(url_data)
print(url_data_ret)  # kw=动漫&ie=utf-8&pn=50

url = 'https://tieba.baidu.com/f?' + url_data
response = ur.urlopen(url).read()
print(response)  # b'\r\n<!DOCTYPE html>\r\n<!--STATUS OK-->\r\n<html>\r\n<head>\r\n

# 2、使用data参数
# 百度翻译,需要提交需要翻译的内容

data = {
    'kw': 'python' # 需要翻译的词
}

# data是一个字典,需要被转码成字节流
url_data = up.urlencode(data)
byte_data = url_data.encode('utf-8')   # 也可以用下面的法子
# byte_data = bytes(url_data, encoding='utf-8')

response = ur.urlopen('https://fanyi.baidu.com/sug',data=byte_data).read()

rsp_json = json.loads(response)
print(rsp_json)
if rsp_json['data']:  # 有翻译结果
    print('翻译结果:', rsp_json['data'][0]['v'])

# 输出结果:
# {'errno': 0, 'data': [{'k': 'python', 'v': 'n. 蟒; 蚺蛇;'}, {'k': 'pythons', 'v': 'n. 蟒; 蚺蛇;  python的复数;'}]}
# 翻译结果: n. 蟒; 蚺蛇;

urllib.request.Request()

  • 利用 urlopen() 方法可以发起简单的请求。但这几个简单的参数并不足以构建一个完整的请求,如果请求中需要加入headers(请求头)、指定请求方式等信息,我们就可以利用更强大的Request类来构建一个请求
urllib.request.Request(url, data=None, headers={}, origin_req_host=None, unverifiable=False, method=None)
参数说明

在这里插入图片描述

高级用法
  • 如果我们需要在请求中添加代理、处理请求的Cookies,我们需要用到Handler和OpenerDirector。
  1. Handler:就是处理者、处理器。 Handler 能处理请求(HTTP、HTTPS、FTP等)中的各种事情。它的具体实现是这个类 urllib.request.BaseHandler。它是所有的 Handler 的基类,其提供了最基本的Handler的方法,例如default_open()、protocol_request()等。
    继承 BaseHandler 有很多个,列举几个比较常见的类:
    ProxyHandler:为请求设置代理
    HTTPCookieProcessor:处理 HTTP 请求中的 Cookies
    HTTPDefaultErrorHandler:处理 HTTP 响应错误。
    HTTPRedirectHandler:处理 HTTP 重定向。
    HTTPPasswordMgr:用于管理密码,它维护了用户名密码的表。
    HTTPBasicAuthHandler:用于登录认证,一般HTTPPasswordMgr 结合使用。
  2. OpenerDirector,可以称之为 Opener。我们之前用过 urlopen() 这个方法,实际上它就是 urllib 为我们提供的一个Opener。那 Opener 和 Handler 又有什么关系?opener 对象是由 build_opener(handler) 方法来创建出来 。我们需要创建自定义的 opener,调用这个opener对象的open方法去获取网页数据,也可以使用install_opener(opener)方法得到一个全局的 OpenerDirector 对象。
发起请求
# 如果不设置 headers 中的 User-Agent,默认的User-Agent是Python-urllib/3.5。
# 可能一些网站会将该请求拦截,所以需要伪装成浏览器发起请求。
# User-Agent 可以在浏览器打开网页时,通过开发者工具查看

import urllib.request as ur

url = "http://tieba.baidu.com/"
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36'
}
request = ur.Request(url=url, headers=headers)
response = ur.urlopen(request)
print(response.read().decode('utf-8'))
模拟登陆
  • 有些网页需要登陆才可以显示,在未登录状态下访问该网页会提示登陆等操作;
  • 在访问网页时,有时我们需要保存会话信息,比如登录信息。有两种比较常用的保存会话信息的方式:
    1. Cookie及Session使用Cookie会将所有会话信息保存在客户端;
    2. 使用Session会将会话信息保存在服务器端,但是服务器端会给客户端发SessionID等信息,这些信息一般存在客户端的Cookie中
  • 有了Cookie,当我们登录成功后,爬取该网站的其他网页时,则会保存登录状态进行内容的爬取;
  • 登录需要爬取得网址,浏览器开发者工具中拿到cookie值
import urllib.request as ur

# 访问CSDN我的学院
url = "https://edu.csdn.net/mycollege"
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36',
    'Cookie': '填入cookie字符串'
}
request = ur.Request(url=url, headers=headers)
response = ur.urlopen(request)
print(response.read().decode('utf-8'))
使用代理ip
  • 为什么要使用代理Ip
    网站为了防止被爬取,会有反爬机制,对于同一个IP地址的大量同类型的访问,会封锁IP,过一段时间后,才能继续访问,这个时候就需要我们用代理ip去构建请求,防止网站的反爬,也就是俗称的反反爬.

  • 反爬策略

    1. 检测浏览器header, User-Agent
    2. ip 封禁
    3. 图片验证码
    4. 滑块
    5. JS轨迹
    6. 证书加密
    7. AI识别
  • 应对方式

    1. 建立代理IP, 轮换访问
    2. 设置访问时间间隔
    3. 可动态设置user agent
    4. 禁用cookies
    5. 设置延迟下载
    6. 使用IP地址池(代理IP、VPN等)
import urllib.request as ur
# 可以在专业代理ip网站获取代理ip
# 需要付费的,生成一个获取代理ip的api接口,访问这个接口得到代理ip
# 有些会提供一些免费的代理ip,但质量不能保证

# 获取代理ip
proxy_address = ur.urlopen('获取代理ip的接口').read().decode('utf-8').strip()
print(proxy_address)  # 类似 127.0.1.1:8000的字符串

# 创建proxy_handler
proxy_handler = ur.ProxyHandler({
    'http': proxy_address
})

# 新建opener对象
proxy_opener = ur.build_opener(proxy_handler)
request = ur.Request(url='https://edu.csdn.net/')

# 直接调用opener的open方法
response = proxy_opener.open(request)   # 这时就是通过代理ip取访问,而不是自己的本机ip
print(response.read().decode('utf-8'))

# 将该opener实例化为全局OpenerDirector对象,这样在使用urlopen时,就是使用该opener
ur.install_opener(proxy_opener)
response_new = ur.urlopen(request)
print(response_new.read().decode('utf-8'))

requests

  • Requests 是Python语编写,基于urllib,采Apache2 Licensed开源协议的 HTTP 库。它比 urllib更加方便,可以节约我们大量的工作,完全满足HTTP测试需求。
  • Requests是第三方库,需要下载
  1. 下载: pip install requests
  2. 导入: import requests

get请求

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

参数说明

在这里插入图片描述

  • kwargs有以下的参数,对于requests.get,其第一个参数被提出来了。
  1. params:字典或字节序列,作为参数增加到url中,使用这个参数可以把一些键值对以?key1=value1&key2=value2的模式增加到url中;
  2. data:字典,字节序或文件对象,重点作为向服务器提供或提交资源是提交,作为request的内容,与params不同的是,data提交的数据并不放在url链接里,而是放在url链接对应位置的地方作为数据来存储,它也可以接受一个字符串对象;
  3. json:json格式的数据,在相关的html,http相关的web开发中非常常见,也是http最经常使用的数据格式,他是作为内容部分可以向服务器提交;
  4. headers:字典是http的相关语,对应了向某个url访问时所发起的http的头i字段,可以用这个字段来定义http的访问的http头,可以用来模拟任何我们想模拟的浏览器来对url发起访问;
  5. cookies:字典或CookieJar,指的是从http中解析cookie;
  6. auth:元组,用来支持http认证功能;
  7. files:字典,是用来向服务器传输文件时使用的字段;
  8. timeout:用于设定超时时间,单位为秒,当发起一个get请求时可以设置一个timeout时间,如果在timeout时间内请求内容没有返回,将产生一个timeout的异常;
  9. proxies:字典,用来设置访问代理服务器;
  10. allow_redirects:开关,表示是否允许对url进行重定向,默认为True;
  11. stream:开关,指是否对获取内容进行立即下载,默认为True;
  12. verify:开关,用于认证SSL证书,默认为True;
  13. cert:用于设置保存本地SSL证书路径。

无参数请求

import requests

# 无参数的get请求
response = requests.get('https://edu.csdn.net/')
print(response)  # <Response [200]>

print(response.encoding)  # 获取当前编码

response.encoding = 'utf-8'   # 获取网页的HTML字符串,可能会出现乱码,可以设置下编码
print(response.text)  # 获取网页的HTML字符串,以encoding解析返回内容

print(response.content)   # 获取网页的HTML内容,字节类型
print(response.content.decode())  # 把相应的二进制字节流转化为str类型

print(response.request.headers)  # 获取请求头
print(response.headers)   # 获取响应头

print(response.request.url)  # 获取请求url
print(response.url)    # 获取响应url

有参数请求

import requests

# 有参数,如果参数中函数中文,会自动编码

# 访问贴吧 python 主题
# 需要分析网址 https://tieba.baidu.com/f?kw=搜索主题&ie=utf-8&pn=页数
data = {
    'kw': '动漫',
    'ie': 'utf-8',
    'pn': '0'
}

# 第一种,直接拼接在url地址上
url = f'https://tieba.baidu.com/f?kw={data["kw"]}&ie={data["ie"]}&pn={data["pn"]}'
response = requests.get(url)
print(response.request.url)
print(response.text)

# 第二种,使用params参数
url = 'https://tieba.baidu.com/f'
headers = {
    'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36'
}
response = requests.get(url=url, params=data, headers=headers)
print(response.request.headers)
print(response.request.url)   # https://tieba.baidu.com/f?kw=python&ie=utf-8&pn=0
print(response.text)

知识总结,交流学习,不当之处敬请指正,谢谢!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值