爬蟲基本原理

1、爬蟲是什麼

一、什麼是互聯網?互聯網創建的目的?

  互聯網由網絡設備和一臺臺計算機鏈接而成,像一張網同樣。css

  互聯網的核心價值在於數據的共享/傳遞:數據是存放於一臺臺計算機上的,而將計算機互聯到一塊兒的目的就是爲了可以方便彼此之間的數據共享/傳遞,不然你只能拿U盤去別人的計算機上拷貝數據了。html

二、什麼是上網?爬蟲須要作什麼?

  所謂上網即是用戶端計算機發送請求給目標計算機,將目標計算機的數據下載到本地的過程。python

(1)經過瀏覽器上網時,用戶獲取網絡數據的方式是:git

  瀏覽器提交請求——>下載網頁代碼——>解析/渲染成頁面。github

(2)爬蟲獲取網絡數據的過程:ajax

  模擬瀏覽器發送請求——>下載網頁代碼——>只提取有用的數據——>存放於數據庫或文件中。正則表達式

(3)這兩種獲取方式區別:數據庫

  爬蟲程序只提取網頁代碼中對咱們有用的數據。json

三、爬蟲概念總結

(1)爬蟲比喻瀏覽器

  若是咱們把互聯網比做一張大的蜘蛛網,那一臺計算機上的數據即是蜘蛛網上的一個獵物,而爬蟲程序就是一隻小蜘蛛,沿着蜘蛛網抓取本身想要的獵物/數據

(2)爬蟲定義

  爬蟲經過代碼僞造瀏覽器發起請求,獲取資源後分析並提取有用數據的程序。

(3)爬蟲價值

  互聯網中最有價值的即是數據,好比天貓商城的商品信息,鏈家網的租房信息,雪球網的證券投資信息等等,這些數據都表明了各個行業的真金白銀,能夠說,誰掌握了行業內的第一手數據,誰就成了整個行業的主宰,若是把整個互聯網的數據比喻爲一座寶藏,那爬蟲就是來教你們如何來高效地挖掘這些寶藏,掌握了爬蟲技能,你就成了全部互聯網信息公司幕後的老闆,換言之,它們都在免費爲你提供有價值的數據。

2、爬蟲的基本流程

  

一、發起請求

  使用http庫向目標站點發起請求,即發送一個Request。Request包含:請求頭、請求體等。

二、獲取響應內容

  若是服務器能正常響應,則會獲得一個Response。Response包含:html,json,圖片,視頻等。

三、解析內容

  解析html數據:正則表達式,第三方解析庫如Beatifulsoup,pyquery等。

  解析json數據:json模塊。

  解析二進制數據:以b的方式寫入文件。

四、保存數據

  數據庫、文件

3、請求和響應

一、Request(請求)

  用戶將本身的信息經過瀏覽器(socket client)發送給服務器(socket server)。

(1)請求方式

  經常使用的請求方式:GET,POST 其餘請求方式:HEAD,PUT,DELETE,OPTHONS

  post與get請求最終都會拼接成這種形式:k1=xxx&k2=yyy&k3=zzz

  post請求的參數放在請求體內: 可用瀏覽器查看,存放於form data內

  get請求的參數直接放在url後。

(2)請求url

  url全稱統一資源定位符,如一個網頁文檔,一張圖片 一個視頻等均可以用url惟一來肯定。

  url編碼:https://www.baidu.com/s?wd=圖片,圖片會被編碼(看示例代碼)。

  網頁的加載過程是: 加載一個網頁,一般都是先加載document文檔, 在解析document文檔的時候,遇到連接,則針對超連接發起下載圖片的請求

(3)請求頭  

  user-agent:請求頭中若是沒有user-agent客戶端配置, 服務端可能將你當作一個非法用戶

  host:

  cookies:cookie用來保存登陸信息

  注意:通常作爬蟲都會加上請求頭。

(4)請求體

  若是是get方式,請求體沒有內容

  若是是post方式,請求體是format data

  注意: 1)登陸窗口,文件上傳等,信息都會被附加到請求體內

        2)登陸,輸入錯誤的用戶名密碼,而後提交,就能夠看到post;正確登陸後頁面一般會跳轉,沒法捕捉到post。

