1. 程式人生 > >Python 模擬登入知乎

Python 模擬登入知乎

前言

前天看到一個爬取了知乎50多萬評論的帖子, 羨慕的同時也想自己來嘗試一下。看看能不能獲取一些有價值的資訊。

必備知識點

下面簡單的來談談我對常見的防爬蟲的一些技巧的理解。

headers

現在很多伺服器都對爬蟲進行了限制,有一個很通用的處理就是檢測“客戶端”的headers。通過這個簡單的判斷就可以判斷出客戶端是爬蟲程式還是真實的使用者。(雖然這一招在Python中可以很輕鬆的解決)。

Referer

referer欄位很實用,一方面可以用於站內資料的防盜鏈。比如我們經常遇到的在別處複製的圖片連結,粘到我們的部落格中出現了“被和諧”的字樣。
這就是referer起到的作用,伺服器在接收到一個請求的時候先判斷Referer是否為本站的地址。如果是的話就返回正確的資源;如果不是,就返回給客戶端預先準備好的“警示”資源。
Referer欄位


所以再寫爬蟲的時候(尤其是爬人家圖片的時候),加上Referer欄位會很有幫助。

User-Agent

User-Agent欄位更是沒的說了。相信絕大部分有防爬長處理的網站都會判斷這個欄位。來檢測客戶端是爬蟲程式還是瀏覽器。

如果是爬蟲程式(沒有新增header的程式),伺服器肯定不會返回正確的內容啦;如果包含了這個欄位,才會進行到下一步的防爬蟲處理操作。
如果網站僅僅做到了這一步,而你的程式又恰好添加了User-Agent,基本上就可以順利的矇混過關了。
User-Agent欄位

隱藏域

很多時候,我們模擬登入的時候需要提交的資料並不僅僅是使用者名稱密碼,還有一些隱藏域的資料。比如拿咱們CSDN來說,檢視登入頁

https://passport.csdn.net/account/login

的時候,你會發現原始碼中有這樣的內容:
隱藏域

也就是說,如果你的程式僅僅post了username和password。那麼是不可能進入到webflow流程的。因為伺服器端接收請求的時候還會判斷有沒有lt和execution這兩個隱藏域的內容。

其他

防止爬蟲還有很多措施,我本人經驗還少,所以不能在這裡一一列舉了。如果您有相關的經驗,不妨留下評論,我會及時的更新到部落格中,我非常的贊同大家秉承學習的理念來交流。

模擬登入

在正式的模擬登入知乎之前,我先來寫個簡單的小例子來加深一下印象。

模擬防爬

模擬防爬肯定是需要伺服器端的支援了,下面簡單的寫一下來模擬整個過程。

伺服器端

login.php

先來看看: login.php

<?php
/**
 * @Author: 郭 璞
 * @File: login.php
 * @Time: 2017/4/7
 * @Contact: [email protected]
 * @blog: http://blog.csdn.net/marksinoberg
 * @Description:  模擬防爬處理
 **/

$username = $_POST['username'];
$password = $_POST['password'];
$token = $_POST['token'];

if (!isset($token)) {
    echo "登入失敗!";
    exit(0);
}else{
    // 這裡簡單的模擬一下token的計算規則,實際中會比這更加的複雜
    $target_token = $username.$username;
    if ($token == $target_token){
        if ($username ==='123456' and $password==='123456'){
            echo "登陸成功!<br>使用者名稱: ".$username."<br>密碼:".$password."<br>token: ".$token;
        }else{
            echo "使用者名稱或密碼錯誤!";
        }
    }else{
        echo "token 驗證失敗!";
    }
}
login.html

相對應的前端程式碼簡單的寫成下面: login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>郭璞的小窩</title>
</head>
<body>

<form action="login.php" method="post">
    使用者名稱: <input type="text" name="username" id="username" required><br>
    密&nbsp;&nbsp;碼:<input type="password" name="password" required><br>
    <input type="hidden" name="token" id="token" value="">
    <hr>
    <input type="submit" value="登入">
