首先,須要理解cookies的含義,是存儲在瀏覽器中的內容,在本地存儲任意鍵值對,第一次訪問時服務器返回一個id存儲到本地cookie中,第二次訪問將cookies一塊兒發送到服務器中
html
常見http狀態碼python
code | 說明 |
---|---|
200 | 請求成功 |
301/302 | 永久重定向/臨時重定向 |
403 | 沒有權限訪問 |
404 | 沒有對應的資源 |
500 | 服務器錯誤 |
503 | 服務器停機或正在維護 |
要爬取知乎內容首先須要進行登陸,在本文中咱們主要介紹2種登陸方式,第一種是經過requests的session保存cookies進行登陸,第二種是經過scrapy
修改start_requests
函數進行登陸瀏覽器
在utils中新建zhihu_login.py
,實例化一個session對象,設置其cookies對象爲cookiesjar
庫中的LWPCookieJar
對象,設置requests庫須要用到的headrs(從瀏覽器中進行拷貝),服務器
session = requests.session() session.cookies = cookiejar.LWPCookieJar(filename='zhihu_cookies.txt') headers = { 'User-Agent':'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36', 'Origin':'https://www.zhihu.com', 'Accept-Language':'zh-CN,zh;q=0.8,en;q=0.6', 'Host':'www.zhihu.com', 'Referer':'https://www.zhihu.com/' }
接下來,咱們要尋找登陸發送數據的頁面,首先打開zhihu.com
退出以前的登陸,來到一個登陸頁面,在登錄頁面中使用手機號碼登陸,此時須要發送一個錯誤的信息給頁面,以找到post數據的網頁(若是輸入正確的帳號密碼就直接登陸成功了,一大堆網頁請求就找不到咱們須要的網頁了)cookie
找到了須要post的網頁,發現post的數據有_xsrf
,passoword
,phone_num
,另一個captcha_type
沒有用,加了以後反而沒法訪問(不知道爲何)session
def zhihu_login(account, password): if re.match('1\d{10}', account): phone_post_url = 'https://www.zhihu.com/login/phone_num' post_data={ '_xsrf':get_xsrf(), 'phone_num':account, 'password':password, # 'captcha_type':'cn' } # session_response = session.post(phone_post_url, data=post_data, headers=header) # print(session_response.text) # result_list = re.findall('"msg": "(.*?)"',session_response.text)[0] # print(result_list.encode('utf8').decode('unicode-escape')) # try: # login_page = session.post(phone_post_url, data=post_data, headers=headers) # print('不要驗證碼,login_code:{}'.format(login_page.status_code)) # except: post_data['captcha'] = get_captcha() login_page = session.post(phone_post_url, data=post_data, headers=headers) result_list = re.findall('"msg": "(.*?)"', login_page.text)[0] print(result_list.encode('utf8').decode('unicode-escape')) session.cookies.save() print('保存成功')
在這裏咱們一開始沒有使用驗證碼,發現只要是爬蟲登陸都會被識別到,因此咱們編寫了一個用於生成驗證碼的代碼:app
def get_captcha(): t = str(int(time.time()*1000)) captcha_url = 'https://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) try: im = Image.open('captcha.jpg') im.show() im.close() except: print('wrong') captcha = input('請輸入驗證碼:') return captcha
保存完cookies,咱們嘗試使用這個cookies再次登陸scrapy
def get_again(): try: session.cookies.load(ignore_discard=True) print('cookies加載成功\n') except: print('cookies加載失敗') response = session.get('https://www.zhihu.com',headers=headers) # response.encoding = response.apparent_encoding with open('my_zhihu_login.html','wb') as f: f.write(response.text.encode('utf8')) print('保存頁面成功')
查看這個頁面發現不停地刷新,暫時尚未找到辦法ide
首先生成一個新的spider,名字爲zhihu函數
在class zhihu中定義headers等信息,重寫start_requests
函數
def start_requests(self): return [scrapy.Request('https://www.zhihu.com/#signin',headers=self.headers, callback=self.login)]
在start_requests
裏面返回一個新的Request,其回調函數設置爲一個新的login函數以下:
def login(self,response): # print(response.text) # a = '<input type="hidden" name="_xsrf" value="36424865b408db8c3f976a1a676cad60"/>' match_obj = re.match('.*name="_xsrf" value="(.*?)"', response.text, re.DOTALL) if match_obj: _xsrf = match_obj.group(1) post_data = { '_xsrf': _xsrf, 'phone_num': 'xxxxxxxxxxx', 'password': 'xxxxxxx', 'captcha':'' } t = str(int(time.time() * 1000)) captcha_url = 'https://www.zhihu.com/captcha.gif?r=' + t + "&type=login" return [scrapy.Request(url=captcha_url, meta={'post_data':post_data}, headers=self.headers, callback=self.get_captcha_login)] else: raise EOFError