Requests-HTML模块

Talk is cheap,Show me your code.

官方文档:http://html.python-requests.org

中文文档:https://cncert.github.io/requests-html-doc-cn/#/?id=rebuild_methodprepared_request-response

GitHub:https://github.com/Liangchengdeye/Requests_Html_Spider

一、简介

1、编写爬虫时requests+BeautifulSoup是一对完美的组合,先通过requests模块将网页爬取下来,再交给BeautifulSoup等一些html解析库进行解析,而requests_html可以直接解析。

2、优点

  • 支持JavaScript
  • 支持CSS选择器
  • 支持xpath选择器
  • 模拟用户代理
  • 自动重定向
  • 连接池和cookie持久性
  • 支持异步

Tips:看文档说这个模块只支持py3.6,但这个库还在更新,所以py3.6及以上版本应该都能用。

3、安装
pip install requests-html

二、使用

1、请求网页

from requests_html import HTMLSession
session = HTMLSession()
参数:
      browser.args = [
      '--no-sand',
      '--user-agent = XXXXX'
      ]

比如:
session = HTMLSession(
    browser_args=[
        '--no-sand',
        '--user-agent=计算机配置'
    ]  # , headless=False  # ⚠️去改源码
)

get请求参数:
    url 【请求的路由】
    headers = {}  【头部信息】 优先级高于cookie
    params = {}  【参数】
    proxies = {'http':'http://端口:ip'}  【代理IP】
    timeout = 0.5  【网页响应超时时间】
    allow_redirects = False  【是否允许重定向,默认True】

post请求参数:
    url 【请求的路由】
    header = {}  【头部信息】
    cookies = {} 【header中有cookie信息,另外单独传入cookie】
    data = {}  【post请求数据是放在数据体中的】
    json = {}  【json格式的数据】
    files = {'file':open(...,'rb')} 【文件数据】
    timeout = 0.5  【网页响应超时时间】
    allow_redirects = False  【是否允许重定向,默认True】
⚠️源码改动3处
(1)from requests_html import HTMLSession 进入
(2)class HTMLSession(BaseSession):
        def __init__(self, **kwargs):
            super(HTMLSession, self).__init__(**kwargs)
(3)因为继承的是BaseSession,所以进入BaseSession修改三处地方
将头部写活
添加头部

2、响应

url = "要请求的网页链接"
响应对象 = session.get(url=url)
响应对象 = session.post(url=url)
响应对象 = session.request(method='get/post',url=url)

    
响应属性:
  响应对象.url 【获取url】
  响应对象.text  【获取响应文本】
  响应对象.encoding = 'GBK/UTF_8'  【设置网页编码】
  响应对象.content  【获取网页上的二进制图片、视频】
  响应对象.json()  【获取json格式数据】
  响应对象.status_code  【状态码】
  响应对象.headers  【获取头部信息】
  响应对象.cookies 【获取cookies信息】
  响应对象.history  【获取历史信息】

3、解析
这个库是解析HTML,所以解析的都是html对象

(1) html对象属性(值):

  响应对象.html.absolute_links  【绝对路径,自动添加http://,自动补全和其他链接地址一样,返回的链接自动转为绝对路径】
  响应对象.html.links 【以列表形式提取、返回响应源码中的所有url链接】
  响应对象.html.base_url  【基础路径,就是主路径,一般是一个网站的网址】
  响应对象.html.html  【html网页】
  响应对象.html.text  【网页中的文本内容】
  响应对象.html.encoding  【获取编码方式】
  响应对象.html.encoding='GBK'  【输出的文本出现乱码,这时就需要指定编码方式,🍓在控制台输入document.charset查看编码类型】
  响应对象.html.raw_html  【未解析过的网页】
  响应对象.html.pq  【<class 'pyquery.pyquery.PyQuery'> pyquery对象】

✨🍰✨(2) html对象方法:

  • 响应对象.html.find () —— 使用css解析器
r.html.find('css选择器')
r.html.find('css选择器',first=True)

