带大家抓一波豆瓣电视剧
一、requests模块学习
使用requests前
- pip install requests
发送get、post请求
- response=requests.get(url) 发送get请求,请求url地址对应的响应
- response=requests.post(url,data={请求体的字典})
response的使用方法
- response.text text方法容易中文乱码 ,它是根据猜测的编码进行编码
,使用encoding方法
response.encoding("utf-8")
response.text
- response.content content方法返回的是二进制响应内容,出现乱码使用decode方法,把响应的二进制转化为字符串
response.content.decode()
编码默认是utf-8
- 正确获取网页内容的方法
response.content.decode()
response.content.decode("gbk")
response.text
带headers的请求方法
有些网页请求的时候,已经识别出你是爬虫程序,不给你正确的响应内容
需要带headers请求头,为了模仿自己是个浏览器去请求,避免反爬
- headers在哪里
根据下图操作,一般请求网页只需要User_Agent就行,具体问题具体分析,其他网页需要不断尝试 - headers请求示例
headers请求写出字典结构
headers={"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36 Edg/87.0.664.66",
"Referer": "https://cn.bing.com/",
...
}
requests.get(url,headers=headers)
使用cookie的请求方法
- 直接把cookie写成字典格式写入headers请求
- 把cookie做成示例
cookie="anonymid=kjcs3aiq-tq2pyp; depovince=GW; jebecookies=8ee72b68-e77c-4f48-b2e1-2f418f2487b4|||||; _r01_=1; JSESSIONID=abcW1HIVGf9LHhcqTM4Ax; ick_login=d169f86a-6143-4093-9128-48ac5f7e5a98; taihe_bi_sdk_uid=75381c376c2d706ce29141114dd426a1; taihe_bi_sdk_session=b04269186269459f41dba554e2cdc9c9"
#写成字典表达式,整体根据";"进行切割,每一块根据等于号进行切割
cookie={i.split("=")[0]:i.split("=")[-1]for i in cookie.split(";")}
requests.get(url,headers=headers,cookies=cookie)
- 使用session发生post请求,获取cookie,在发送get请求
session=requests.session() #session和requests方法相似
session.post(url,data=data,headers=headers)
session.get(url,headers=headers)
使用超时参数
- timeout
为防止服务器不能及时响应,大部分发至外部服务器的请求都应该带着 timeout 参数。在默认情况下,除非显式指定了 timeout 值,requests 是不会自动进行超时处理的。如果没有 timeout,你的代码可能会挂起若干分钟甚至更长时间。
requests.get(url,headers=headers,timeout=3) 就是网页请求的时候三秒内必须反应,否则就会报错
二、retrying模块学习
使用前需要pip install retrying
-retrying
工作中经常碰到的问题就是,某个方法出现了异常,重试几次。循环重复一个方法是很常见的。比如爬虫中的获取代理,对获取失败的情况进行重试。
retrying提供一个装饰器函数retry,被装饰的函数会在运行失败的情况下重新执行,默认一直报错就一直重试。
- retrying示例
from retrying import retry
@retry(stop_max_attempt_number=5)
#5次失败以后就会报错,不设置参数默认一直尝试
def get_proxies(self):
r = requests.get('代理地址')
print('正在获取')
raise Exception("异常")
print('获取到最新代理 = %s' % r.text)
params = dict()
if r and r.status_code == 200:
proxy = str(r.content, encoding='utf-8')
params['http'] = 'http://' + proxy
params['https'] = 'https://' + proxy
三、json模块学习
json库提供了几个API:
- json.dumps(): 将字典序列化为json字符串
- json.loads(): 将json字符串反序列化为字典
- json.dump(): 将字典序列化到一个文件,是文本文件,就是相当于将序列化后的json字符串写入到一个文件
- json.load(): 从文件中反序列出字典
总结: 不带s的是序列到文件或者从文件中反序列化,带s的是都在内存中操作不涉及到持久化
json示例
import josn
for content in content_list:
data=json.dumps(content,ensure_ascii=False)
#ensure_ascii=False 这是因为json.dumps 序列化时对中文默认使用的ascii编码.想输出真正的中文需要指定ensure_ascii=False:
四、开始今天的豆瓣电视剧抓取
- 分析网页
可以看出数据动态加载数据,很明显是json数据,为了好找到数据请求,可以先进行清空
找到数据,点击数据请求,选择Preview选项,然后再根据请求的url里关键词精确寻找其他url
- 分析url链接
- 写出代码整体架构
#导入需要用到的库
import requests
import json
from retrying import retry
#先建一个类 doubanspider
class doubanspider():
def __init__(self):
self.base_url="https://movie.douban.com/j/search_subjects?type=tv&tag=%E7%83%AD%E9%97%A8&sort=recommend&page_limit=20&page_start={}"
@retry(stop_max_attempt_number=3)
def parse_url(self,url): #定义一个请求url的方法
pass
def get_content_list(self,html_str): #定义一个获取json数据的方法
pass
def save_content(self,conten_list): #定义一个保存数据的方法
pass
def main(self): #定义一个主程序逻辑
pass
if __name__ == '__main__': #主程序入口
douban=doubanspider() #实例化一个对象
douban.main()
- 整体代码
# -*- coding: utf-8 -*-
"""
@author: XCHEN
@contact: 1272012812@QQ.com
@software: PyCharm
@file: douban.py
@time: 2020/12/31 13:00
"""
# 导入模块
# -*- coding: utf-8 -*-
"""
@author: XCHEN
@contact: 1272012812@QQ.com
@software: PyCharm
@file: douban.py
@time: 2020/12/31 13:00
"""
# 导入模块
import requests
import time
import json
from retrying import retry
headers={"User-Agent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Mobile Safari/537.36 Edg/87.0.664.66"}
class doubanspider:
def __init__(self):
self.base_url="https://movie.douban.com/j/search_subjects?type=tv&tag=%E7%83%AD%E9%97%A8&sort=recommend&page_limit=20&page_start={}"
@retry(stop_max_attempt_number=3)
# 请求url
def parse_url(self,url):
response=requests.get(url,headers=headers,timeout=5).content.decode()
time.sleep(0.5)
try:
html_str=response
except:
html_str=None
return html_str
# 获取json数据
def get_content_list(self,html_str):
dic_data=json.loads(html_str)
content_list=dic_data["subjects"]
return content_list
#保存json数据
def save_content1(self,content_list):
num=0
with open("doban.txt","a",encoding="utf-8") as f:
for contents in content_list:
num+=1
data=json.dumps(contents,ensure_ascii=False)
f.write(data)
f.write("\n")
print("<---------------------抓取了{}条数据------------>".format(len(content_list)),"\n")
#保存海报数据
def save_content2(self,context_list):
for contents in context_list:
dict = {
"title": contents["title"],
"cover": contents["cover"]
}
with open("./dobanpic/{}.jpg".format(dict["title"]), "wb") as f:
pic = requests.get(dict["cover"]).content
print("<----------------{}.jpg保存成功-------------->".format(dict["title"]))
f.write(pic)
#主函数逻辑
def main(self):
num=0
#可以根据自己抓取的需求,我这里直接死循环了
while True:
start_url=self.base_url.format(num)
html_str=self.parse_url(start_url)
data=self.get_content_list(html_str)
self.save_content1(data)
self.save_content2(data)
num+=10
#主程序入口
if __name__ == '__main__':
doban=doubanspider()
doban.main()
- 效果展示
新兴博主,多多关注哦。。。