python3 爬虫基础(UPDATE)

  1. 客户端与服务器的网页通信简单原理:
    客户端向服务器发送一个请求,服务端对该客户端的请求进行解析,然后服务端向客户端发送出一个响应,而后客户端对该响应进行解析,然后就解析出用户所看到的网页。

  2. 请求与响应:
    请求:请求方法(get、post(与需要用户登录的网页有关)),请求头,请求 URL,请求体(与需要用户登录的网页有关)。
    响应:响应体(html代码爬虫重点分析对象),响应头、响应码(根据它可以 判断服务器的情况,如 200 代表请求成功)

3.爬虫基本流程:

发起请求-->获取响应内容-->解析内容-->保存数据
请求:
	一般爬虫都会加上请求头.
解析内容:
	解析html数据:用正则表达式和第三方解析库解析。
	解析json数据:用json模块解析。
	解析二进制数据:以wb的方式写入文件。
存储:
	数据库、文件

4.python3请求库:
(1)urllib库(python内置的HTTP请求库)

它有4个模块:
	request:最基本的HTTP请求模块。
	error:异常处理模块,如果出现请求错误,我们可以捕获这些异常,
			然后进行重试或其他操作以保证程序不会意外终止。
	parse: 一个工具模块,提供了许多URL 处理方法,比如拆分、解析、合并等。	
	robotparser :主要是用来识别网站的robots.txt 文件,然后判断哪些网站可以爬,
			哪些网站不可以爬,它其实用得比较少。

request请求模块使用

import urllib.request

#返回一响应对象
response=urllib.request.urlopen("https://zhidao.baidu.com/question/539674215.html")

#打印响应对象类型和响应码。根据响应码可判断服务器的状态
#print(type(response),response.status)

#打印响应头信息
#for a in response.getheaders():
#    print(a)

#传入一个"Server",获取响应头的Server值,
# 该值代表服务器用什么搭建的。
#print(response.getheader("Server"))

#返回二进制数据对象(html内容)
#html=response.read()
#print(type(html))

#网页的编码格式确认:可以用浏览器打开需抓取的网页url,
#   打开开发者工具,找到html下<head> charset="gbk" </head>,"gbk"为编码格式之一
#对二进制数据解码。解码格式一定要与抓取网页的编码格式对应
#print(html.decode("gbk"))

向request请求模块传递参数

"""
import urllib.parse
import urllib.request

#传递了一个参数word,值是hello,它需要被转码成bytes(字节流)类型。
# 其中转字节流采用了bytes()方法
#urllib.parse 模块里的urlencode()方法来将参数字典转化为字符串.
# 第二个参数指定编码格式
data = bytes(urllib.parse.urlencode({'word':'hello'}), encoding="utf-8")

#如果传递了这个参数(data),则它的请求方式就不再是GET 方式,而是POST 方式。
response= urllib.request.urlopen('http://httpbin.org/post',data=data)

#我们传递的参数出现在了form 字段中,这表明是模拟了表单提交的方式,
# 以POST 方式传输数据。
print(response.read().decode("utf-8"))
"""

import urllib.request
#timeout 参数用于设置超时时间,单位为秒,
#意思就是如果请求超出了设置的这个时间,还没有得到响应,就会抛出异常。
response = urllib.request.urlopen('http://httpbin.org',timeout=0.1)
print(response.read().decode("utf-8"))

利用更强大的Request 类来构建:利用urlopen ()方法可以实现最基本请求的发起,但这几个简单的参数并不 足以构建一个完整的请求。

class urllib. request. Request ( ur 1, data=None, headers={}, origin_req_host=None, unverifiable=False, method =None)
第一个参数url用于请求URL,这是必传参数,其他都是可选参数。
第二个参数data 如果要传,必须传bytes (字节流)类型的。如果它是字典,可以先用urllib.parse 模块里的urlencode ()编码。
第三个参数headers 是一个字典,它就是请求头,我们可以在构造请求时通过headers 参数直 	接构造,
	也可以通过调用请求实例的add_ header ()方法添加。添加请求头最常用的用法就是通过修改User-Agent 来伪装浏览器
第四个参数origin_req_host 指的是请求方的host 名称或者IP 地址
第五个参数u nveri干iable 表示这个请求是否是无法验证的,默认是False ,意思就是说用户没有足够权限来选择接收这个请求的结果。
第六个参数method 是一个字符串,用来指示请求使用的方法
from urllib import request,parse
url='http://httpbin.org/post'
headers={
    'User-Agent':'Mozilla/4.0(compatible;MSIE 5.5;Windows NT)',
    'Host':'httpbin.org',
}
dict={
    'name':'Germey'
}

