一开始是想爬取毒液这部电影的影评,于是开始做了一个爬取的毒液,发现爬取了10页以后就会跳出错误,然后就发现了需要登陆豆瓣以后才能爬取,于是做了一个模拟登陆的。
1,需要点一个持续日志,才能看到。
登录豆瓣是向服务器发送一个post请求2,于是我们查看了post发送的数据到底是什么:
post请求中的数据第一次我只考虑的地方很少,却忘记了,假如需要验证码的是什么,所以当出现验证码的时候,进行了分析。
当有验证码的时候,post请求中的数据3,所以我们要去获取网页中的验证码的url以及验证码的id:
获取img标签下的src,以及valeu运用正则表达式,去获取。
def _get_captcha_info(url,user,password):
captcha_info=dict()
response=requests.get(url,headers=req_headers)
if response.status_code==200:
html=response.text
#验证码url
pat =re.compile(r'<img id="captcha_image" src="(.*?)" alt="captcha" class="captcha_image"/>',re.S)
response_1 =re.search(pat,html)
if response_1:
captcha_url =response_1.group(1)
print("验证码图片:{}".format(captcha_url))
captcha_solution =input('验证码:')
captcha_info['captcha-solution']=captcha_solution
#验证码ID
pat1 =re.compile(r'<input type="hidden" name="captcha-id" value="(.*?)"/>',re.S)
response_2 =re.search(pat1,html)
if response_2:
captcha_id =response_2.group(1)
captcha_info['captcha-id']=captcha_id
return captcha_info
4,在这里我们要运用requests.session().post()去向服务器发送post请求
session()就是一个与服务器进行会话的过程,是一个持续性的。
def login(self,url,user,password):
#登录
req_headers={
'User-Agent':"Mozilla/5.0 (X11; U; Linux x86_64; zh-CN; rv:1.9.2.10) Gecko/"
"20100922 Ubuntu/10.10 (maverick) Firefox/3.6.10"
}
self.url =url
self.user =user
self.password =password
req_data={
'source':'index_nav',
'redir': 'https://www.douban.com/',
'login':'登录',
'form_email':user,
'form_password':password
}
# 添加验证码信息到请求体中
captcha_info=_get_captcha_info(url,user,password)
if captcha_info:
req_data.update(captcha_info)
# 使用Session post数据
session=requests.Session()
resp=session.post(url,data=req_data,headers=req_headers)
return session
于是将这整个封装为一个DoubanLogin类,返回的是一个session对象。
5,于是我们便可以爬取毒液中的所有影评了:
直接用session对毒液影评的url进行请求,因为session是一个持续性的,session中以及是有我们登录的账号在上面了
def getHtml(session,start):
data={
'start':start,
'limit':'20',
'sort':'new_score',
'status':'P'
}
try:
url=r'https://movie.douban.com/subject/3168101/comments?'+urlencode(data)
print(url)
response =session.get(url,headers=headers)
if response.status_code==200:
return response.text
return None
except RequestException:
print('请求失败')
return None
6,因为每一页显示了20位用户的评论,我先通过用BeautifulSoup提取每个用户的评论块,然后用正则提取评论人的名称,推荐指数,评论日期,评论内容
def get_user(session,start):
rows=[]
Html =getHtml(session,start)
# print(Html)
soup =bs4.BeautifulSoup(Html,'lxml')
users=soup.select('div[class="comment-item"]')
for use in users:
result =dowload(use)
if result:
rows.append(result)
doload_Cvs(rows)
def dowload(use):
use =str(use)
pat =re.compile(r'<a class="" href=".*?">(.*?)</a>.*?<span class="allstar.*?rating" title="(.*?)"></span>.*?<span class="comment-time " title="(.*?)">.*?<span class="short">(.*?)</span>',re.S)
response =re.search(pat,use)
if response:
response =response.groups(1)
name =response[0]
sore =response[1]
time =response[2][0:11]
comment =response[3]
return{
'name':name,
'sore':sore,
'time':time,
'comment':comment
}
7,保存爬取后的数据
这里我选择是保存在了本地的csv文件中
注意的是当我在保存的时候,老是出现了编码上的错误,需要encode='utf_8_sig'
def doload_Cvs(rows):
#注意encoding='utf_8_sig'
with open('douban.csv','a+',encoding='utf_8_sig',newline='') as f:
headers =['name','time','sore','comment']
#以字典的形式写入
fcsv=csv.DictWriter(f,fieldnames=headers)
file_size =os.path.getsize('douban.csv')
#判断文件是否存在,如果存在就不需要写入头部名称了
if file_size==0:
#写入第一行头部名称
fcsv.writeheader()
#写入多行
fcsv.writerows(rows)
print('下载成功')
8,结果
图片.png
9,接下来的任务是做一个可视化的数据,来分析这些数据中的内容
网友评论