二、Response(響應)

  服務器接收請求,分析用戶發來的請求信息,而後返回數據(返回的數據中可能包含其餘連接,如:圖片,js,css等) 

  瀏覽器在接收Response後,會解析其內容來顯示給用戶,而爬蟲程序在模擬瀏覽器發送請求而後接收Response後,是要提取其中的有用數據。

(1)響應狀態

    200:表明成功
    301:表明跳轉
    404:文件不存在
    403:權限
    502:服務器錯誤

(2)Response header

  set-cookie:可能有多個,是來告訴瀏覽器,把cookie保存下來。

(3)preview就是網頁源代碼

  最主要的部分,包含了請求資源的內容,如網頁html,圖片二進制數據等。

4、項目示例

一、示例一:爬取汽車之家新聞資訊

"""
爬取汽車之家新聞頁面數據
"""
import requests   # pip3 install requests
from bs4 import BeautifulSoup
import os


# 1.僞造瀏覽器發送請求
r1 = requests.get(
    url="http://www.autohome.com.cn/news/"
)

r1.encoding = "gbk"   # 字節按照gbk編碼返回
# print(r1.text)   # 響應體
# print(r1.headers)   # 響應頭


# 2.去響應體中解析出想要的數據
soup = BeautifulSoup(r1.text, "html.parser")

# 3.找名字按照規則:div標籤且id=auto-channel-layload-article
container = soup.find(name="div", attrs={'id': "auto-channel-lazyload-article"})

# 4.去container中找全部li標籤
li_list = container.find_all(name="li")
for tag in li_list:
    # print(tag)   # li標籤內的全部內容

    """ 文章標題 """
    title = tag.find(name="h3")
    if not title:
        # h3爲空的時候
        continue

    # 這裏拿到的title是標籤對象
    # print(title, type(title))   # <h3>16家銀行/萬億授信 一汽將發力新能源</h3> <class 'bs4.element.Tag'>

    # title.text拿到標籤文本
    print(title.text)       # 文章標題內容:樁跟車走 沃爾沃收購移動充電公司股份

    """ 文章簡介 """
    summary = tag.find(name="p")
    print(summary.text)     # 文章簡介:[汽車之家 新聞]  據中國一汽官方消息,日前中...各銀行給中國一汽意向性授...

    """ 文章地址 """
    a = tag.find(name="a")
    # summary.attrs:打印出全部的標籤屬性
    # print(a.attrs)            # {'href': '//www.autohome.com.cn/news/201810/924097.html#pvareaid=102624'}
    # 能夠發現a.attrs獲得的是一個字典,所以能夠用get方法回去字典值
    # print(a.attrs.get('href'))  # //www.autohome.com.cn/news/201810/924096.html#pvareaid=102624
    url = "https:" + a.attrs.get('href')
    print(url)              # https://www.autohome.com.cn/news/201810/924097.html#pvareaid=102624

    """ 文章配圖地址 """
    img = tag.find(name="img")
    img_url = "https:" + img.get("src")  # 內部直接調用attrs.get
    print(img_url)         # 圖片地址輸出:https://www3.autoimg.cn/newsdfs/8K1Z4867.jpg

    """ 下載圖片到本地imgs """
    r2 = requests.get(
        url=img_url
    )
    file_name = img_url.rsplit('/', maxsplit=1)[1]
    file_path = os.path.join('imgs', file_name)

    with open(file_path, "wb") as f:
        f.write(r2.content)

二、示例二:抓取抽屜新熱榜新聞(攜帶user-agent)

"""
爬取抽屜新熱榜新聞數據
"""

import requests
from bs4 import BeautifulSoup
import os


# 1.僞造瀏覽器發送請求
r1 = requests.get(
    url="https://dig.chouti.com/",

    # 假裝請求頭
    headers={
        "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36"
    }
)

# print(r1.text)

# 2.去響應體中解析出想要的數據
soup = BeautifulSoup(r1.text, "html.parser")

# 3.找名字按照規則:div標籤且id=content-list
container = soup.find(name="div", attrs={"id": "content-list"})

