Python爬虫使用cookie登录获取推荐帖子

项目背景:在之前的文章中,咱们练习了爬取虎扑的帖子【项目链接】,练习了使用selenium测试化工具获取论文信息【项目链接】,今天,就来实践免账号密码登录,获取推荐帖子。从本文中,你将能学到如何使用cookie免登录和具体分析过程;掌握了这个方法,其他项目也很容易上手了。

Python爬虫使用cookie免登录获取推荐

1. Cookie免登录-获取基础问题以及链接
老步骤,首先咱们先在浏览器中进入知乎,并登录,进入开发者模式。
知乎

在这里插入图片描述
咱们将这个cookie的值copy下来,作为免登录使用。

ok,接下来可以咱们先写一段免登录代码。

import requests
from bs4 import BeautifulSoup
import json

link="https://www.zhihu.com"
session = requests.session()

headers={
    'cookie':'xxxxxxxxxxxxxxxxxx',
    'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36',
}
re  = session.get(url=link,headers=headers)

首先headers里面有两个,一个是cookie 它的值就是咱们上面copy下来的,另外一个是user-agent,它的作用是让你的这个爬虫看起来更像一个正常的浏览器。
此时可以输出返回值看看,是正常进入的主页。

接下来进行返回数据的解析
在这里插入图片描述
在这里插入图片描述
从上面两个图咱们可以分析出来,题目所处在div.Card TopstoryItem TopstoryItem-isRecommend 下的a标签

标题链接所处在div.Card TopstoryItem TopstoryItem-isRecommend下的a标签里的href属性
所以下面代码就是负责获取这两个数据的

soup = BeautifulSoup(re.text,"lxml")
infoimage = soup.find("img",class_="Avatar AppHeader-profileAvatar")
title = soup.find("div",class_="Card TopstoryItem TopstoryItem-isRecommend").find('a').text
titlelink = soup.find("div",class_="Card TopstoryItem TopstoryItem-isRecommend").find('a')['href']

在这里插入图片描述
这个title没有任何问题,但是后面的链接不是咱们想要的,因为无法直接点击就能在浏览器中打开。
咱们看一下完整的链接是什么样子

https://www.zhihu.com/question/30173526/answer/517853719

哦,这样的话只是少了前面这几个字符,咱们做字符连接操作就可以很容易的解决了。

headstring=“https://www.zhihu.com”
titlelink = headestring+titlelink

在这里插入图片描述
这样不就ok 了嘛。

没错,咱们第一步ok了。平常刷知乎的人都知道,他的问题不是像虎扑帖子那样有个页数,咱们通过地址栏修改部分参数就可以到达不同的页数,知乎是当你侧栏向下拖动到当前最后一个问题时,再向下拖动,就会自动加载几个问题。好,我们通过开发者模式来分析一下,侧栏向下拖动时,发生了什么。

2. 分析加载更多时发生了什么
在这里插入图片描述
首先咱们先点击红点右边的清除按钮清除所有请求过的内容,然后将ALL 切换成xhr。xhr类型即通过XMLHttpRequest方法发送的请求。

在这里插入图片描述
这是我侧栏向下滑到底后,再向下滑加载出来的。通过查看它们response返回结果,图中蓝色所返回的就是新加载的数据。

在这里插入图片描述

看样子是加载了六个。好了,咱们再看看这个请求连接的参数都是什么意思。【https://www.zhihu.com/api/v3/feed/topstory/recommend?session_token=27f2b0bcff1exxxxx&desktop=true&page_number=3&limit=6&action=down&after_id=11】
这里token的值部分用了xxx代替。

