Day1
1.什么是爬虫?
网络爬虫(又被称为网络蜘蛛,网络机器人)是一种按照一定的规则,自动抓取万维网信息的程序或者脚本。
2.爬虫的作用?
搜索引擎
商品比价
知乎数据分析平台
3.网页的三大特征?
1)每一个网页都有一个唯一的url统一资源定位符,来进行定位
2)网页都是通过html超文本展示的
3)所有的网页都是通过HTTP超文本传输协议来传输的
4.爬虫的流程?
1)分析网站,得到目标url
2)根据url发起请求,获得页面源码
3)从源码中提取数据,提取到目标数据,做数据的筛选和持久化存储
,从页面中提取新的url地址,继续执行第二部操作
4)爬虫结束:所有的目标url都已经提取完毕,并且得到数据,再灭有其他的请求人物,这时意味着爬虫结束
5.爬虫的分类?
1.通用爬虫:是搜索引擎的重要组成部分
1)主要目的?
是将互联网上的网页下载到本地,经过预处理(去噪,分词,去广告等),最终将数据存储到本地,形成一个互联网内容的镜像
2)通用爬虫的缺点?
a.必须遵守robot协议,就是一个网页爬取的规范,告诉爬取者,哪些目录下的资源允许爬取,哪些不允许
b.搜素引擎返回的都是网页,90%都是无需用的数据
c.不能够根据不同的用户需求或者见多结果返回不同的结果
d.通用爬虫对于媒体的文件不能够获取
2.聚焦爬虫:是面向特定主题需求的一种网络爬虫程序
6.OSI七层协议:
- 应用层:用户的应用程序提供网络服务(http,https,ftp...)
- 表示层:负责端到端的数据信息可以被另一个主机所理解和识别,按照一定的格式将信息传递给会话层。
- 会话层:会话层管理主机之间的会话进程,即负责建立、管理、终止进程之间的会话.
- 传输层:(tcp/udp)进行数据传输
TCP 和 UDP 对比
传输方式上: 面向连接的 非面向链接的
传输数据: 数据流 数据包(可能出现丢包)
传输效率: 慢 快
传输稳定性: 高 低
"""
- 网路层:路由器
- 数据链路层:网桥,交换机
- 物理层:网卡,网线,集线器,中继器,调制解调器
2.发起请求
携带请求头:User-Agent:模拟浏览器进行请求
Cookies:存储在浏览器里面的,使用cookie表明用户身份
Refere:说明当前的请求是从哪个页面发起的
3.str和bytes数据类型
python2中:对于字符串和bytes类型的数据没有明显的区分
python3中:有明显区分,将bytes类型的数据转换为字符串使用decode('编码类型')
将字符串转换为bytes类型使用encode('编码类型')
bytearray和bytes类型的数据是有区别的:bytearray是可变的。(通过切片的方式,一个字符占2个字节。)
常见的字符集的编码类型:utf-8 gbk gb2312
Day2
1.使用不同的UA发起请求
User_Agent里面放一些不同的数据,调用random.choice方法,每次获取不同的UA
2.使用随机UA发起请求
from fake_useragent import UserAgent
User_agent = UserAgent()#实例化UA对象
#随机获取
Print(user_agent.random)
3.get请求url中含有中文
From urllib import parse,requets
#quote将中文转化为URL能够识别的编码格式
quote_str = parse.quote(kw)
print(quote_str)
#将url编码格式转化为中文
unqute_str = parse.unquote(quote_str)
print(unqute_str)
# 将字典类型的参数转化为url编码格式
parmars = {
'wd': kw,
'pn':(page-1)*10,
}
result = parse.urlencode(parmars)
print(result)
4.urllib_post请求
from urllib import parse,request
url = 'https://httpbin.org/post'
#表单数据
fordata = {
'name':'赵文竹',
'age':18,
'gender':'女',
}
#先使用urlencode将参数转为url编码格式的字符串,然后使用encode()将字符串转换为bytes类型的参数
formdata = parse.urlencode(fordata).encode()
#不需要添加请求头
response= request.urlopen(url,data=formdata)
print(response.status)
print(response.read().decode('utf-8'))
#设置请求头
req_header = {
'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36',
}
req = request.Request(url,headers=req_header,data=formdata)
response = request.urlopen(req)
print(response.status)
5.正则表达式:
实际上爬虫一共就四个主要步骤:
明确目标 (要知道你准备在哪个范围或者网站去搜索)
爬 (将所有的网站的内容全部爬下来)
取 (去掉对我们没用处的数据)
处理数据(按照我们想要的方式存储和使用)
目的 给定一个正则表达式和另一个字符串,我们可以达到如下的目的:
Day3
1.urllib_parse
url.parse :定义了url的标准接口,实现url的各种抽取
parse模块的使用:url的解析,合并,编码,解码
使用时需导入
from urllib import parse
- urlparse()实现URL的识别和分段
url = 'https://book.qidian.com/info/1004608738?wd=123&page=20#Catalog'
"""
url:待解析的url
scheme='':假如解析的url没有协议,可以设置默认的协议,如果url有协议,设置此参数无效
allow_fragments=True:是否忽略锚点,默认为True表示不忽略,为False表示忽略
"""
result = parse.urlparse(url=url,scheme='http',allow_fragments=True)
print(result)
print(result.scheme)
"""
(scheme='https', netloc='book.qidian.com', path='/info/1004608738', params='', query='wd=123&page=20', fragment='Catalog')
scheme:表示协议
netloc:域名
path:路径
params:参数
query:查询条件,一般都是get请求的url
fragment:锚点,用于直接定位页
面的下拉位置,跳转到网页的指定位置
- urlunparse()可以实现URL的构造
url_parmas = ('https', 'book.qidian.com', '/info/1004608738', '', 'wd=123&page=20', 'Catalog')
#components:是一个可迭代对象,长度必须为6
result = parse.urlunparse(url_parmas)
print(result)
"""
https://book.qidian.com/info/1004608738?wd=123&page=20#Catalog
"""
- urljoin()传递一个基础链接,根据基础链接可以将某一个不完整的链接拼接为一个完整链接
base_url = 'https://book.qidian.com/info/1004608738?wd=123&page=20#Catalog'
sub_url = '/info/100861102'
full_url = parse.urljoin(base_url,sub_url)
print(full_url)
- urlencode()将字典构形式的参数序列化为url编码后的字符串
parmas = {
'wd':'123',
'page':20
}
parmas_str = parse.urlencode(parmas)
print(parmas_str)
"""
page=20&wd=123
"""
- parse_qs()将url编码格式的参数反序列化为字典类型
parmas_str = 'page=20&wd=123'
parmas = parse.parse_qs(parmas_str)
print(parmas)
"""
{'page': ['20'], 'wd': ['123']}
"""
- quote()可以将中文转换为URL编码格式
word = '中国梦'
url = 'http://www.baidu.com/s?wd='+parse.quote(word)
print(parse.quote(word))
print(url)
"""
%E4%B8%AD%E5%9B%BD%E6%A2%A6
http://www.baidu.com/s?wd=%E4%B8%AD%E5%9B%BD%E6%A2%A6
"""
- unquote:可以将URL编码进行解码
url = 'http://www.baidu.com/s?wd=%E4%B8%AD%E5%9B%BD%E6%A2%A6'
print(parse.unquote(url))
"""
http://www.baidu.com/s?wd=中国梦
"""
2.urllib 的异常错误处理
URLError:
来自urllib库的error模块,继承自OSError,由request模块产生的异常都可以通过捕捉这个类来处理.
产生的原因主要有:
- 没有网络连接
- 服务器连接失败
- 找不到指定的服务器
from urllib import error,request
def check_urlerror():
"""
没有网络
服务器连接失败
找不到指定的服务器
reason:返回错误原因
"""
req_url = 'https://www.baiduxxx.com/'
try:
response = request.urlopen(url=req_url)
print(response.status)
except error.URLError as err:
"""
1.[Errno -3] Temporary failure in name resolution:
(没有网络)无法解析域名,即DNS解析配置出现问题
2.[Errno -2] Name or service not known:
未知的服务器,找不到服务器
3.timed out
请求超时
"""
print('===',err.reason)
HTTPError
- HTTPError是URLError的子类,我们发出一个请求时,服务器上都会对应一个response应答对象,其中它包含一个数字"响应状态码"。
- 专门用来处理HTTP请求错误,比如未认证,页面不存在等
- 有三个属性:
code:返回HTTP的状态码
reason:返回错误原因
headers:返回请求头
注意,urllib可以为我们处理重定向的页面(也就是3开头的响应码),100-299范围的号码表示成功,所以我们只能看到400-599的错误号码。
def check_httperror():
"""
处理认证或则请求失败的错误
例如:出现404表示页面未找到等
code:返回的HTTP状态码
reason:返回的错误原因
headers:返回的请求头
:return:
"""
req_url = 'https://www.qidian.com/all/nsacnscn.htm'
try:
response = request.urlopen(url=req_url)
print(response.status)
except error.HTTPError as err:
"""
Not Found (reason)
404 (code)
Server: nginx (headers)
Date: Mon, 19 Nov 2018 13:36:11 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 15616
Connection: close
"""
print('===', err.reason,err.code,err.headers)
改进版
因为HTTPError的父类是URLError,所以我们更好的处理顺序应该是先捕获子类的错误,再捕获父类的错误
from urllib import request,error
def check_error():
"""
因为HTTPError的父类是URLError,所以我们更好的处理顺序应该是
先捕获子类的错误,再捕获父类的错误
"""
req_url = 'https://www.baiduxxx.com/'
try:
response = request.urlopen(url=req_url)
print(response.status)
except error.HTTPError as err:
print(err.code,err.reason,err.headers)
except error.URLError as err:
print('===', err.reason)
下面是常见的HTTP状态码:
- 200 - 请求成功
- 301 - 资源(网页等)被永久转移到其它URL
- 302 - 资源(网页等)被临时转移到其它URL
- 401 - 未授权
- 403 - 禁止访问
- 408 - 请求超时
- 404 - 请求的资源(网页等)不存在
- 500 - 内部服务器错误
- 503 - 服务器不可用
3.Handler处理器 和 自定义Opener
基本的urlopen()方法不支持代理、cookie等其他的HTTP/HTTPS高级功能。所以要支持这些功能:
- 使用相关的 Handler处理器 来创建特定功能的处理器对象;
- 然后通过 urllib.request.build_opener()方法使用这些处理器对象,创建自定义opener对象;
- 使用自定义的opener对象,调用open()方法发送请求。
import urllib.request
# 构建一个HTTPHandler 处理器对象,支持处理HTTP请求
http_handler = urllib.request.HTTPHandler()
# 构建一个HTTPHandler 处理器对象,支持处理HTTPS请求
# http_handler = urllib.request.HTTPSHandler()
# 调用urllib.request.build_opener()方法,创建支持处理HTTP请求的opener对象
opener = urllib.request.build_opener(http_handler)
# 构建 Request请求
request = urllib.request.Request("http://www.baidu.com/")
# 调用自定义opener对象的open()方法,发送request请求
response = opener.open(request)
# 获取服务器响应内容
print (response.read().decode())
如果在 HTTPHandler()增加 debuglevel=1参数,还会将 Debug Log 打开,这样程序在执行的时候,会把收包和发包的报头在屏幕上自动打印出来,方便调试,有时可以省去抓包的工作。仅需要修改的代码部分:
4.ProxyHandler处理器用来设置代理
urllib.request中通过ProxyHandler来设置使用代理服务器,下面代码说明如何使用自定义opener来使用代理:
from urllib import request,error
#构建支持代理的handler
proxy = {
'http':'61.138.33.20:808',
'https':'120.69.82.110:44693',
}
proxy_handler = request.ProxyHandler(proxies=proxy)
# 构建一个私密代理Handler,需要加上私密代理账户的用户名和密码
# authproxy = {
# "http" :"username:password@61.135.217.7:80"
#}
# authproxy_handler=urllib.request.ProxyHandler(
# proxies=authproxy
#)
#根据proxy_handler实例化一个opener对象
opener = request.build_opener(proxy_handler)
url = 'http://www.baidu.com/'
# 使用https://httpbin.org/get接口验证使用了代理
# url = 'https://httpbin.org/get'
try:
response = opener.open(url,timeout=5)
print(response.status)
except error.HTTPError as err:
print(err.reason)
except error.URLError as err:
print(err.reason)
# 1. 如果按照上面代码,只有使用opener.open()方法发送
请求才使用自定义的代理,而urlopen()则不使用自定义代理。
response = opener.open(request)
# 2. 将自定义的opener设置为全局的opener,之后所有的,不管是
opener.open()还是urlopen() 发送请求,都将使用自定义代理。
# request.install_opener(opener)
# response = urlopen(request)
5.urllib_cookie设置
Cookie 是指某些网站服务器为了辨别用户身份和进行Session跟踪,而储存在用户浏览器上的文本文件,Cookie可以保持登录信息到用户下次与服务器的会话。
获取到一个有登录信息的Cookie模拟登陆
# -*- coding:utf-8 -*-
import urllib.request
url = 'https://www.douban.com/people/175417123/'
#根据刚才的登录信息来构建一个已经登录过的用户的headers信息
headers = {
'User-Agent':' Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:59.0) Gecko/20100101 Firefox/59.0',
'Host':'www.renren.com',
'Cookie':'anonymid=jgoj4xlw-3izsk4; depovince=BJ; jebecookies=62d94404-de1f-450a-919b-a2d9f4c8b811|||||; _r01_=1; JSESSIONID=abchsGLNgne0L8_wz2Emw; ick_login=cf54f2dc-8b0b-417a-96b2-32d4051f7236; jebe_key=02cb19ad-2966-4641-8828-217160ca67a0%7Cba6f6d6ec917200a4e17a85dbfe33a4a%7C1525230975024%7C1%7C1525230982574; t=87a502d75601f8e8c0c6e0f79c7c07c14; societyguester=87a502d75601f8e8c0c6e0f79c7c07c14; id=965706174; xnsid=e1264d85; ver=7.0; loginfrom=null; wp_fold=0',
}
# 2. 通过headers里的报头信息(主要是Cookie信息),构建Request对象
request = urllib.request.Request(url, headers=headers)
# 3. 直接豆瓣个人主页(主要是Cookie信息)
#,判断这是一个已经登录的用户,并返回相应的页面
response = urllib.request.urlopen(request)
# 4. 打印响应内容
print (response.read().decode())
6.cookiejar库 和 HTTPCookieProcessor处理器
在Python处理Cookie,一般是通过cookiejar模块和 urllib模块的HTTPCookieProcessor处理器类一起使用。
cookiejar模块:主要作用是提供用于存储cookie的对象
HTTPCookieProcessor处理器:主要作用是处理这些cookie对象,并构建handler对象。
- cookiejar 库
该模块主要的对象有CookieJar、FileCookieJar、MozillaCookieJar、LWPCookieJar。其实大多数情况下,我们只用CookieJar(),如果需要和本地文件交互,就用 MozillaCookjar()
CookieJar:管理HTTP cookie值、存储HTTP请求生成的cookie、向传出的HTTP请求添加cookie的对象。整个cookie都存储在内存中,对CookieJar实例进行垃圾回收后cookie也将丢失。
# urllib_cookiejar_test1.py
import urllib
from http import cookiejar
# 构建一个CookieJar对象实例来保存cookie
cookiejar = cookiejar.CookieJar()
# 使用HTTPCookieProcessor()来创建cookie处理器对象,参数为CookieJar()对象
handler=urllib.request.HTTPCookieProcessor(cookiejar)
# 通过 build_opener() 来构建opener
opener = urllib.request.build_opener(handler)
# 4. 以get方法访问页面,访问之后会自动保存cookie到cookiejar中
opener.open("http://www.baidu.com")
## 可以按标准格式将保存的Cookie打印出来
cookieStr = ""
for item in cookiejar:
cookieStr = cookieStr + item.name + "=" + item.value + ";"
## 舍去最后一位的分号
print (cookieStr[:-1])
我们使用以上方法将Cookie保存到cookiejar对象中,
MozillaCookjar()
MozillaCookjar()保存和使用cookie使用使用MozillaCookjar将cookie信息保存到本地的时候需要调用save()方法实现存储save()函数带有两个参数,ignore_discard和ignore_expires。
*
ignore_discard: 即保存需要被丢弃的cookie。
*
ignore_expires: 即过期的cookie也保存。
from urllib import request
from http.cookiejar import MozillaCookieJar
#文件名(该文件用来并保存cookies信息)
filename = 'cookies.txt'
#声明一个MozillaCookieJar()对象,用来存储cookies
mz_cookiejar = MozillaCookieJar(filename)
#使用HTTPCookieProcessor实例化cookie处理器对象
handler = request.HTTPCookieProcessor(mz_cookiejar)
#自定义opener
opener = request.build_opener(handler)
response = opener.open('http://www.baidu.com/')
#调用save方法将cookies信息存储到本地
mz_cookiejar.save(ignore_discard=True,ignore_expires=True)
使用MozillaCookjar()加载本地文件中cookies数据,发起请求
- 使用load()方法加载出本地文件存储的cookies信息
mz_cookiejar.load(filename)
from urllib import request
from http.cookiejar import MozillaCookieJar
#文件名(该文件用来并保存cookies信息)
filename = 'cookies.txt'
#声明一个MozillaCookieJar()对象,用来存储cookies
mz_cookiejar = MozillaCookieJar(filename)
#加载出本地文件存储的cookies信息
mz_cookiejar.load(filename)
#打印加载本地coolies后的mz_cookiejar
print(mz_cookiejar)
#打印出cookie的name和value
for item in mz_cookiejar:
print(item.name,item.value)
#使用HTTPCookieProcessor实例化cookie处理器对象
handler = request.HTTPCookieProcessor(mz_cookiejar)
#自定义opener
opener = request.build_opener(handler)
#发起请求
response = opener.open('http://www.baidu.com/')