# 4.去container中找到全部新聞內容
li_list = container.find_all(name="div", attrs={"class": "item"})

for tag in li_list:
    # print(tag)   # 每條新聞的全部內容

    """ 文章標題 """
    title = tag.find(name="a", attrs={"class": "show-content"})
    print("標題:", title.text.strip())   # strip():去除先後多餘的空格

    """ 文章簡介 """
    summary = tag.find(name="span", attrs={"class": "summary"})
    if not summary:
        continue
    print("摘要:", summary.text)

    """ 文章地址 """
    a = tag.find(name="a", attrs={"class": "show-content"})
    url = a.attrs.get('href')
    print("地址:", url)

    """ 文章配圖地址 """
    img = tag.find(name="img")
    img_url = "https:" + img.get("original")    # 內部直接調用attrs.get
    print("圖片地址:", img_url)

    """ 下載圖片帶本地/imgs_2 """
    r2 = requests.get(
        url=img_url
    )
    file_name = img_url.rsplit('/', maxsplit=1)[1]  # 取圖片名
    file_name = file_name.rsplit('?', maxsplit=1)[0]
    file_path = os.path.join('imgs_2', file_name)

    with open(file_path, "wb") as f:
        f.write(r2.content)

三、示例三:對抽屜中新聞點贊

  第一次訪問保留cookie,登陸時須要再次攜帶。

"""
經過代碼進行自動登陸,而後對新聞點贊
"""
import requests

# ####################### 第一部分:登陸 ######################

# 僞造瀏覽器發送get請求
r1 = requests.get(
    url="https://dig.chouti.com/",
    # 假裝請求頭
    headers={
        "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36"
    }
)

# print(r1.text)   # 響應體
# print(r1.headers)   # 響應頭
# 查看cookie
r1_cookie_dict = r1.cookies.get_dict()
print(r1_cookie_dict)   # {'gpsd': 'a3b15f31b3f3c9815cf4a8202c1ba0a4', 'JSESSIONID': 'aaaMJJh_RM5aC-2uGWzAw'}


# 僞造瀏覽器發送post請求
r2 = requests.post(
    url="https://dig.chouti.com/login",   # 在瀏覽器嘗試登陸,控制檯查看Network下login請求信息
    # 假裝請求頭
    headers={
        "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36"
    },
    # 僞造要發送的請求體數據
    data={
        "phone": "8618687883720",   # 帳戶
        "password": "w*****p",         # 密碼
        "oneMonth":1
    },
    # 抽屜的防護爬蟲策略:不看頁面直接發POST的獲得的cookie是錯誤的。第一次頁面訪問獲得的cookie纔是真的cookie
    cookies=r1_cookie_dict
)

# 查看返回結果
print(r2.text)
"""
錯誤:{"result":{"code":"21101", "message":"手機號或密碼錯誤", "data":{}}}
正確:{"result":{"code":"9999", "message":"", "data":{"complateReg":"0","destJid":"cdu_54078126953"}}}
"""

# ####################### 第二部分:點贊 ######################
r3 = requests.post(
    url="https://dig.chouti.com/link/vote?linksId=22886331",
    # 假裝請求頭
    headers={
        "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36"
    },
    cookies=r1_cookie_dict
)

# 查看返回結果
print(r3.text)
"""
{"result":{"code":"30010", "message":"你已經推薦過了", "data":""}}
"""

  注意:抽屜的防護爬蟲策略:不看頁面直接發POST的獲得的cookie是錯誤的。頁面訪問獲得的cookie纔是真的cookie。

四、示例四:自動登陸github

(1)瀏覽器登陸github分析

  故意輸入錯誤的帳戶密碼登陸github:

  

  查看提交的post請求數據:

  

  服務響應頁面是https://github.com/session,查看源碼中form表單中token信息

  

(2)代碼以下 

import requests
from bs4 import BeautifulSoup


# ########### 僞造瀏覽器發送get請求 #############
r1 = requests.get(
    url="https://github.com/login"
)
s1 = BeautifulSoup(r1.text, 'html.parser')