</form>
<script>
    document.getElementById('username').onblur = function() {
        var username = document.getElementById("username").value;
        var token = document.getElementById('token');
        token.value = username+username;
    }
</script>

</body>
</html>
瀏覽器測試
正常提交使用者名稱密碼的話如下:

正確提交資訊

我們不難發現,伺服器端和客戶端使用了相同的計算規則,這樣的話我們就可以實現對客戶端的登入請求進行一次簡答的甄選了。正常的瀏覽器請求都是沒有問題的。

使用者名稱或者密碼填寫錯誤的情況如下:

使用者名稱密碼出錯的情況

爬蟲沒有新增隱藏域時

用爬蟲程式執行的話,如果沒有新增隱藏域的內容,我們就不可能正確地登入了。那麼先來看下這樣的傻瓜式爬蟲是怎麼失效的吧。
使用Python寫一個這樣的爬蟲用不了多少程式碼,那麼就用Python來寫吧。其他的介面測試工具postman,selenium等等也都是很方便的,這裡暫且不予考慮。

# coding: utf8

# @Author: 郭 璞
# @File: sillyway.py                                                                 
# @Time: 2017/4/7                                   
# @Contact: 1064319632@qq.com
# @blog: http://blog.csdn.net/marksinoberg
# @Description: 傻瓜式爬蟲未新增隱藏域的值

import requests

url = "http://localhost/phpstorm/pachong/login.php"

payload = {
    'username': '123456',
    'password': '123456'
}

response = requests.post(url=url, data=payload)
print(response.text)

執行的結果如下:
傻瓜式爬蟲,未新增隱藏域資訊

對比PHP檔案對於請求的處理,我們可以更加輕鬆的明白這個邏輯。

添加了隱藏域的爬蟲

正如上面失敗的案例,我們明白了要新增隱藏域的值的必要性。那麼下面來改進一下。

因為我們”不知道”伺服器端是怎麼對token處理的具體的邏輯。所以還是需要從客戶端的網頁下手。
且看下面的圖片。
客戶端隱藏域內容獲取

注意:這裡僅僅是為了演示的方便,採用了對username欄位失去焦點時計算token。實際上在網頁被拉取到客戶端瀏覽器的時候, 伺服器會事先計算好token的值,並賦予到token欄位的。所以大可不必計較這裡的實現。

Python程式碼

# coding: utf8

# @Author: 郭 璞
# @File: addhiddenvalue.py                                                                 
# @Time: 2017/4/7                                   
# @Contact: [email protected]
# @blog: http://blog.csdn.net/marksinoberg
# @Description: 添加了隱藏域資訊的爬蟲

import requests

## 先獲取一下token的內容值,方便接下來的處理
url = 'http://localhost/phpstorm/pachong/login.php'

payload = {
    'username': '123456',
    'password': '123456',
    'token': '123456123456'
}

response = requests.post(url, data=payload)
print(response.text)

實現效果如下:
添加了token域內容的爬蟲效果

現在是否對於隱藏域有了更深的認識了呢?

知乎模擬登入

按照我們剛才的邏輯,我們要做的就是:

先開啟預登陸介面,目標:得到必須提交的隱藏域的值
然後通過post再次訪問該路徑(準備好了一切必須的資訊)
獲取網頁內容並進行解析,或者做其他的處理。

思路很清晰了,下面就可以直接上程式碼了。

# coding: utf8

# @Author: 郭 璞
# @File: ZhiHuLogin.py                                                                 
# @Time: 2017/4/7                                   
# @Contact: [email protected]
# @blog: http://blog.csdn.net/marksinoberg
# @Description: 模擬登陸知乎
import re
from bs4 import BeautifulSoup
import subprocess, os
import json
import requests

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.86 Safari/537.36",
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
    "Accept-Encoding": "gzip, deflate",
    "Host": "www.zhihu.com",
    "Upgrade-Insecure-Requests": "1",
}