![在这里插入图片描述](https://img-blog.csdnimg.cn/20191210215334958.png
session_token:这个值是固定的,就好比你身份证号一样,记下来,以后都可以用的上。
desktop:这个值我也不知道有什么用,只见过它为true,没见过为false.
page_number:这个中文翻译就是页码的意思,虽然在底部没有明确的页码,但是每次向下请求时,加载出来的都算是一页。这里为3是因为这个值的初始值是2,向下刷新一次就成3了。
limit:这个参数是加载数据的数量,图片中它的值为6,说明这次加载了六条数据。
action:行为,向下请求更多,默认为down就行了。
after_id:这个值意思是请求一次后,请求的第一条数据的id是多少,也就是请求的第一个数据是总的第几个数据。因为首页默认加载是10条数据,所以向下一次请求后,第一条数据的id就是11.

ok了,这个咱们也分析完了,接下来就使用返回的数据,提取出我们需要的信息。
咱们需要问题的题目以及对应的回答的地址,地址格式如下:

 https://www.zhihu.com/question/22378218/answer/767231136

因为数据太多,我就直接挑我们需要的几个数据截图给大家
在这里插入图片描述
上图数据是在data 下的target下的question
从解析json的角度代码是

text = jsons['data'][0]['target']['question']['title']
url1 = jsons['data'][0]['target']['question']['url']

好了,题目有了,部分url也有了,但是这个url跟咱们目标地址不太一样,只有question/xxxxx 咱们还缺少answer/xxxx。没关系,这些数据肯定都有,咱们再找找。

在这里插入图片描述
果然,在data下target下我们发现一个url,这个地址后面就包含着咱们需要的数据。

获取这个url的代码是:

url2 = jsons['data'][0]['target']['url']

好了,数据都找到了,剩下的就是拼拼凑凑了。这里还需要介绍两个咱们需要用到了方法。

str.find(str, beg=0, end=len(string))
str – 指定检索的字符串
beg – 开始索引,默认为0。
end – 结束索引,默认为字符串的长度。

str.replace(old, new, max)
old – 将被替换的子字符串。
new – 新字符串,用于替换old子字符串。
max – 可选字符串, 替换不超过 max 次

好了,看看咱们进行处理的代码:

#     text = jsons['data'][0]['target']['question']['title']
#     url1 = jsons['data'][0]['target']['question']['url']
#     url2 = jsons['data'][0]['target']['url']
#     url1 = url1[url1.find("/questions"):]
#     url2 = url2[url2.find("/answers"):]
#     url = "https://www.zhihu.com"+url1+url2
#     url = url.replace("questions","question").replace("answers","answer")

对了,这里还有一个就是截取字符串的小tip,举个例子

str = "123456"
str1 = str[3:]
printf(str1)

输出为:456

也就是从左边0开始数,数到3,也就是上面的数字4,:代表之后所有,获取4以及后面所有的字符。

这只是获取到了一条数据,那我想批量获取怎么办呢,咱们可以将它写入到for循环中,将after_id和page_number参数化。

for i in range(2,5):
    num=i
    num2=11+(i-2)*6
    link2 = "https://www.zhihu.com/api/v3/feed/topstory/recommend?session_token=70f706886fdfd5be1685cca0686e0e2f&desktop=true&page_number="+str(num)+"&limit=6&action=down&after_id="+str(num2)
    re = session.get(url=link2,headers=headers)
    jsons = json.loads(re.text)
    for j in range(len(jsons['data'])):
        try:
            text = jsons['data'][j]['target']['question']['title']
        except:
            continue
        url1 = jsons['data'][j]['target']['question']['url']
        url2 = jsons['data'][j]['target']['url']
        url1 = url1[url1.find("/questions"):]
        url2 = url2[url2.find("/answers"):]
        url = "https://www.zhihu.com"+url1+url2
        url = url.replace("questions","question").replace("answers","answer")
        print(text,url,end="\n")

这里我加入的一个try-except ,原因是我在测试的时候发现,有时候会出报找不到question的错误,但是我看了返回值确实存在。由于没有找到原因,我就使用这个异常捕捉,出现异常时,就使用continue 跳到下一个新的循环。

这个项目后面可以完善的地方还有很多,我在这里给几个思路:
1、使用多线程提高速度
2、尝试将获取的数据存储起来,excel或者Mongodb数据库

好了,项目到此结束了,有什么问题欢迎一起讨论。下面放出完整的项目代码:

import requests
from bs4 import BeautifulSoup
import json
import time

link="https://www.zhihu.com"
session = requests.session()

headers={
    'cookie':'xxxx',
}
re  = session.get(url=link,headers=headers)
soup = BeautifulSoup(re.text,"lxml")
infoimage = soup.find("img",class_="Avatar AppHeader-profileAvatar")
title = soup.find("div",class_="Card TopstoryItem TopstoryItem-isRecommend").find('a').text
titlelink = soup.find("div",class_="Card TopstoryItem TopstoryItem-isRecommend").find('a')['href']
print(title,"https://www.zhihu.com"+titlelink)
#上面代码读者可以自行完善,我只是获取了其中一条数据。
for i in range(2,5):
    num=i
    num2=11+(i-2)*6
    link2 = "https://www.zhihu.com/api/v3/feed/topstory/recommend?session_token=xxxxxxxf&desktop=true&page_number="+str(num)+"&limit=6&action=down&after_id="+str(num2)
    re = session.get(url=link2,headers=headers)
    jsons = json.loads(re.text)
    for j in range(len(jsons['data'])):
        try:
            text = jsons['data'][j]['target']['question']['title']
        except:
            continue
        url1 = jsons['data'][j]['target']['question']['url']
        url2 = jsons['data'][j]['target']['url']
        url1 = url1[url1.find("/questions"):]
        url2 = url2[url2.find("/answers"):]
        url = "https://www.zhihu.com"+url1+url2
        url = url.replace("questions","question").replace("answers","answer")
        print(text,url,end="\n")
发布了48 篇原创文章 · 获赞 34 · 访问量 23万+

猜你喜欢

转载自blog.csdn.net/lzx159951/article/details/103480524