# 拿到token信息
token = s1.find(name="input", attrs={"name": "authenticity_token"}).get("value")
print(token)    # Y/OZ1lHKUHW0+...vMWEvRCzUrtkw==

# 拿到cookie
r1_cookie_dict = r1.cookies.get_dict()


# ########### 僞造瀏覽器發送post請求 ##############
r2 = requests.post(
    url="https://github.com/session",
    data={
        "commit": "Sign in",
        "utf8": "✓",
        "authenticity_token": token,
        "login": "hxxxxxx6",
        "password": "xxxxxxxx"
    },
    cookies=r1_cookie_dict
)

r2_cookie_dict = r2.cookies.get_dict()


# #########僞造瀏覽器發送get請求,嘗試訪問登陸用戶才能訪問的頁面######
r3 = requests.get(
    url="https://github.com/settings/emails",
    # cookies=r1_cookie_dict
    cookies=r2_cookie_dict     # 經測試驗證,使用這個cookie能夠拿到數據
)
print(r3.text)  # 在返回的html找到我的的郵箱信息,說明登陸並訪問成功

五、套路總結

  • 汽車之家
  • 抽屜新聞:攜帶user-agent。
  • 登陸抽屜:第一次訪問保留cookie,登陸時須要再次攜帶。 
  • 自動登陸github:獲取csrf_token 及 到底攜帶哪個cookie。

5、爬取拉勾網

一、登陸查看「個人邀請頁面」

  

  代碼示例以下所示:

import re
import json
import requests

all_cookie_dict = {}
# ############################ 第一步訪問登陸頁面 #################
r1 = requests.get(
    url="https://passport.lagou.com/login/login.html",
    headers={
        "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36",
    }
)
# print(r1.text)

"""查看登陸頁面源碼
    <!-- 頁面樣式 -->    
    <!-- 動態token,防護僞造請求,重複提交 -->
<script>
    window.X_Anti_Forge_Token = '011025d5-fb0e-46be-a2a9-6ad036224062';
    window.X_Anti_Forge_Code = '62107713';
</script>
"""
token = re.findall("X_Anti_Forge_Token = '(.*)';", r1.text)[0]
print(token)   # '51a18f67-865e-4b8d-9e3f-aad9944611ee'

code = re.findall("X_Anti_Forge_Code = '(.*)';", r1.text)[0]
print(code)    # '28683037'

r1_cookie_dict = r1.cookies.get_dict()
all_cookie_dict.update(r1_cookie_dict)


# ######################## 第二步 去登陸 #####################
r2 = requests.post(
    url="https://passport.lagou.com/login/login.json",
    headers={
        "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36",

        # 常規請求頭
        "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
        "Host": "passport.lagou.com",
        "Origin": "https://passport.lagou.com",
        "Referer": "https://passport.lagou.com/login/login.html",

        # X-Requested-With:說明是ajax請求
        "X-Requested-With": "XMLHttpRequest",

        # 自定義請求頭:動態token,防護僞造請求,重複提交
        "X-Anit-Forge-Code": code,
        "X-Anit-Forge-Token": token,
    },
    # 在登陸失敗的login.json中查看要發送的請求體數據
    data={
        "isValidate": "true",
        "username": "1xxxxxxx0",
        "password": "c94be20xxxxxxxxa89fea5a0f",   # 加密的密碼寫密文
        "request_form_verifyCode": "",
        "submit": ""
    },
    cookies=all_cookie_dict
)

r2_response_json = r2.json()   # 將字符串反序列化,把字符串變爲字典

print(r2_response_json)  # {'content': {'rows': []}, 'message': '操做成功', 'submitToken': 'e1fa3919-679d-4aa0-8b9c-224b7d707ed2'}
print(r2)    # <Response [200]>

r2_cookie_dict = r2.cookies.get_dict()
all_cookie_dict.update(r2_cookie_dict)


# ######################## 第三步 grant.html #####################
r3 = requests.get(
    url="https://passport.lagou.com/grantServiceTicket/grant.html",
    headers={
        "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36",
        "Referer": "https://passport.lagou.com/login/login.html",
        "Host": "passport.lagou.com",
    },
    cookies=all_cookie_dict,
    allow_redirects=False   # 只往地址發一個請求,再也不跳轉了(重定向)
)