############################# 從郵箱方式登入
loginurl = 'http://www.zhihu.com/login/email'
session = requests.session()
html = session.get(url=loginurl, headers=headers).text
soup = BeautifulSoup(html, 'html.parser')
print(soup)
xsrf_token = soup.find('input', {'name':'_xsrf'})['value']
print("登入xsrf_token: "+xsrf_token)

############################ 下載驗證碼備用
checkcodeurl = 'http://www.zhihu.com/captcha.gif'
checkcode = session.get(url=checkcodeurl, headers=headers).content
with open('./checkcode.png', 'wb') as f:
    f.write(checkcode)
print('已經開啟驗證碼,請輸入')
# subprocess.call('./checkcode.png', shell=True)
os.startfile(r'checkcode.png')
checkcode = input('請輸入驗證碼:')
os.remove(r'checkcode.png')
############################ 開始登陸
payload = {
    '_xsrf': xsrf_token,
    'email': input('請輸入使用者名稱:'),
    'password': getpass.getpass(prompt="請輸入密碼:"),#input('請輸入密碼:'),
    'remeber_me': 'true',
    'captcha': checkcode
}
response = session.post(loginurl, data=payload)
print("*"*100)

result = response.text
print("登入訊息為:"+result)
tempurl = 'https://www.zhihu.com/question/57964452/answer/155231804'
tempresponse = session.get(tempurl, headers=headers)
soup = BeautifulSoup(tempresponse.text, 'html.parser')
print(soup.title)

實現的效果如下

模擬登入知乎效果

介面,我們正確的獲取到了title的內容。(也許你會說,正常訪問也會獲取到這個內容的,但是我們是從已登入的session上獲取的,請記住這一點哈。)。

更新版知乎模擬登陸

程式碼部分

# coding: utf8

# @Author: 郭 璞
# @File: MyZhiHuLogin.py                                                                 
# @Time: 2017/4/8                                   
# @Contact: [email protected]
# @blog: http://blog.csdn.net/marksinoberg
# @Description: 我的模擬登入知乎

import requests
from bs4 import BeautifulSoup
import os, time
import re
# import http.cookiejar as cookielib

# 構造 Request headers
agent = 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Mobile Safari/537.36'
headers = {
    "Host": "www.zhihu.com",
    "Referer": "https://www.zhihu.com/",
    'User-Agent': agent
}

######### 構造用於網路請求的session
session = requests.Session()
# session.cookies = cookielib.LWPCookieJar(filename='zhihucookie')
# try:
#     session.cookies.load(ignore_discard=True)
# except:
#     print('cookie 檔案未能載入')

############ 獲取xsrf_token
homeurl = 'https://www.zhihu.com'
homeresponse = session.get(url=homeurl, headers=headers)
homesoup = BeautifulSoup(homeresponse.text, 'html.parser')
xsrfinput = homesoup.find('input', {'name': '_xsrf'})
xsrf_token = xsrfinput['value']
print("獲取到的xsrf_token為: ", xsrf_token)

########## 獲取驗證碼檔案
randomtime = str(int(time.time() * 1000))
captchaurl = 'https://www.zhihu.com/captcha.gif?r='+\
             randomtime+"&type=login"
captcharesponse = session.get(url=captchaurl, headers=headers)
with open('checkcode.gif', 'wb') as f:
    f.write(captcharesponse.content)
    f.close()
# os.startfile('checkcode.gif')
captcha = input('請輸入驗證碼:')
print(captcha)

