前面基本将爬虫的基础知识学习得差不多了,今天最后深入下requests模块,这个写完之后,一般的网站大家都可以去爬取了,后面会慢慢给大家分享一些烧脑的东西,今天还是先说说requests模块。
思考问题1:如果一个网站需要账号密码登录后才能获得自己想要的东西,这个时候怎么进行爬取呢?
答案分享:如果直接通过进去之后的网页的链接爬取,这个时候会报访问错误。其实我们想要做的就是让浏览器能够记录登录的过程,这里需要引入cookie这个概念,等我们在登录的时候,得到cookie,浏览器再带着cookie去请求下一个网页。抓取思路基本和前面的一样,就是增加了session会话,下面是获取17k小说书架的信息,代码如下:
# 浏览器如何记录登录的过程?
# 登录 -> 得到cookie
# 带着cookie去请求到书架url -> 书架上的内容
#
# 必须得把上面的两个操作连起来
# 我们可以使用session进行请求 -> session你可以认为是一连串的请求,在这个过程中的cookie不会丢失
import requests
import time
# session会话
session = requests.session()
# 1.登录
url = "https://passport.17k.com/ck/user/login"
data = {
"loginName": "XXXX", # 这里填写自己的账号
"password": "XXXXX" # 这里填写自己的密码
}
resp = session.post(url, data=data)
# print(resp.text)
# print(resp.cookies) # 看cookie
# 2.拿书架上的内容
# 直接通过刚才那个session获取,因为刚才那个session里面带有cookie
url_bookself = "https://user.17k.com/ck/author/shelf?page=1&appKey=2406394919"
resp_bookself = session.get(url_bookself)
datas = resp_bookself.json()['data']
for item in datas:
# 书名
bookname = item['bookName']
# 作者
author = item['authorPenName']
# 书籍分类
bookCategory = item['bookCategory']['name']
# 创作时间
createTimeValue = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(item['createTimeValue']/1000))
# 更新时间
updateTimeValue = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(item['updateTimeValue']/1000))
print(bookname, author, bookCategory, createTimeValue, updateTimeValue)
上面的代码一个是session,一个是time,这两个大家可以自行研究,还有一个是json,获得的json格式我这里单独给大家整理在下面,其实就是一个字典,然后从中提取出自己想要的内容:
获取的json格式,然后从json格式数据中提取想要的信息
{'status': {'code': 0, 'msg': 'succ'},
'data': [{'bookId': 3222462,
'bookName': '穿到三千小世界里当炮灰',
'coverImg': 'https://cdn.static.17k.com/book/189x272/62/24/3222462.jpg-189x272?v=1600827772000',
'authorId': 75291810,
'authorPenName': '时初四',
'introduction': '世上总有那么一些人,总是被天道偏爱,万中无一,金手指满满。',
'bookClass': {'id': 3, 'name': '女生'},
'bookChannel': {'id': 18, 'name': '幻想言情'},
'bookCategory': {'id': 172, 'name': '时空快穿'},
'authLevel': {'id': 4, 'name': 'VIP作品'},
'progress': 0,
'lastUpdateChapter': {'id': 42291581, 'name': '第333章 大结局:丧尸能吃吗', 'createTime': 1612285279000, 'updateTime': 1612287639000, 'isVIP': {'id': 1, 'name': '是'}, 'publishTime': 1612285409000},
'status': {'id': 4, 'name': '正常'},
'bookStatus': {'id': 3, 'name': '完本'},
'isVIP': {'id': 1, 'name': '是'},
'bookmarkChapterId': 42291581,
'bookmarkChapterName': '第333章 大结局:丧尸能吃吗',
'bookmarkChapterVipFlag': 1,
'topFlag': 0,
'createTimeValue': 1635478048000,
'updateTimeValue': 1645080007000,
'topTimeValue': 0,
'bookupdateTimeValue': 1667528548000,
'recCode': 'null1670660670511885',
'type': 5},
{'bookId': 3328785,
'bookName': '长生',
'coverImg': 'https://cdn.static.17k.com/book/189x272/85/87/3328785.jpg-189x272?v=1625066380000',
'authorId': 16439338,
'authorPenName': '风御九秋',
'introduction': '国之将亡,必有乱世妖孽,国之将亡,必有济世真人......',
'bookClass': {'id': 2, 'name': '男生'},
'bookChannel': {'id': 24, 'name': '仙侠武侠'},
'bookCategory': {'id': 9, 'name': '古典仙侠'},
'authLevel': {'id': 4, 'name': 'VIP作品'},
'progress': 0,
'lastUpdateChapter': {'id': 47451236, 'name': '第五百四十九章 铁锅王八', 'createTime': 1670601548000, 'updateTime': 1670601849000, 'isVIP': {'id': 1, 'name': '是'}, 'publishTime': 1670601549000},
'status': {'id': 4, 'name': '正常'},
'bookStatus': {'id': 1, 'name': '连载'},
'isVIP': {'id': 1, 'name': '是'},
'bookmarkChapterId': 0,
'bookmarkChapterName': '',
'bookmarkChapterVipFlag': 0,
'topFlag': 0,
'createTimeValue': 1635478074000,
'updateTimeValue': 1635478074000,
'topTimeValue': 0,
'bookupdateTimeValue': 1670601849000,
'recCode': 'null1670660670511885',
'type': 5}
],
'num': 20,
'curPage': 1,
'totalNum': 2,
'totalPage': 1,
'hasMore': 0,
'time': 1670660670000}
上面代码运行的结果如下:
思考问题2:如果一个网站是从另一个网站跳转过来,并且单独访问这个网站的时候访问失败,它需要你告知从指定的网站跳转过来才有用,这种又该如何爬取?
答案分享:这个叫做防盗链机制。需要知道你是从哪个网站跳转过来的,接下来看一个例子,下载梨视频里面的视频文件。如果直接从https://pearvideo.com/videoStatus.jsp?contId=1530514&mrd=0.919094593210594进行抓取会提示报错,需要在访问头部加上上一跳的网址信息,"Referer": f"https://pearvideo.com/video_{contId}"代码如下:
# 1.拿到contID
# 2.拿到videoStatus返回的json -> srcURL
# 3.srcURl里面的内容进行修整
# 4.拿到真实的url下载视频
import requests
# 拉取视频的网址
# url = "https://pearvideo.com/video_1465967"
url = "https://pearvideo.com/video_1530514"
contId = url.split("_")[1]
# 准备代理信息
proxy = {
"http": "http://220.181.111.37:80",
"http": "http://61.135.169.121:80",
"http": "http://120.197.179.166:8080",
}
videoStatusUrl = f"https://pearvideo.com/videoStatus.jsp?contId={contId}&mrd=0.9190945932105943"
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36",
# 防盗链:溯源,当前本次请求的上一级是谁
"Referer": f"https://pearvideo.com/video_{contId}"
}
resp = requests.get(videoStatusUrl, headers=headers)
dic = resp.json()
srcUrl = dic['videoInfo']['videos']['srcUrl']
systemTime = dic['systemTime']
srcUrl = srcUrl.replace(systemTime, f"cont-{contId}")
# print(srcUrl)
# 下载视频
with open("c.mp4", mode="wb") as f:
f.write(requests.get(srcUrl, proxies=proxy).content)
print("视频下载完成!")
上面的代码运行后的结果是可以直接将视频下载到本地。上面代码还涉及到两个知识点值得大家关注,一个是下载视频和下载图片是一样的,都是用open函数,另外一个是里面用到了代理机制,大家可以研究下,这里给大家提供一个免费的代理IP的网址:https://ip.jiangxianli.com/?page=1
到此爬虫的基本操作就说完了,大家可以根据上面的一些知识去爬一些简单的东西了,比如爬取歌曲、图片、文章、视频等。