urllib与requests爬虫简介 -- 潘登同学的爬虫笔记
第一个爬虫程序
from urllib.request import urlopen
response = urlopen("http://www.baidu.com/")
print(response.read().decode())
urllib的基本使用
- requset.urlopen(url,data,timeout):打开一个url,并返回一个response对象。
- url:要打开的url地址。
- data:如果是POST请求,则需要提供要发送的数据。
- timeout:设置请求超时时间,单位为秒。
- response.read():读取response的内容,返回bytes类型
- response.getcode():返回 HTTP的响应码,成功返回200,4服务器页面出错,5服务器问题
- response.geturl():返回实际请求的url地址
- response.info():返回response的头部信息
Request对象的使用
使用urllib.request.urlopen发送请求时,可以将参数封装到一个Request对象中。
from urllib.request import urlopen
from urllib.request import Request
url = 'http://www.server.com/login'
user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'
headers = { 'User-Agent' : user_agent }
request = Request(url, headers=headers)
response = urlopen(request)
page = response.read()
运行结果和直接传递URL完全一样的,只不过中间多了一个request对象,推荐大家这么写,因为在构建请求时还需要加入好多内容,通过构建一个request,服务器响应请求得到应答,这样显得逻辑上清晰明确
urllib发送get请求
Get请求的参数都是在Url中体现的,如果有中文,需要转码,这时我们可使用
- urllib.parse.urlencode() 转换键值对
- urllib.parse. quote() 转换一个值
from urllib.request import urlopen,Request
from urllib.parse import quote
args =input('请输入要搜索的内容:')
ua = UserAgent()
url = f'https://www.baidu.com/s?wd=
{quote(args)}'
# 或者
# parms ={
# 'wd':args
# }
# url = f'http://www.baidu.com/s?ie=utf-8&f=8&rsv_bp=1&tn=baidu&{urlencode(parms)}'
headers = {
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36 Edg/101.0.1210.47'
}
req = Request(url,headers = headers)
resp = urlopen(req)
print(resp.read().decode())
实战-喜马拉雅网站
喜马拉雅网站音乐栏目 https://www.ximalaya.com/yinyue/
from urllib.request import urlopen,Request
from time import sleep
def spider_music(_type,page):
for num in range(1, page+1):
if num == 1:
url = f'https://www.ximalaya.com/yinyue/{_type}'
else:
url = f'https://www.ximalaya.com/yinyue/{_type}/p{num}/'
headers = {
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36 Edg/101.0.1210.47'
}
req = Request(url,headers = headers)
resp = urlopen(req)
html = resp.read().decode()
# 解析html
# 保存数据
# 休息一会儿
sleep(1)
print(f'第{num}页数据爬取完成')
if __name__ == '__main__':
spider_music('minyao',10)
urllib发送post请求
如何查看post请求的参数名称:可以随便发送一些数据,在网络中的login请求中,点击载荷,可以查看到参数名称。
from urllib.request import Request,urlopen
from urllib.parse import urlencode
url = 'https://www.kuaidaili.com/login/'
# 封装数据
data = {
'next': '/login/?next=%2F',
'login_type': '1',
'username': '398707160@qq.com',
'passwd': '111111111',
}
tru_data = urlencode(data).encode()
# 封装头信息
headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.63 Safari/537.36'}
# 封装Request对象
req = Request(url,data=tru_data,headers=headers)
resp = urlopen(req)
print(resp.read().decode())
动态页面获取数据
有时在访问了请求后,并不能获取想要的数据。很大的原因之一就是,当前的页面是动态的。目前网络的页面分为2大类:
- 静态页面:特征:访问有UI页面URL,可以直接获取数据
- 动态页面(AJAX):特征:访问有UI页面URL,不能获取数据。需要抓取新的请求获取数据
有些网页内容使用AJAX加载,而AJAX一般返回的是JSON,直接对AJAX地址进行post或get,就返回JSON数据了
情形:https://www.hupu.com/页面有新闻,不断向下拉可以加载更多新闻,但是不能直接获取数据,需要使用AJAX加载数据。
from urllib.request import urlopen,Request
import json
url = 'https://www.hupu.com/home/v1/news?page=2&pageSize=50'
headers = {
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.63 Safari/537.36'
}
req = Request(url,headers=headers)
resp = urlopen(req)
html = resp.read().decode()
print(html)
'''
静态
访问地址栏里的数据就可以获取到想要的数据。
动态
访问地址栏里的数据就可以获取不到想要的数据。
解决方案:抓包
打开浏览器的开发者工具-network-xhr,找到可以获取到数据的url访问即可
'''
请求 SSL证书验证
现在随处可见 https 开头的网站,urllib可以为 HTTPS 请求验证SSL证书,就像web浏览器一样,如果网站的SSL证书是经过CA认证的,则能够正常访问
如果SSL证书验证不通过,或者操作系统不信任服务器的安全证书,比如浏览器在访问12306网站的时候,会警告用户证书不受信任。(据说 12306 网站证书是自己做的,没有通过CA认证)
import ssl
# 忽略SSL安全认证
context = ssl._create_unverified_context()
# 添加到context参数里
response = urlopen(request, context = context)
伪装自己的爬虫-请求头
- User-Agent:浏览器的标识,可以伪装成浏览器,让网站认为是浏览器访问。
有些网站不会同意程序直接用上面的方式进行访问,如果识别有问题,那么站点根本不会响应,所以为了完全模拟浏览器的工作,要使用faked-useragent库。
pip install fake-useragent
from fake_useragent import UserAgent
ua = UserAgent()
url = 'http://httpbin.org/get'
headers = {
'User-Agent':ua.random
}
req = Request(url,headers=headers)
resp = urlopen(req)
print(resp.read().decode())
注意
- fake-useragent 在创建对象时,可能创建不了,多部分原因为服务器访问不到的原因
- 解决方案:拷贝
fake-useragent_version.json
的配置文件到用户目录C:\Users\Feel\AppData\Local\Temp
urllib的底层原理
当你获取一个URL你使用一个opener(一个urllib.OpenerDirector的实例)。在前面,我们都是使用的默认的opener,也就是urlopen。它是一个特殊的opener,可以理解成opener的一个特殊实例,传入的参数仅仅是url,data,timeout。
如果我们需要用到Cookie,只用这个opener是不能达到目的的,所以我们需要创建更一般的opener来实现对Cookie的设置
from urllib.request import Request,build_opener
from fake_useragent import UserAgent
url = 'http://httpbin.org/get'
headers = {
'User-Agent':UserAgent().random
}
req = Request(url,headers=headers)
opener = build_opener()
resp = opener.open(req)
print(resp.read().decode())
handler能实现一些附加的功能,如要显示headers,可以用HTTPHandler。
from urllib.request import Request,build_opener,HTTPHandler
from fake_useragent import UserAgent
url = 'http://httpbin.org/get'
headers = {
'User-Agent':UserAgent().random
}
req = Request(url,headers=headers)
opener = build_opener(HTTPHandler(debuglevel=1))
resp = opener.open(req)
print(resp.read().decode())
伪装自己的爬虫-设置代理
爬虫设置代理就是让别的服务器或电脑代替自己的服务器去获取数据
- 透明代理:目标网站知道你使用了代理并且知道你的源IP地址,这种代理显然不符合我们这里使用代理的初衷
- 匿名代理:匿名程度比较低,也就是网站知道你使用了代理,但是并不知道你的源IP地址
- 高匿代理:这是最保险的方式,目标网站既不知道你使用的代理更不知道你的源IP
from urllib.request import Request,build_opener,ProxyHandler
from fake_useragent import UserAgent
# 设置访问地址
url = 'http://httpbin.org/get'
# 设置请求对象
req = Request(url)
# 构建可以使用代理的控制器
handler = ProxyHandler({'http': 'http://101.10.13.10:3128'})
# 构建opener
opener = build_opener(handler)
# 发送请求
resp = opener.open(req)
print(resp.read().decode())
爬虫cookie的使用
网络部分信息或APP的信息,若是想获取数据时,需要提前做一些操作,往往是需要登录,或者提前访问过某些页面才可以获取到!!
其实底层就是在网页里面增加了Cookie信息。cookie通常在请求头里设置,而urllib的Request对象可以设置headers信息。
- 登录获取cookie,点击检查,查看network,找到访问的url地址,找到cookie信息,复制到本地,保存到本地文件。
from urllib.request import Request,build_opener
from fake_useragent import UserAgent
url ='https://www.kuaidaili.com/usercenter/overview'
headers = {
'User-Agent':UserAgent().chrome,
'Cookie':'channelid=0; sid=1621786217815170; _ga=GA1.2.301996636.1621786363; _gid=GA1.2.699625050.1621786363; Hm_lvt_7ed65b1cc4b810e9fd37959c9bb51b31=1621 786363,1621823311; _gat=1; Hm_lpvt_7ed65b1cc4b810e9fd37959c9bb51b31=162 1823382; sessionid=48cc80a5da3a451c2fa3ce682d29fde7'
}
req = Request(url,headers= headers)
opener = build_opener()
resp = opener.open(req)
print(resp.read().decode())
代码登录-并保持登录状态
问题
- 不想手动复制cookie,太繁琐了!
解决方案
- 在再代码中执行登录操作,并保持Cookie不丢失
from urllib.request import Request,urlopen,HTTPCookieProcessor
from fake_useragent import UserAgent
url = 'https://www.kuaidaili.com/login/'
headers = {
'User-Agent':UserAgent().chrome
}
# 发送请求,用于登录用户
data = {
'next': '/',
'login_type': '1',
'username': '398707160@qq.com',
'passwd': '111111111',
}
tru_data = urlencode(data).encode()
req = Request(url,data=tru_data,headers=headers)
handler = HTTPCookieProcessor()
opener = build_opener(handler)
resp = opener.open(req)
# 发送请求,获取数据
index_url = 'https://www.kuaidaili.com/usercenter/overview'
index_req = Request(index_url,headers=headers)
resp = opener.open(index_req)
print(resp.read().decode())
爬虫保存与读取cookie
我们可以利用本模块的http.cookiejar.CookieJar类的对象来捕获cookie并在后续连接请求时重新发送,比如可以实现模拟登录功能。该模块主要的对象有CookieJar、FileCookieJar、MozillaCookieJar、LWPCookieJar
from urllib.request import Request,urlopen,HTTPCookieProcessor
from fake_useragent import UserAgent
from http.cookiejar import MozillaCookieJar
def save_cookie():
url = 'https://www.kuaidaili.com/login/'
headers = {
'User-Agent':UserAgent().chrome
}
# 发送请求,用于登录用户
data = {
'next': '/',
'login_type': '1',
'username': '398707160@qq.com',
'passwd': '111111111',
}
tru_data = urlencode(data).encode()
req = Request(url,data=tru_data,headers=headers)
# 创建保存cookie的对象
cookie_jar = MozillaCookieJar()
handler = HTTPCookieProcessor(cookie_jar)
opener = build_opener(handler)
resp = opener.open(req)
cookie_jar.save('cookie.txt',ignore_discard=True,ignore_expires=True)
def load_cookie():
# 发送请求,获取数据
index_url = 'https://www.kuaidaili.com/usercenter/overview'
index_req = Request(index_url,headers=headers)
# 加载cookie
cookie_jar = MozillaCookieJar()
cookie_jar.load('cookie.txt',ignore_discard=True,ignore_expires=True)
handler = HTTPCookieProcessor(cookie_jar)
resp = opener.build_opener(handler).open(index_req)
print(resp.read().decode())
if __name__ == '__main__':
save_cookie()
load_cookie()
保存的cookie有有效期,如果cookie过期,则需要重新登录获取。
urllib的异常处理
from urllib.request import Request,urlopen
from urllib.error import URLError,HTTPError
from fake_useragent import UserAgent
url = 'https://www.itbaizhan.com/stages/id/xxssee'
headers = {
'User-Agent':UserAgent().chrome
}
req = Request(url,headers=headers)
try:
resp = urlopen(req)
print(resp.read().decode())
except URLError as e:
if e.args:
# 打印状态码
print(e.args[0].errno)
else:
print(e.code)
print('爬取完成')
requests模块
pip install requests
import requests
from fake_useragent import UserAgent
def requests_get():
url = 'https://www.baidu.com/s'
headers = {
'User-Agent':UserAgent().chrome
}
params = {
'wd':'python爬虫'
}
try:
response = requests.get(url,headers=headers,params=params)
print(response.text)
except requests.exceptions.RequestException as e:
print(e)
def requests_post():
url = 'https://www.kuaidaili.com/login/'
headers = {
'User-Agent':UserAgent().chrome
}
data = {
'next': '/',
'login_type': '1',
'username': '398707160@qq.com',
'passwd': '111111111',
}
try:
response = requests.post(url,headers=headers,data=data)
print(response.text)
except requests.exceptions.RequestException as e:
print(e)
requests伪装爬虫
- User-Agent:浏览器的标识,可以伪装成浏览器,让网站认为是浏览器访问。
import requests
from fake_useragent import UserAgent
def requests_get():
url = 'http://httpbin.org/get'
headers = {'User-Agent':UserAgent().chrome}
resp = requests.get(url,headers=headers)
print(resp.text)
def requests_proxy():
url = 'http://httpbin.org/get'
headers = {'User-Agent':UserAgent().chrome}
proxy = {
'http': 'http://101.10.13.10:3128'
}
resp = requests.get(url,headers=headers,proxies=proxy)
设置超时时间
可以通过timeout属性设置超时时间,一旦超过这个时间还没获得响应内容,就会提示错误
url = 'http://github.com'
headers = {'User-Agent':UserAgent().chrome}
resp = requests.get(url,headers=headers, timeout=0.001)
print(resp.text)
session自动保存cookies
seesion的意思是保持一个会话,比如 登陆后继续操作(记录身份信息) 而requests是单次请求的请求,身份信息不会被记录
import requests
from fake_useragent import UserAgent
def requests_session():
url = 'https://www.kuaidaili.com/login/'
headers = {
'User-Agent':UserAgent().chrome
}
data = {
'next': '/',
'login_type': '1',
'username': '398707160@qq.com',
'passwd': '111111111',
}
# 创建一个session对象
s = requests.Session()
response = s.post(url,headers=headers,data=data)
# 发送请求,获取数据
index_url = 'https://www.kuaidaili.com/usercenter/overview'
index_req = Request(index_url,headers=headers)
response = s.get(index_url,headers=headers)
# 用session对象发出get请求,设置cookies
s.get('http://httpbin.org/cookies/set/sessioncookie/123456789')
ssl验证
# 禁用安全请求警告
requests.packages.urllib3.disable_warnings()
resp = requests.get(url, verify=False, headers=headers)