爬虫

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高级功能。所以要支持这些功能:

  1. 使用相关的 Handler处理器 来创建特定功能的处理器对象;
  2. 然后通过 urllib.request.build_opener()方法使用这些处理器对象,创建自定义opener对象;
  3. 使用自定义的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/')
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,542评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,596评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,021评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,682评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,792评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,985评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,107评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,845评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,299评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,612评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,747评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,441评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,072评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,828评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,069评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,545评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,658评论 2 350

推荐阅读更多精彩内容

  • HTTP基本原理 URI、URL、URN(Uninform Resource) URI(Identifier):统...
    GHope阅读 2,070评论 2 26
  • Python爬虫入门(urllib+Beautifulsoup) 本文包括:1、爬虫简单介绍2、爬虫架构三大模块3...
    廖少少阅读 9,798评论 0 6
  • 什么是Urllib: Urllib是python内置的HTTP请求库 包括以下模块 urllib.request ...
    啊烟雨阅读 1,296评论 0 5
  • 该笔记主要参考 cqc 大佬的 blog。 一、综述 二、爬虫基础了解 三、urllib库的基本使用 1、简单的爬...
    火禾子_阅读 691评论 0 0
  • 网络 理论模型,分为七层物理层数据链路层传输层会话层表示层应用层 实际应用,分为四层链路层网络层传输层应用层 IP...
    FlyingLittlePG阅读 762评论 0 0