r3_cookie_dict = r3.cookies.get_dict()
all_cookie_dict.update(r3_cookie_dict)

# 下一步要跳轉的地址
print(r3.headers["Location"])  # 在響應頭裏包含:Location: https://www.lagou.com/?action=grantST&ticket=ST-30a4f4ce3dd


# ######################## 第四步 action=grantST&ticket=ST-30a4f4ce3d #####################
r4 = requests.get(
    url=r3.headers["Location"],
    headers={
        "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36",
        "Referer": "https://passport.lagou.com/login/login.html",
        "Host": "www.lagou.com",
        "Upgrade-Insecure-Requests": "1",
    },
    cookies=all_cookie_dict,
    allow_redirects=False   # 只往地址發一個請求,再也不跳轉了(重定向)
)

r4_cookie_dict = r4.cookies.get_dict()
print(r4_cookie_dict)
all_cookie_dict.update(r4_cookie_dict)


# ######################## 第五步 獲取認證信息 #####################
r5 = requests.get(
    url=r4.headers["Location"],
    headers={
        "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36",
        "Referer": "https://passport.lagou.com/login/login.html",
        "Host": "www.lagou.com",
        "Upgrade-Insecure-Requests": "1",
    },
    cookies=all_cookie_dict,
    allow_redirects=False   # 只往地址發一個請求,再也不跳轉了(重定向)
)

r5_cookie_dict = r5.cookies.get_dict()
all_cookie_dict.update(r5_cookie_dict)
print(r5_cookie_dict)
print(r5.headers["Location"])


# ######################## 第六步 訪問查看"個人邀請" #####################
# 在控制檯network中查看invitation.html信息

r = requests.get(
    url="https://www.lagou.com/mycenter/invitation.html",
    headers={
        "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36",
        "Host": "www.lagou.com",
        "Upgrade-Insecure-Requests": "1",
        "Pragma": "no-cache",
    },
    cookies=all_cookie_dict
)

# print(r.text)   # 在網頁中查看本身的用戶名:<span class="unick bl">xxx</span>
print("薩xxx" in r.text)   # True

二、登陸拉鉤網修改我的信息

  拉勾網我的信息,原用戶名是has22二、職位是雲平臺工程師。

  代碼示例以下所示:

import re
import json
import requests


all_cookie_dict = {}
# ############################ 第一步訪問登陸頁面 #################
r1 = requests.get(
    url="https://passport.lagou.com/login/login.html",
    headers={
        "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36",
    }
)
# print(r1.text)

"""查看登陸頁面源碼
    <!-- 頁面樣式 -->    
    <!-- 動態token,防護僞造請求,重複提交 -->
<script>
    window.X_Anti_Forge_Token = '011025d5-fb0e-46be-a2a9-6ad036224062';
    window.X_Anti_Forge_Code = '62107713';
</script>
"""
token = re.findall("X_Anti_Forge_Token = '(.*)';", r1.text)[0]
# print(token)   # '51a18f67-865e-4b8d-9e3f-aad9944611ee'

code = re.findall("X_Anti_Forge_Code = '(.*)';", r1.text)[0]
# print(code)    # '28683037'

r1_cookie_dict = r1.cookies.get_dict()
all_cookie_dict.update(r1_cookie_dict)


# ######################## 第二步 去登陸 #####################
r2 = requests.post(
    url="https://passport.lagou.com/login/login.json",
    headers={
        "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36",

        # 常規請求頭
        "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
        "Host": "passport.lagou.com",
        "Origin": "https://passport.lagou.com",
        "Referer": "https://passport.lagou.com/login/login.html",

        # X-Requested-With:說明是ajax請求
        "X-Requested-With": "XMLHttpRequest",

        # 自定義請求頭:動態token,防護僞造請求,重複提交
        "X-Anit-Forge-Code": code,
        "X-Anit-Forge-Token": token,
    },
    # 在登陸失敗的login.json中查看要發送的請求體數據
    data={
        "isValidate": "true",
        "username": "1xxxxxxxx0",
        "password": "c94be204f3xxxxxxx89fea5a0f",   # 加密的密碼寫密文
        "request_form_verifyCode": "",
        "submit": ""
    },
    cookies=all_cookie_dict
)

