爬虫基本原理

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、爬某我的的抖音视频

相关文章
相关标签/搜索