r.html.find('#footer')  # 查找footer标签元素对象
r.html.find('a',first=True)  # 查找第一个a标签元素对象

 🍋find函数有5个参数:
 selector【css解析式,要用的CSS选择器】
 first 【布尔值,如果为真则表示获取符合css表达式的第一个元素对象,否则返回满足条件的元素对象列表】
 containing【如果指定,则只返回包含提供文本的元素,放在列表中】
 clean【布尔值,是否消除 <script> 和<style> 标签对html产生的影响】
 _encoding【编码方式】

 🍋因为函数获得的是元素,所以元素还有他的属性

----- 响应对象.html.find().text ----
r.html.find('a', first=True).text  >>> 获取元素的文本内容
>>>输出:校花网
----- 响应对象.html.find().attrs ----
r.html.find('a', first=True)  >>> 查找元素对象
r.html.find('a', first=True).attrs)  >>>获取元素所有的属性
r.html.find('a', first=True).attrs['href'] >>> 获取元素的具体属性,返回值是个字典

>>>输出:
>>>  <Element 'a' href='http://www.xiaohuar.com' title='校花网'>
>>>  {'href': 'http://www.xiaohuar.com', 'title': '校花网'}
>>>  http://www.xiaohuar.com
----- 响应对象.html.find().html ----
r.html.find('a', first=True).html  >>> 查找html内容
>>>输出 <a href="http://www.xiaohuar.com" title="&#x6821;&#x82B1;&#x7F51;">校花网</a>

⭕️CSS选择器:
  (1) 类名选择器
    class ——> .类名
  (2) id选择器
    id ——> #id名
  (3) 标签选择器
    p ——> 标签p
  (4) 后代选择器
    所有:儿子,孙子,重孙...
    ul li a
  (5) 子选择器
    只有儿子
    ul li
  (6) 属性选择器(5种)
    [属性] 用于选取带有指定属性的元素
    [属性=值] 用于选取带有指定属性和值的元素
    [属性^=值] 匹配属性值以指定值开头的每个元素
    [属性$=值] 匹配属性值以指定值结尾的每个元素
    [属性~=值] 用于选取属性值中包含指定词汇的元素
    [属性=*值] 匹配属性值中包含指定值的每个元素
  (7) 群组选择器
    选择器1,选择器2... 相当于or
  (8) 多条选择器
    选择器1选择器2... 相当于and

更多用法:https://www.w3school.com.cn/cssref/css_selectors.asp


  • 响应对象.html.xpath() —— 使用path解析器
r.html.xpath('xpath选择器')  
r.html.xpath('xpath选择器',first=True)