########### 開始登陸
headers['X-Xsrftoken'] = xsrf_token
headers['X-Requested-With'] = 'XMLHttpRequest'
loginurl = 'https://www.zhihu.com/login/email'
postdata = {
    '_xsrf': xsrf_token,
    'email': '郵箱@qq.com',
    'password': '密碼'
}
loginresponse = session.post(url=loginurl, headers=headers, data=postdata)
print('伺服器端返回響應碼:', loginresponse.status_code)
print(loginresponse.json())
# 驗證碼問題輸入導致失敗: 猜測這個問題是由於session中對於驗證碼的請求過期導致
if loginresponse.json()['r']==1:
    # 重新輸入驗證碼,再次執行程式碼則正常。也就是說可以再第一次不輸入驗證碼,或者輸入一個錯誤的驗證碼,只有第二次才是有效的
    randomtime = str(int(time.time() * 1000))
    captchaurl = 'https://www.zhihu.com/captcha.gif?r=' + \
                 randomtime + "&type=login"
    captcharesponse = session.get(url=captchaurl, headers=headers)
    with open('checkcode.gif', 'wb') as f:
        f.write(captcharesponse.content)
        f.close()
    os.startfile('checkcode.gif')
    captcha = input('請輸入驗證碼:')
    print(captcha)

    postdata['captcha'] = captcha
    loginresponse = session.post(url=loginurl, headers=headers, data=postdata)
    print('伺服器端返回響應碼:', loginresponse.status_code)
    print(loginresponse.json())




##########################儲存登陸後的cookie資訊
# session.cookies.save()
############################判斷是否登入成功
profileurl = 'https://www.zhihu.com/settings/profile'
profileresponse = session.get(url=profileurl, headers=headers)
print('profile頁面響應碼:', profileresponse.status_code)
profilesoup = BeautifulSoup(profileresponse.text, 'html.parser')
div = profilesoup.find('div', {'id': 'rename-section'})
print(div)

驗證效果

更新版知乎模擬登陸

總結

經過了今天的測試,發現自己之前對於網頁的處理理解的還是不夠到位。

  • 對於“靜態頁面”,常用的urllib, requests應該是可以滿足需要的了。

  • 對於動態頁面的爬取,可以使用無頭瀏覽器PhantomJS,Selenium等來實現。

但是一直處理的不夠精簡,導致在爬一些重定向頁面的過程中出現了很多意想不到的問題。

在這塊的爬蟲程式還有很多地方需要進行完善啊。

另外模擬登入還有一個利器,那就是cookie。下次有時間的話再來學習一下使用cookie來實現。今天就先到這裡吧。

相關推薦

Python 模擬登入

前言 前天看到一個爬取了知乎50多萬評論的帖子, 羨慕的同時也想自己來嘗試一下。看看能不能獲取一些有價值的資訊。 必備知識點 下面簡單的來談談我對常見的防爬蟲的一些技巧的理解。 headers 現在很多伺服器都對爬蟲進行了限制,有一個

Python 爬蟲-模擬登入-爬取拉勾網職位資訊

用Python寫爬蟲是很方便的,最近看了xlzd.me的文章,他的文章寫的很到位,提供了很好的思路。因為他的文章部分程式碼省略了。下面是基於他的文章的三個程式碼片段: 基於Python3,Python2的話需要修改下input輸入函式和print的用法。 爬取豆瓣電影top250 爬取拉勾網職位資訊 模擬

[Python]網路爬蟲(三):使用cookiejar管理cookie 以及 模擬登入

大家好哈,上一節我們研究了一下爬蟲的異常處理問題,那麼接下來我們一起來看一下Cookie的使用。 為什麼要使用Cookie呢? Cookie,指某些網站為了辨別使用者身份、進行session跟蹤而儲存在使用者本地終端上的資料(通常經過加密) 比如說有些網站需要登入後才

python--python3爬蟲之模擬登入

程式碼在python3環境下測試通過: from bs4 import BeautifulSoup import requests url = 'http://www.zhihu.com' login_url = url+'/login/email' captcha_

selenium 模擬登入和微博

sleep https epo element select selenium clas .com -c pip install selenium __author__ = ‘admin‘ __date__ = 2017 / 11 / 3 from selenium im

