知乎内容需要登陆后才能查看,与之前案例不同,这里要向浏览器提交登录信息。
首先爬取知乎登录页面
def getHtmlText(url):
try:
r = requests.get(url)
r.encoding = 'utf-8'
return r.text
except:
return ''
url = 'https://www.zhihu.com/'
getHtmlText(url)
'<html><body><h1>500 Server Error</h1>\nAn internal server error occured.\n</body></html>\n'
此时出现 500 Server Error,解决方法为通过 headers={...} 更改用户代理为浏览器
def getHtmlText(url):
headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36'}
try:
r = requests.get(url, headers = headers)
r.encoding = 'utf-8'
return r.text
except:
return ''
在知乎登录页面打开Chrome浏览器F12,这里打钩之后新跳转的页面的信息就不会覆盖之前接受到的信息,输入账号密码点击登录,就可以看到需要提交的表单数据。
版本一:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import requests
import re
import time
from PIL import Image
from bs4 import BeautifulSoup
import json
# 构造 Request headers
# 登陆的url地址
logn_url = 'http://www.zhihu.com/#signin'
session = requests.session()
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.82 Safari/537.36',
}
content = session.get(logn_url, headers=headers).content
soup = BeautifulSoup(content, 'html.parser')
def getxsrf():
return soup.find('input', attrs={'name': "_xsrf"})['value']
# 获取验证码
def get_captcha():
t = str(int(time.time() * 1000))
captcha_url = 'http://www.zhihu.com/captcha.gif?r=' + t + "&type=login"
r = session.get(captcha_url, headers=headers)
with open('captcha.jpg', 'wb') as f:
f.write(r.content)
f.close()
im = Image.open('captcha.jpg')
im.show()
im.close()
captcha = input("please input the captcha\n>")
return captcha
def isLogin():
# 通过查看用户个人信息来判断是否已经登录
url = "https://www.zhihu.com/settings/profile"
login_code = session.get(url, allow_redirects=False).status_code
if int(x=login_code) == 200:
return True
else:
return False
def login(secret, account):
# 通过输入的用户名判断是否是手机号
if re.match(r"^1\d{10}$", account):
print("手机号登录 \n")
post_url = 'http://www.zhihu.com/login/phone_num'
postdata = {
'_xsrf': getxsrf(),
'password': secret,
'remember_me': 'true',
'phone_num': account,
}
else:
print("邮箱登录 \n")
post_url = 'http://www.zhihu.com/login/email'
postdata = {
'_xsrf': getxsrf(),
'password': secret,
'remember_me': 'true',
'email': account,
}
try:
# 不需要验证码直接登录成功
login_page = session.post(post_url, data=postdata, headers=headers)
login_code = login_page.text
print(login_page.status)
print(login_code)
except:
# 需要输入验证码后才能登录成功
postdata["captcha"] = get_captcha()
login_page = session.post(post_url, data=postdata, headers=headers)
login_code = eval(login_page.text)
print(login_code['msg'])
if __name__ == '__main__':
if isLogin():
print('您已经登录')
else:
account = input('请输入你的用户名\n> ')
secret = input("请输入你的密码\n> ")
login(secret, account)
存在问题:运到验证码为“点击图中倒立文字或移动滑块至”,则登陆失败,跳转到登录界面。听说可以用打码平台解决
版本二(来自某知乎er):
打开你要爬取信息的界面,发出请求查看所需 headers,比较重要的有 'User-Agent' 和 ‘cookie’,对应添加
import requests
import re
url='https://www.zhihu.com/question/22591304/followers'
headers={
'User-Agent':
'Cookie':}
page=requests.get(url,headers=headers).text
imgs=re.findall(r'<img src=\"(.*?)_m.jpg',page)
查看 imgs 即可看到匹配的图片
以下是一段爬取知乎头像的代码:
# -*- coding: utf-8 -*-
#py3.6
import requests
import urllib
import re
import random
from time import sleep
def main():
url='https://www.zhihu.com/question/22591304/followers'
headers={ 'User-Agent':'', 'Cookie':''}
i=1
for x in range(20,40,20):
data={'start':'0',
'offset':str(i),
'_xsrf':'2e65c02ceeaaa1ac16d193415cf8d5be'}
page=requests.post(url,headers=headers,data=data,timeout=50).text
imgs=re.findall(r'<img src=\\"(.*?)_m.jpg',page)
#在爬下来的json上用正则提取图片地址,去掉_m为大图
for img in imgs:
try:
img=img.replace('\\','')
#去掉\字符这个干扰成分
pic=img+'.jpg'
path='d:\\zhihu\\'+str(i)+'.jpg'
#声明存储地址及图片名称
urllib.request.urlretrieve(pic,path)
#下载图片
print(u'下载了第'+str(i)+u'张图片')
i+=1
sleep(random.uniform(0.5,1))
#睡眠函数用于防止爬取过快被封IP
except:
pass
sleep(random.uniform(0.5,1))
if __name__=='__main__':
main()
貌似 get 和 post 方法返回的 .text 形式不一样, post 会用 \\" 转义表示 ”,而 get 不会;
另外,data 中 '_xsrf' 在 F12 Form Data 中没找到,但必不可少,难道隐藏了?要用抓包工具?