#urllib.parse 模块里的urlencode()方法来将参数字典转化为字符串.
# 其中转字节流采用了bytes()方法
data=bytes(parse.urlencode(dict),encoding="utf-8")
req = request.Request(url=url,data=data,headers=headers,method='POST')
#req .add_header('User-Agent','Mozilla/4 .0 (compatible; MSIE 5.5; Windows NT )')
response=request.urlopen(req)
print(response.read().decode('utf-8'))

更强大的工具Handler 登场了,利用它们,我们几乎可以做到HTTP请求中所有的事情。
urllib.request 模块里的BaseHandler 类,它是所有其他Handler 的父类,它提
供了最基本的方法。
另一个比较重要的类就是OpenerDirector ,我们可以称为Opener ,Opener 可以使用open()方法,返回的类型和urlopen()如出一辙。它和Handler 有什么关系呢?简而言之,就是利用Handler 来构建Opener 。

代理

from urllib.error import URLError
from urllib.request import  ProxyHandler,build_opener

proxy_handler=ProxyHandler({
    'http':'http://127.0.0.1:9734',
    'https':'https://127.0.0.1:9734'
})
opener=build_opener(proxy_handler)
try:
    response=opener.open('https://www.baidu.com')
    print(response.read().decode('utf-8'))
except URLError as e:
    print(e.reason)

Cookies

import http.cookiejar,urllib.request
cookie=http.cookiejar.CookieJar()
handler=urllib.request.HTTPCookieProcessor(cookie)
opener=urllib.request.build_opener(handler)
response=opener.open("http://www.baidu.com")
#打印出每条Cookie的名称和值
for item in cookie:
    print(item.name+"="+item.value)

将Cookies 保存成Mozilla 型浏览器的Cookies 格式

import http.cookiejar,urllib.request
#保存Cookie,生成cookies.txt
cookie=http.cookiejar.MozillaCookieJar("cookies.txt")
handler=urllib.request.HTTPCookieProcessor(cookie)
opener=urllib.request.build_opener(handler)
response=opener.open("http://www.baidu.com")
cookie.save(ignore_discard=True,ignore_expires=True)

保存成libwww-perl(LWP)格式的Cookies 文件
调用load ()方法来读取本地的Cookies 文件,获取到了Cookies 的内容

import http.cookiejar,urllib.request
#保存Cookie,生成cookies.txt
cookie=http.cookiejar.LWPCookieJar("cookies.txt")
handler=urllib.request.HTTPCookieProcessor(cookie)
opener=urllib.request.build_opener(handler)
response=opener.open("http://www.baidu.com")
cookie.save(ignore_discard=True,ignore_expires=True)

#读取本地的cookies.txt
cookie=http.cookiejar.LWPCookieJar()
cookie.load('cookies.txt',ignore_discard=True,ignore_expires=True)
handler=urllib.request.HTTPCookieProcessor(cookie)
opener=urllib.request.build_opener(handler)
response=opener.open('http://www.baidu.com')
print(response.read().decode('utf-8'))

处理异常

#处理异常
import urllib.request,urllib.error
#URLError类来自urlib库的error模块,它继承自OSError类,是error异常模块的基类
import urllib.error
try:
    response=urllib.request.urlopen("https://www.google.com")
#HTTPError是URLError的子类,专门用来处理HTTP请求错误。
#捕获其中一个与之对应的异常
except urllib.error.HTTPError as e:
    # 返回错误原因、HTTP状态码、请求头
    print(e.reason,e.code,e.headers,sep='\n')
except urllib.error.URLError as e:
    #返回错误原因
    print(e.reason)
else:
    print('Request Successfully')

做出更详细的异常判断

import socket,urllib.request,urllib.error
try:
    #设置超时时间2s
    response=urllib.request.urlopen('https://www.google.com',timeout=2)
except urllib.error.URLError as e:
    print(type(e.reason))
    #isinstance()判断它的类型
    if isinstance(e.reason,socket.timeout):
        print('TIME OUT')

urllib 库里还提供了parse 模块,它定义了处理URL 的标准接口,例如实现URL部
分的抽取、合并以及链接转换

#抽取
from urllib.parse import urlparse
result = urlparse('http://www.baidu.com/index.html;user?id=5#comment')
print(type(result), result)
"""
输出结果
		‘
		<class 'urllib.parse.ParseResult'> 
		ParseResult(scheme='http', netloc='www.baidu.com',
		path='/index.html', params='user', query='id=5', fragment='comment')
		’
	返回结果是一个ParseResult 类型的对象,它包含6 个部分,分别是scheme 、netloc 、
	path 、pa rams 、query 和fragment。scheme ,代表协议、netloc ,即域名、
	path ,即访问路径、params,代表参数、查询条件query、
	#后面是锚点,用于直接定位页面内部的下拉位置
"""
#抽取
result = urlparse('http://www.baidu.com/index.html;user?id=5#comment', allow_fragments=False)
print(result)
#返回结果ParseResult 实际上是一个元组,我们可以用索引顺序来获取,
#也可以用属性名获取。
print(result[0],result.scheme)
#allow_ fragments :即是否忽略fragment 。如果它被设置为False ,干ragment 部分就会被忽略,
#它会被解析为path 、parameters 或者query 的一部分,而fragment 部分为空。