爬蟲入門到精通-headers的詳細講解(模擬登入

直接開始案例吧。 本次我們實現如何模擬登陸知乎。 1.抓包 首先開啟知乎登入頁 知乎 - 與世界分享你的知識、經驗和見解 注意開啟開發者工具後點擊“preserve log”,密碼記得故意輸入錯誤,然後點選登入   我們很簡單的就找到了 我們需要的請

selenium模擬登入

Selenium是一個用於Web應用程式測試的工具。Selenium測試直接執行在瀏覽器中,就像真正的使用者在操作一樣。支援的瀏覽器包括IE(7, 8, 9, 10, 11),Mozilla Firefox,Safari,Google Chrome,Opera等。這個工具的主

Python3 模擬登入(requests)

# -*- coding: utf-8 -*- """ 知乎登入分為兩種登入 一是手機登入 API : https://www.zhihu.com/login/phone_num 二是郵箱登入 API : https://www.zhihu.c

python requests登入

這裡用python模擬登入知乎,並確定登入的情況:class ZhiHu(object): headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:47.0)'

Python3下模擬登入

程式碼: # -*- coding:UTF-8 -*- import requests , time import hmac ,json from bs4 import BeautifulSoup from hashlib import sha1 def get_

python爬蟲模擬登陸

自從暑假學了大概一個月左右的爬蟲,開學之後就沒怎麼搞爬蟲了,當時也就學到scrapy框架就放下了,大致瞭解了一下框架,不是太理解,但是在這之前本人的爬蟲水平也僅僅侷限於爬取簡單頁面,爬取動態頁面也稍微瞭解下,但是一直沒有學模擬登陸,因為當時怎麼也搞不懂模擬登陸是

python爬蟲scrapy框架——人工識別登入倒立文字驗證碼和數字英文驗證碼(2)

import scrapy import re import json class ZhihuSpider(scrapy.Spider): name = 'zhihu' allowed_domains = ['www.zhihu.com'] start_urls = ['http

Python爬蟲倒立文字驗證碼登入

引言 本文解析了知乎倒立文字驗證碼的原理,人工識別倒立文字所在位置後組織報文成功登入。 原理 關於登入的基本原理可參考Python爬蟲之模擬知乎登入,只不過這篇文章中登入的驗證碼為“數字英文”模式,而當前登入時是“點選倒立文字”模式,所以主要記錄這部分。

Python爬蟲之模擬登陸

在chrome瀏覽器下抓取登陸過程的包(注意把Preserve log勾上): 表單的結構主要包括_xsrf, password, phone_num 我們要找到_xsrf的值,重新載入zhihu.

python爬蟲scrapy框架——人工識別登入倒立文字驗證碼和數字英文驗證碼

import requests try: import cookielib except: import http.cookiejar as cookielib import re import time def get_xsrf(): # 獲取xsrf code res

利用python requests庫模擬登陸

當初搜模擬登陸的時候在知乎上也找到一些內容。 以下是程式碼 import requests import time import json import os import re import sys import subprocess from bs4 import Be

Python模擬登入豆瓣網,並爬取小組信息

count alias pass spa .post windows chrome apr ror import requests from bs4 import BeautifulSoup from PIL import Image headers = { ‘

Python爬去上問題下所有圖片

sts dal b- log email token db4 trie fin from zhihu_oauth import ZhihuClient from zhihu_oauth.exception import NeedCaptchaException cli

Scrapy Selenium實戰:Selenium登入儲存cookies後訪問需要登入頁面

Scrapy Selenium實戰:Selenium登入知乎儲存cookies後訪問需要登入頁面 安裝 chromedriver 新建爬蟲 zhihu.py 獲取瀏覽器真實的User-Agent 執行驗證

python爬取專欄使用者評論資訊

工具:python3,pycharm,火狐瀏覽器 模組:json,requests,time 登入知乎,進入專欄。 進入後隨便選擇一個專欄,我們選擇一個粉絲比較多的。點選進去。 其實,我們可以爬取這個專欄的所有文章,開啟開發者工具F12,點選重新整理 找