h.html.xpath("//div[@id='menu']/a")
h.html.xpath("//div[@id='menu']",first=True  

参数和属性参照css选择器。


⭕️XPath选择器
语法:
(1) 选取节点

表达式 描述
nodename 选取此节点的所有子节点
/ 从根节点选取
// 从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置
. 选取当前节点
.. 选取当前节点的父节点
@ 选取属性

实例🌰

路径表达式 结果
bookstore 选取 bookstore 元素的所有子节点
/bookstore 选取根元素 bookstore。
注释:假如路径起始于正斜杠( / ),则此路径始终代表到某元素的绝对路径!
bookstore/book 选取属于 bookstore 的子元素的所有 book 元素
//book 选取所有 book 子元素,而不管它们在文档中的位置
bookstore//book 选择属于 bookstore 元素的后代的所有 book 元素,而不管它们位于 bookstore 之下的什么位置
//@lang 选取名为 lang 的所有属性

(2)谓语:用来查找某个特定的节点或者包含某个指定的值的节点
实例🌰

路径表达式 结果
/bookstore/book[1] 选取属于 bookstore 子元素的第一个 book 元素
/bookstore/book[last()] 选取属于 bookstore 子元素的最后一个 book 元素
/bookstore/book[last()-1] 选取属于 bookstore 子元素的倒数第二个 book 元素
/bookstore/book[position()<3] 选取最前面的两个属于 bookstore 元素的子元素的 book 元素
//title[@lang] 选取所有拥有名为 lang 的属性的 title 元素
//title[@lang='eng'] 选取所有 title 元素,且这些元素拥有值为 eng 的 lang 属性
/bookstore/book[price>35.00] 选取 bookstore 元素的所有 book 元素,且其中的 price 元素的值须大于 35.00
/bookstore/book[price>35.00]/title 选取 bookstore 元素中的 book 元素的所有 title 元素,且其中的 price 元素的值须大于 35.00

(3) 选取未知节点

通配符 描述
* 匹配任何元素节点
@* 匹配任何属性节点
node() 匹配任何类型的节点

实例🌰

路径表达式 结果
/bookstore/* 选取 bookstore 元素的所有子元素
//* 选取文档中的所有元素
//title[@*] 选取所有带有属性的 title 元素

(4) 选取若干路径
实例🌰:通过在路径表达式中使用“|”运算符,可以选取若干个路径

路径表达式 结果
//book/title 竖杠 //book/price 选取 book 元素的所有 title 和 price 元素
//title 竖杠 //price 选取文档中的所有 title 和 price 元素
/bookstore/book/title 竖杠 //price 选取属于 bookstore 元素的 book 元素的所有 title 元素,以及文档中所有的 price 元素

更多用法:https://www.w3school.com.cn/xpath/index.asp


  • 响应对象.html.search() —— 搜索元素的文本内容
r.html.search('模板')  # 查出一个
r.html.search_all('模板')  # 查出所有
🌰:r.html.search('我觉得很有{}理')[0]  >>>输出:道
    r.html.search('我觉得很{a}道{test}')['test']  >>>输出:理

🐨tips:如果没有找到的话返回网页
  • 响应对象.html.render() —— JavaScript支持
    内置支持js渲染,对以往需要使用Selenium获取源码的页面可不再额外使用Selenium库操作。
    render方法将会渲染页面的JavaScript,返回渲染后的数据。
    特别注意的是:在初次使用该功能的时候会自动下载支持包:Chromium
from requests_html import HTMLSession

session = HTMLSession()
r = session.get('http://python-requests.org/')
r.html.render()

🍋render()方法可用参数:
  retries 【在Chromium里加载页面的重试次数】
  script 【执行页面上的JavaScript (可选参数) 】
  wait 【页面加载前的等待时间,防止超时 (单位:秒,可选参数) 】
  scrolldown 【接收整数参数n,如果提供参数n,表示向后翻n页】
  sleep 【在页面初次渲染之后的等待时间】
  reload 【如果为False,则不会重新从浏览器加载内容,而是读取内存里的内容】
  keep_page 【如果为True,将会允许你通过r.html.page与浏览器页面交互】

🐨Tips:如果scrolldown和sleep都指定,那么程序会在暂停相应时间后,再往后翻页面(如:scrolldown=10, sleep=1)

scripy:"""( ) => {
​       js代码
​       js代码
​       }
​       """
​       scrolldow:n
​       sleep:n
​       keep_page:True/False
()=>{
Object.defineProperties(navigator,{
        webdriver:{
        get: () => undefined
        }
    })

🍋与浏览器交互
(1) 页面事件 —— r.html.page.XXX

----- 格式 -----
async def 函数名():  # 先定义一个函数
    await r.html.page.XXX  # 交互方式
session.loop.run_until_complete(函数名())  # 调用

 ----- 交互方式 -----
r.html.page.screenshot({"path":路径})  # 截屏
r.html.page.evaluate("""()=>{js代码}""")  
r.html.page.cookies()
r.html.page.type('css选择器','内容',{'delay':100})
r.html.page.click('css选择器')  # 点击
r.html.page.focus('css选择器')  # 聚焦
r.html.page.hover('css选择器')  # 悬浮
r.html.page.waitForSelector('css选择器')
r.html.page.waitFor(1000)  # 等待

(2) 键盘事件 —— r.html.page.keyboard.XXX

r.html.page.keyboard.type('咸鱼今天努力了没',{'delay':100})  # 键盘打字
r.html.page.keyboard.up('Shift')  # Shift抬起,按键可以换成别的
r.html.page.keyboard.down('Shift')  # Shift按下
r.html.page.keyboard.press('ArrowLeft')  # 一直按左键进行选择

(3) 鼠标事件 —— r.html.page.mouse.XXX

r.html.page.mouse.click(x,y,{  # 点击
    'button':'left',
    'click':1
    'delay':0
})
r.html.page.mouse.down({'button':'left'})  # 鼠标按下
r.html.page.mouse.up({'button':'left'}) # 鼠标抬起
🐷一般up和down一起使用,表示点击一下
r.html.page.mouse.movie(x,y,{'steps':1})  # 鼠标移动,步长为1表示移动一步就到,步长设置的越大,则步数越细,移动越慢

练习:

from requests_html import HTMLSession

session = HTMLSession(
    browser_args=[
        '--no-sand',
        '--user-agent=自己的电脑配置'
    ]  # , headless=False  # ⚠️去改源码
)

url = 'http://www.google.com'
# r = session.request(method='get', url=url)
# print(dir(r.html.find('a',first=True)))
#
# a_element = r.html.find('#footer',first=True)
# print(a_element.attrs['name'])
# print(r.html.search_all('(提示:{name},最新章节可能会{pwd},登录书架即可实时查看。)')[0])

r = session.request(method='get', url='https://www.bilibili.com/')

scrapts = """
    ()=>{
        Object.defineProperties(navigator,{
        webdriver:{
        get:() => undefined
        }
    })}
"""

try:
    r.html.render(script=scrapts, sleep=1, keep_page=True)


    async def main():
        await r.html.page.screenshot({"path": '1.png', 'clip': {'x': 200, 'y': 200, 'width': 400, 'height': 400}})
        res = await r.html.page.evaluate("""
        ()=>{
            var a = document.querySelector("#list")
            return {'x':a.offsetLeft}
        }
        """)
        print(res)
        print(await r.html.page.cookies())
        await r.html.page.type('#kw', '泷泽萝拉', {'delay': 500})
        await r.html.page.waitForSelector('[name="tj_trnews"]')
        await r.html.page.click('[name="tj_trnews"]')
        await r.html.page.focus('[type="number"]')
        await r.html.page.keyboard.type('111', {'delay': 200})
        await r.html.page.hover('[data-stat-id="6f5c93b4d1baf5e9"]')
        await r.html.page.keyboard.type('喜欢你啊', {'delay': 200})
        await r.html.page.keyboard.down('Shift')
        for i in range(3):
            await r.html.page.keyboard.press('ArrowLeft', {'delay': 1000})
        await r.html.page.keyboard.up('Shift')
        await r.html.page.keyboard.up('Backspace')
        res = await r.html.page.evaluate('''
        ()=>{
            car a = document.querySelector('[alt="【究极爆肝】德克萨斯与拉普兰德的感伤往事(明日方舟描改 动画手书·完整版)"]')
            return {
                'x':a.x+a.width/2,
                'y':a.y+a.height/2
            }
        }
        ''')
        print(res)
        await r.html.page.mouse.movie(res['x'], res['y'], {'step': 200})
        await r.html.page.mouse.down({'button': 'right'})
        await r.html.page.mouse.up({'button': 'right'})
        await r.html.page.mouse.click(res['x'], res['y'])

        await r.html.page.waitFor(5000)
    session.loop.run_until_complete(main())
finally:
    session.close()

实战:

1、校花网图片
# 对页码进行分析
# http://www.xiaohuar.com/hua/
# http://www.xiaohuar.com/list-1-1.html  第2页
# http://www.xiaohuar.com/list-1-2.html  第3页

import os
from requests_html import HTMLSession

# 生成所有页码url
def get_page_url():
    for i in range(46):
        yield 'http://www.xiaohuar.com/list-1-{}.html'.format(i)

session = HTMLSession()

# 第一页解析测试
url = "http://www.xiaohuar.com/list-1-0.html"

# 解析页面,获取图片名和url
def parse_page(url):
    r = session.request(method='get', url=url)
    img_element_list = r.html.find('[class="img"] img')
    for img_element in img_element_list:
        file_name1 = img_element.attrs.get('alt').replace('/', '').replace('\\', '')
        # print(file_name)
        file_name = file_name1 + '.png'
        file_url: str = img_element.attrs.get('src')
        file_url = r.html.base_url[:-1] + file_url if not file_url.startswith("http") else file_url
        save_file(file_name, file_url)

# 保存图片
def save_file(name, url):
    base_path = '校花图片'
    file_path = os.path.join(base_path, name)
    r = session.get(url=url)
    with open(file_path, 'wb') as f:
        f.write(r.content)
        print('%s下载成功' % name)


if __name__ == '__main__':
    for page_url in get_page_url():
        parse_page(page_url)
2、校花网视频
"""
分析:校花网视频分为两种,一种是mp4格式的,一种是m3u8格式的,所以要分别进行处理
"""
from requests_html import HTMLSession
import os

session = HTMLSession()

# 获取索引页url
def get_index_page():
    for i in range(6):
        url = 'http://www.xiaohuar.com/list-3-%s.html' % i
        yield url

# 解析索引页获取详情页url
# 解析详情页
def get_detail_page(url):
    r = session.get(url=url)
    for element in r.html.find('#images a[class="imglink"]'):
        yield element.attrs.get('href')

# 解析详情页获取视频url,名字
# 获得名字,类型,链接
def get_url_name(url):
    r = session.get(url=url)
    r.html.encoding = 'gbk'
    file_name = r.html.find("title", first=True).text.replace('\\', '')
    print(file_name)
    element = r.html.find('#media source', first=True)
    if element:
        vurl = element.attrs.get('src')
        vtype = 'mp4'
    else:
        vurl = r.html.search('var vHLSurl    = "{}";')[0]
        vtype = 'm3u8'
    return file_name, vurl, vtype


# 保存文件
def save(file_name, vurl, vtype):
    if vtype == "mp4":
        file_name += ".mp4"
        r = session.get(url=vurl)
        with open(file_name, 'wb') as f:
            f.write(r.content)
    elif vtype == "m3u8":
        save_m3u8(file_name, vurl)


# 处理m3u8
# save_m3u8('xxx','https://www6.laqddcc.com/hls/2019/05/05/BRsIeDpx/playlist.m3u8')
def save_m3u8(file_name, vurl):
    if not os.path.exists(file_name):
        os.mkdir(file_name)
    r = session.get(url=vurl)
    m3u8_path = os.path.join(file_name, 'playlist.m3u8')
    with open(m3u8_path, 'wb') as f:
        f.write(r.content)
    for line in r.text:
        if line.endswith('ts'):
            ts_url = vurl.replace('playlist.m3u8', line)
            ts_path = os.path.join(file_name, line)
            r0 = session.get(url=ts_url)
            with open(ts_path, 'wb') as f:
                f.write(r0.content)


if __name__ == '__main__':
    for index_page in get_index_page():
        for detail_url in get_detail_page(index_page):
            file_name, vurl, vtype = get_url_name(detail_url)
            save(file_name, vurl, vtype)
3、模拟知乎登录
"""
分析:知乎用密码登录,总共发送3次请求,请求路由相同,但请求方式不同;验证码有两种方式,字母验证码和选择倒立文字验证码;两个加密,formdata加密和signature加密。
     3次请求:【第一次】https://www.zhihu.com/api/v3/oauth/captcha?lang=en  get请求检测是否需要验证码,传输的是json格式;
             【第二次】https://www.zhihu.com/api/v3/oauth/captcha?lang=en  put获取验证码,返回的是base64格式的验证码;
             【第三次】https://www.zhihu.com/api/v3/oauth/captcha?lang=en  post请求发送验证码。
     两种验证码:lang=en 英文;lang=cn 中文。
     signature加密是使用sha1和hmac;
     formdata加密是通过导入加密的js函数来反解出的。
"""
import requests
import base64
import Image
from time import sleep
import hmac
from hashlib import sha1
import time
from urllib.parse import urlencode
import execjs
import json


class Zhihu(object):
    def __init__(self):
        self.session = requests.session()
        self.headers = {
            'referer': 'https://www.zhihu.com/signin?next=%2F',
            'user-agent': '自己的电脑配置'
        }
        self.picture = None  # 存验证码
        self.signature = None  # 存签名
        self.picture_url = None  # 存验证码链接

    def getbasecookie(self):
        self.session.get(url='https://www.zhihu.com/signin?next=%2F', headers=self.headers)
        self.session.get(url='https://www.zhihu.com/api/v4/search/preset_words', headers=self.headers)
        # self.session.post(url='https://www.zhihu.com/udid', headers=self.headers)  # 未知

    def getcapture(self):
        # 获取验证码方法,有时候不用获取验证码就可以直接登录
        # lang=en是英文字母,lang=cn是选倒过来的文字
        message = self.session.get(url='https://www.zhihu.com/api/v3/oauth/captcha?lang=en',
                                   headers=self.headers).json()  # get请求检测是否需要验证码,传输的是json格式
        print(message)  # {'show_captcha':True/False}
        if message['show_captcha'] == False:  # 如果不需要验证码
            self.picture = ''
        else:
            self.picture_url = self.session.put(url='https://www.zhihu.com/api/v3/oauth/captcha?lang=en',
                                                headers=self.headers).json()  # put获取验证码,返回的是base64格式的验证码
            # 采用base64格式将验证码通过图片格式显示出来
            with open('captcha.jpg', 'wb') as f:
                f.write(base64.b64decode(self.picture_url['img_base64']))
            image = Image.open('captcha.jpg')
            image.show()
            self.picture = input('请输入验证码:')
            sleep(2)
            message1 = self.session.post(url='https://www.zhihu.com/api/v3/oauth/captcha?lang=en',data={'input_text':self.picture},headers=self.headers).json()  # post请求发送验证码
            print(message1)

    def get_signature(self):
        # 知乎登录的主要问题在于找到signature,重点
        a = hmac.new('d1b964811afb40118a12068ff74a12f4'.encode('utf-8'),digestmod=sha1)
        a.update('password'.encode('utf-8'))
        a.update(b'c3cef7c66a1843f8b3a9e6a1e3160e20')
        a.update(b'com.zhihu.web')
        a.update(str(int(time.time()*1000)).encode('utf-8'))
        self.signature = a.hexdigest()

    def Login_phone(self):
        # 登录
        data = {
            'client_id': 'c3cef7c66a1843f8b3a9e6a1e3160e20',
            'grant_type': 'password',
            'timestamp': str(int(time.time() * 1000)),
            'source': 'com.zhihu.web',
            'signature': self.signature,
            'username': '+8615151979063',
            'password': '88404620wpr',
            'captcha': self.picture,
            'lang': 'en',
            'utm_source': '',
            'ref_source': 'other_https://www.zhihu.com/signin?next=%2F',
        }

        headers = {
            'scheme': 'https',
            'accept': '*/*',
            'accept-encoding': 'gzip, deflate, br',
            'accept-language': 'zh-CN,zh;q=0.8',
            'cache-control': 'no-cache',
            # 'content-length':'412',
            'pragma': 'no-cache',
            'origin': 'https://www.zhihu.com',
            'user-agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 SE 2.X MetaSr 1.0',
            'content-type': 'application/x-www-form-urlencoded',
            'referer': 'https://www.zhihu.com/signin?next=%2F',
            'x-xsrftoken': self.session.cookies.get('_xsrf'),
            'x-requested-with': 'fetch',
            'x-ab-param': 'top_vipconsume=1;se_famous=1;se_featured=1;top_ebook=0;top_recall_exp_v1=1;se_topicdirect=2;li_ts_sample=old;qa_answerlist_ad=0;zr_ans_rec=gbrank;se_likebutton=0;se_d2q=0;top_root=0;pf_noti_entry_num=0;li_android_vip=0;se_limit=0;se_ltr_nn=0;se_time_threshold=0;top_gr_ab=0;pf_fuceng=1;ls_videoad=0;top_ydyq=X;qa_test=0;zr_art_rec=base;se_topiclabel=1;top_recall_exp_v2=1;ls_new_upload=0;zr_km_answer=open_cvr;se_webtimebox=0;se_backsearch=0;tp_meta_card=0;zr_search_xgb=0;zr_km_xgb_model=new_xgb;se_spb309=0;soc_special=0;li_album3_ab=0;li_se_xgb=0;se_p_slideshow=0;ls_fmp4=0;soc_bignew=1;soc_bigone=0;ug_zero_follow_0=0;zr_article_rec_rank=close;zr_km_paid_answer=0;se_ri=0;tp_sft_v2=d;zr_rec_answer_cp=close;se_agency= 0;tsp_hotctr=1;soc_notification=0;pf_foltopic_usernum=50;zr_video_rank=new_rank;se_whitelist=0;tp_sft=a;tp_header_style=1;ug_zero_follow=0;li_se_paid_answer=0;se_go_ztext=0;tp_topic_head=1;top_reason=1;li_qa_new_cover=0;se_expired_ob=0;top_recall_deep_user=1;tsp_lastread=0;li_qa_cover=old;li_price_test=1;tp_qa_metacard_top=top;se_rr=0;se_wannasearch=0;se_subtext=0;pf_creator_card=1;zr_km_tag=open;se_mclick1=0;se_movietab=1;top_v_album=1;ug_newtag=0;zr_km_slot_style=event_card;se_page_limit_20=1;se_zu_recommend=0;top_rank=0;zr_intervene=0;se_billboardsearch=0;se_new_topic=0;se_payconsult=0;soc_update=1;pf_feed=1;zr_answer_rec_cp=open;se_ltr_ck=0;tp_qa_metacard=1;top_universalebook=1;se_websearch=3;ug_goodcomment_0=1;ug_follow_answerer=0;zr_infinity_small=256;se_mclick=0;top_native_answer=1;li_hot_score_ab=0;zr_rel_search=base;zr_video_recall=current_recall;se_ad_index=10;se_college_cm=0;ug_fw_answ_aut_1=0;zr_video_rank_nn=new_rank;se_college=default;se_search_feed=N;ug_follow_topic_1=2;li_back=0;se_webrs=1;se_amovietab=1;top_new_feed=5;li_pay_banner_type=0;li_ebook_detail=1;se_preset_tech=0;se_colorfultab=1;tp_sticky_android=0;li_tjys_ec_ab=0;ug_follow_answerer_0=0;li_album_liutongab=0;li_se_kv=0;se_mobileweb=1;top_quality=0;se_lottery=0;top_test_4_liguangyi=1;zr_km_style=base;se_ios_spb309=0;se_auto_syn=0;tsp_vote=1;pf_newguide_vertical=0;tsp_childbillboard=1;li_se_album_card=0;se_ltr_gc=0;tp_qa_toast=1;tp_m_intro_re_topic=1;se_waterfall=0;top_hotcommerce=1;zr_infinity_a_u=close;se_webmajorob=0;se_zu_onebox=0;se_site_onebox=0',
            'x-zse-83': '3_2.0',
        }
        print(self.session.cookies.get('_xsrf'))
        print(urlencode(data))

        with open('知乎加密js.js','r',encoding='utf-8') as f:
            js = execjs.compile(f.read())  # 传入unicode字符
            data = js.call(u'b',urlencode(data))  # data_dict为表单数据
            print(data)
        message = self.session.post(url='https://www.zhihu.com/api/v3/oauth/sign_in',headers=headers,data=data)
        message.encoding='utf-8'
        print(message.text)
        print(json.loads(message.text)['error']['message'])

    def target_url(self,url):
        text = self.session.get(url)
        return text.text


if __name__ == '__main__':
    zhihu = Zhihu()
    zhihu.getbasecookie()  # 首次cookie
    zhihu.getcapture()  # 验证码
    zhihu.get_signature()  # signature
    zhihu.Login_phone()  # 登录
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 195,783评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,360评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 142,942评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,507评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,324评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,299评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,685评论 3 386
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,358评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,652评论 1 293
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,704评论 2 312
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,465评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,318评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,711评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,991评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,265评论 1 251
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,661评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,864评论 2 335