# 合并
# urlparse()的对立方法urlunparse()
from urllib.parse import urlunparse
data = ['http', 'www.baidu.com', 'index.html', 'user', 'a=6', 'comment']
#接受的可迭代对象的参数个数必须为6个
print(urlunparse(data))
#抽取
#与urlparse()类似,只返回5个参数,只不过不在单独解析params
from urllib.parse import urlsplit
result = urlsplit('http://www.baidu.com/index.html;user?id=5#comment')
print(result)
# 合并
#与urlunparse()类似
from urllib.parse import urlunsplit
data = ['http', 'www.baidu.com', 'index.html', 'a=6', 'comment']
#接受的可迭代对象的参数个数必须为5个
print(urlunsplit(data))

#上诉方法提必须要有特定长度的对象,链接的每一部分都要清晰分开。

通过urljoin ()方法,我们可以轻松实现链接的解析、拼合与生成。

from urllib.parse import urljoin
#第一个参数为基础链接,第二个参数为新链接。该方法会分析base_url 的scheme 、netloc 和path
这3 个内容并对新链接缺失的部分进行补充,最后返回结果。
print(urljoin('http://www.baidu.com', 'FAQ.html'))

urlencode (),它在构造GET 请求参数的时候非常有用.

from urllib.parse import urlencode

params = {
    'name': 'germey',
    'age': 22
}
#字典类型转化为GET 请求参数
base_url = 'http://www.baidu.com?'
url = base_url + urlencode(params)
print(url)

#为上例的逆方法

from urllib.parse import parse_qs

query = 'name=germey&age=22'
#一串GET 请求参数,利用parse_qs()方法,就可以将它转回字典
print(parse_qs(query))

parse_qs l ()方法

from urllib.parse import parse_qsl
query = 'name=germey&age=22'
#它用于将参数转化为元组组成的列表
print(parse_qsl(query))
#运行结果是一个列表,而列表中的每一个元素都是一个元组,元组的第一个内容是参数名,
#第二个内容是参数值

quote(),该方法可以将内容转化为URL 编码的格式。URL 中带有中文参数时,
有时可能会导致乱码的问题,此时用这个方法可以将中文字符转化为URL 编码。

from urllib.parse import quote

keyword = '壁纸'
url = 'https://www.baidu.com/s?wd=' + quote(keyword)
print(url)

unquote()方法,它可以进行URL 解码.

from urllib.parse import unquote

url = 'https://www.baidu.com/s?wd=%E5%A3%81%E7%BA%B8'
print(unquote(url))

分析Robots 协议

Robots 协议也称作爬虫协议、机器人协议,它的全名叫作网络爬虫排除标准(Robots Exclusion Protocol ),用来告诉爬虫和搜索引擎哪些页面可以抓取,哪些不可以抓取。它通常是一个叫作robots .txt的文本文件,一般放在网站的根目录下。

当搜索爬虫访问一个站点时,它首先会检查这个站点根目录下是否存在robots.txt 文件,如果存在,搜索爬虫会根据其中定义的爬取范围来爬取。如果没有找到这个文件,搜索爬虫便会访问所有可直接访问的页面。

下面我们看一个robots.txt 的样例:
User-agent: *			->描述了搜索爬虫的名称。其设置为*则代表该协议对任何爬取爬虫有效。
Disallow: /				->指定了不允许抓取的目录,设置为/则代表不允许抓取所有页面。
Allow: /public/			->Allow 一般和Disallow 一起使用,用来排除某些限制。可以抓取public 目录。

这实现了对所有搜索爬虫只允许爬取public 目录的功能,将上述内容保存成robots.txt 文件,
放在网站的根目录下,和网站的人口文件放在一起。

了解Robots 协议之后,我们就可以使用robotparser 模块来解析robots.txt 了。

from urllib.robotparser import RobotFileParser

#rp = RobotFileParser('http://www.jianshu.com/robots.txt')
rp = RobotFileParser()
#用来设置robots.txt 文件的链接。
rp.set_url('http://www.jianshu.com/robots.txt')
#注意,这个方法执行一个读取和分析操作.这个方法不会返回任何内容,但是执行了读取操作。
rp.read()
#can_fetch()方法判断了网页是否可以被抓取。
#第一个是User-agent,第二个是要抓取的URL。返回结果是True 或False
print(rp.can_fetch('*', 'http://www.jianshu.com/p/b67554025d7d'))
print(rp.can_fetch('*', "http://www.jianshu.com/search?q=python&page=1&type=collections"))
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值