r2_response_json = r2.json()   # 將字符串反序列化,把字符串變爲字典

# print(r2_response_json)  # {'content': {'rows': []}, 'message': '操做成功', 'submitToken': 'e1fa3919-679d-4aa0-8b9c-224b7d707ed2'}
# print(r2)    # <Response [200]>

r2_cookie_dict = r2.cookies.get_dict()
all_cookie_dict.update(r2_cookie_dict)


# ######################## 第三步 grant.html #####################
r3 = requests.get(
    url="https://passport.lagou.com/grantServiceTicket/grant.html",
    headers={
        "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36",
        "Referer": "https://passport.lagou.com/login/login.html",
        "Host": "passport.lagou.com",
    },
    cookies=all_cookie_dict,
    allow_redirects=False   # 只往地址發一個請求,再也不跳轉了(重定向)
)

r3_cookie_dict = r3.cookies.get_dict()
all_cookie_dict.update(r3_cookie_dict)

# 下一步要跳轉的地址
# print(r3.headers["Location"])  # 在響應頭裏包含:Location: https://www.lagou.com/?action=grantST&ticket=ST-30a4f4ce3dd


# ######################## 第四步 action=grantST&ticket=ST-30a4f4ce3d #####################
r4 = requests.get(
    url=r3.headers["Location"],
    headers={
        "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36",
        "Referer": "https://passport.lagou.com/login/login.html",
        "Host": "www.lagou.com",
        "Upgrade-Insecure-Requests": "1",
    },
    cookies=all_cookie_dict,
    allow_redirects=False   # 只往地址發一個請求,再也不跳轉了(重定向)
)

r4_cookie_dict = r4.cookies.get_dict()
# print(r4_cookie_dict)
all_cookie_dict.update(r4_cookie_dict)


# ######################## 第五步 獲取認證信息 #####################
r5 = requests.get(
    url=r4.headers["Location"],
    headers={
        "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36",
        "Referer": "https://passport.lagou.com/login/login.html",
        "Host": "www.lagou.com",
        "Upgrade-Insecure-Requests": "1",
    },
    cookies=all_cookie_dict,
    allow_redirects=False   # 只往地址發一個請求,再也不跳轉了(重定向)
)

r5_cookie_dict = r5.cookies.get_dict()
all_cookie_dict.update(r5_cookie_dict)
# print(r5_cookie_dict)
# print(r5.headers["Location"])


# ######################## 第六步 模擬重定向 #####################
r6 = requests.get(
    url=r5.headers["Location"],
    headers={
        "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36",
        "Referer": "https://passport.lagou.com/login/login.html",
        "Host": "www.lagou.com",
        "Upgrade-Insecure-Requests": "1",
    },
    cookies=all_cookie_dict,
    allow_redirects=False   # 只往地址發一個請求,再也不跳轉了(重定向)
)

r6_cookie_dict = r6.cookies.get_dict()
all_cookie_dict.update(r6_cookie_dict)
print(r6.headers['Location'])   # https://www.lagou.com/


# ######################## 第七步 模擬重定向 #####################
r7 = requests.get(
    url=r6.headers["Location"],
    headers={
        "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36",
        "Referer": "https://passport.lagou.com/login/login.html",
        "Host": "www.lagou.com",
        "Upgrade-Insecure-Requests": "1",
    },
    cookies=all_cookie_dict,
    allow_redirects=False   # 只往地址發一個請求,再也不跳轉了(重定向)
)

r7_cookie_dict = r7.cookies.get_dict()
all_cookie_dict.update(r7_cookie_dict)
print(r7.headers)


