简介
- 网络爬虫(又被称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者),是一种按照一定的规 则,自动地抓取万维网信息的程序或者脚本。另外一些不常使用的名字还有蚂蚁、自动索引、模拟程序或者蠕虫。
- 其实通俗的讲就是通过程序去获取web页面上自己想要的数据,也就是自动抓取数据。
用途
- 可以抓取到 任何你想要抓取的内容,前提是你的浏览器访问得到
本质
- 爬虫的本质就是模拟浏览器打开网页,获取网页中我们想要的那部分数据。
- 浏览器打开网页的过程:
- 在浏览器的输入地址栏,输入想要访问的网址。
- 经过DNS服务器找到服务器主机,向服务器发送一个请求
- 服务器经过解析处理后返回给用户结果(包括html,js,css文件等等内容)
- 浏览器接收到结果,进行解释通过浏览器屏幕呈现给用户结果
- 爬虫的关键点:模拟请求,解析处理,自动化。
基本流程
- 发起请求
通过HTTP库向目标站点发起请求(request),请求可以包含额外的header等信息,等待服务器响应 - 获取响应内容
如果服务器能正常响应,会得到一个Response,Response的内容便是所要获取的页面内容,类型可能是HTML,Json字符串,二进制数据(图片或者视频)等类型 - 解析内容
得到的内容可能是HTML,可以用正则表达式,页面解析库进行解析,可能是Json,可以直接转换为Json对象解析,可能是二进制数据,可以做保存或者进一步的处理 - 保存数据
保存形式多样,可以存为文本,也可以保存到数据库,或者保存特定格式的文件
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对象
- response.read()得到返回的网页内容,可使用decode(“utf-8”)解码字符串;
- 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。
- 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 结合使用。 - 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'))
模拟登陆
- 有些网页需要登陆才可以显示,在未登录状态下访问该网页会提示登陆等操作;
- 在访问网页时,有时我们需要保存会话信息,比如登录信息。有两种比较常用的保存会话信息的方式:
- Cookie及Session使用Cookie会将所有会话信息保存在客户端;
- 使用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去构建请求,防止网站的反爬,也就是俗称的反反爬. -
反爬策略
- 检测浏览器header, User-Agent
- ip 封禁
- 图片验证码
- 滑块
- JS轨迹
- 证书加密
- AI识别
-
应对方式
- 建立代理IP, 轮换访问
- 设置访问时间间隔
- 可动态设置user agent
- 禁用cookies
- 设置延迟下载
- 使用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是第三方库,需要下载
- 下载: pip install requests
- 导入: import requests
get请求
requests.get(url, params=None, **kwargs)
参数说明

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

被折叠的 条评论
为什么被折叠?