# ######################## 第八步 查看我的信息 #####################
# 控制檯點擊XHR過濾。XHR英文全名XmlHttpRequest,中文能夠解釋爲可擴展超文本傳輸請求。
r8 = requests.get(
    url="https://gate.lagou.com/v1/neirong/account/users/0/",
    headers={
        "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36",
        "Referer": "https://account.lagou.com/v2/account/userinfo.html",
        "Host": "gate.lagou.com",
        "X-L-REQ-HEADER": "{deviceType:1}",
    },
    cookies=all_cookie_dict
)
# print(r8.text)
"""
{"state":1,"message":"操做成功","content":{"userName":"has222","sex":"MALE",
"portrait":"i/image3/M00/1B/24/CgpOIFp65ICAEqMgAACu8uPNxO0027.png","positionName":"雲平臺工程師·朗新公司",
"introduce":"Linux運維、python開發","isCompleteInfo":1},"submitCode":"95742353",
"submitToken":"fce637ee-e1ba-46ff-822d-4a3b88ac8478"}
"""
r8_response_json = r8.json()
# print(r8_response_json)
all_cookie_dict.update(r8.cookies.get_dict())


# ######################## 第九步 編輯我的信息 #####################
# 編輯我的信息保存後查看控制檯響應
r9 = requests.put(
    url="https://gate.lagou.com/v1/neirong/account/users/0/",
    headers={
        "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36",
        "Host": "gate.lagou.com",
        "Origin": "https://account.lagou.com",
        "Pragma": "no-cache",
        "Referer": "https://account.lagou.com/v2/account/userinfo.html",
        "X-Anit-Forge-Code": r8_response_json.get("submitCode"),
        "X-Anit-Forge-Token": r8_response_json.get("submitToken"),
        "X-L-REQ-HEADER": "{deviceType:1}"
    },
    json={
        'userName': 'hsusu999',
        'sex': 'MALE',
        'portrait': 'i/image3/M00/1B/24/CgpOIFp65ICAEqMgAACu8uPNxO0027.png',
        'positionName': 'python開發工程師;朗xxxxx限公司',
        'introduce': 'Linux運維、python開發',
        'isCompleteInfo': 1
    },
    cookies=all_cookie_dict
)

print(r9.text)
"""
{"state":1,"message":"操做成功","content":{"refreshTgtUrl":"https://passport.lagou.com/refreshTgt/
byUserToken.html?userToken=28e1eae45fa4eef75f0ed1328ef360f415e1e3469dd20ea6&signature=60ACCB0704BD5531C9E7D87673EDAA7E
&action=refreshTgt&callback=https%253A%252F%252Faccount.lagou.com%252Faccount%252Fcuser%252FuserInfo.
html&serviceId=account&ts=1540825857888"},"submitCode":"44415820","submitToken":"74a8c7b0-1851-4f24-8728-73cae1c4763f"}
"""

  我的信息修改結果以下所示:
  

三、拉勾網爬取總結

(1)Token和Code存在頁面上,且攜帶在自定義請求頭上

# ############################ 第一步訪問登陸頁面 #################
r1 = requests.get(
    url="https://passport.lagou.com/login/login.html",
    headers={
        "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36",
    }
)
# print(r1.text)

"""查看登陸頁面源碼
    <!-- 頁面樣式 -->    
    <!-- 動態token,防護僞造請求,重複提交 -->
<script>
    window.X_Anti_Forge_Token = '011025d5-fb0e-46be-a2a9-6ad036224062';
    window.X_Anti_Forge_Code = '62107713';
</script>
"""
token = re.findall("X_Anti_Forge_Token = '(.*)';", r1.text)[0]
# print(token)   # '51a18f67-865e-4b8d-9e3f-aad9944611ee'

code = re.findall("X_Anti_Forge_Code = '(.*)';", r1.text)[0]
# print(code)    # '28683037'

(2)重定向:

  如何讓requests裏面不主動重定向:

allow_redirects=False   # 只往地址發一個請求,再也不跳轉了(重定向)

  在響應頭的Location中獲取要重定向的地址:

url=r6.headers["Location"],

(3)請求發送時須要攜帶上次請求的code和token

 

(4)原則:徹底模擬瀏覽器的行爲

  瀏覽器保存重定向的地址,如下兩項須要勾選:

  

6、爬某我的的抖音視頻

相關文章
相關標籤/搜索