Python玩转CSDN,用selenium统计博客的阅读量

尽管CSDN为创作者提供了数据观星,可以非常便捷地查看最近的创作情况,但是并没有提供文章间的对比,也没有更详尽的分析功能。所以本文通过selenium对博客的阅读量等内容进行爬取。

获取所有博文

这个功能是比较容易实现的,按理说一个人的所有文章都在博客主页,每篇文章的标题大致如下

<div class="blog-list-box-top" data-v-6fe2b6a7>
    <h4 data-v-6fe2b6a7>Python标准库32个模块的整理</h4>
</div>

文章标题为Python标准库32个模块的整理,其classblog-list-box-top

接下来通过selenium进入个人主页。

from selenium import webdriver
url = 'https://tinycool.blog.csdn.net/?type=blog'
driver = webdriver.Edge()
driver.get(url)

然后查找class,如果使用find_element的方法,则只显示第一个匹配对象,

>>> Title = driver.find_element_by_class_name('blog-list-box-top')
>>> print(Title.text)
QT调用外部程序

如果采用find_elements,则可定位所有文章,

>>> titleClass = 'blog-list-box-top'
>>> for T in driver.find_elements_by_class_name(titleClass):
...   print(T.text)
...
QT调用外部程序
#。。。

从而得到当前页所有文章的标题,然而这个页面是那种无限滚动的,所以先滚动一下试试

driver.execute_script("window.scrollTo(0,document.body.scrollHeight)")

可以通过对比文章数量和标题数量,来判断是否已经滚动到底,其中文章数位于

<li data-v-bb5f5e3e="" class="active"><!---->文章·<span class="nav-li-num" data-v-bb5f5e3e="">197</span></li>

可见文章这两个字在<li>中,nav-li-num这个class中直接就是文章的数量。

from selenium import webdriver
url = 'https://tinycool.blog.csdn.net/?type=blog'
driver = webdriver.Edge()
driver.get(url)
nArticles = driver.find_elements_by_class_name('nav-li-num')[0].text
nArticles = int(nArticles)

接下来只需对比当前滚动的位置是否有足量的Title,

import time
titleClass = 'blog-list-box-top'
scriptDown = "window.scrollTo(0,document.body.scrollHeight)"
scriptUp = "window.scrollTo(0,-500)"
Titles = driver.find_elements_by_class_name(titleClass)

while len(Titles) < nArticles:
    driver.execute_script(scriptUp)
    time.sleep(1)   #发出命令后等待1秒
    driver.execute_script(scriptDown)
    time.sleep(1)
    Titles = driver.find_elements_by_class_name(titleClass)

运行结束后,获取了237篇博客。

>>> len(Titles)
237

而博客链接被存放在一个a标签中

<a data-v-6fe2b6a7="" href="https://blog.csdn.net/m0_37816922/article/details/122035260?spm=1001.2014.3001.5502" target="_blank" data-report-click="{
     
     &quot;spm&quot;:&quot;3001.5502&quot;}" data-report-query="spm=3001.5502"><div data-v-6fe2b6a7="" class="blog-list-box-top"><h4 data-v-6fe2b6a7="">【C标准库】get和put</h4></div> </a>

为了获取链接,可以先复制一下这个a标签的完整Xpath,得到

/html/body/div[2]/div/div[1]/div/div/div/div/div/div[2]/div/div[2]/div/div[2]/div/article[1]/a

然后获取所有a标签所对应的链接,需要注意,刚刚获取的xpath仅仅是一篇文章的,所以article后面有一个[1],在下面的代码中,去掉这个[1],可以获取当前页面上的所有这个路径下的a标签,然后再提取出a标签中的href就行了

xpath = '/html/body/div[2]/div/div[1]/div/div/div/div/div/div[2]/div/div[2]/div/div[2]/div/article/a'
links = driver.find_elements_by_xpath(xpath)
links = [L.get_attribute('href') for L in links]

爬取数据

在得到所有的链接之后,就能摘取每篇文章的信息了。

在主页,除了标题之外还有阅读量、点赞和评论

<div data-v-6fe2b6a7="" class="view-num-box">
    <span data-v-6fe2b6a7="" class="view-num">
        91<span data-v-6fe2b6a7="" class="two-px">&nbsp;阅读&nbsp;·</span>
    </span>
</div> 
<div data-v-6fe2b6a7="" class="give-like-box">
    <span data-v-6fe2b6a7="" class="give-like-num">
        5<span data-v-6fe2b6a7="" class="two-px">&nbsp;点赞&nbsp;·</span>
    </span></div>
<div data-v-6fe2b6a7="" class="comment-box">
    <span data-v-6fe2b6a7="" class="comment-num">0<span data-v-6fe2b6a7="" class="two-px">&nbsp;评论</span>
    </span>
</div>

而进入文章后,则可以更加方便地获取发布时间、阅读量、和收藏量。

<div class="bar-content">
<span class="time">&nbsp;2021-10-24 11:13:03&nbsp;发布</span>
<span class="read-count">15086</span>
<span class="name">收藏</span>
    <span class="get-collection">
        584
    </span>

故而在主页可爬取点赞数,由于数量和描述之间有一个空格,可split之后再转化为数字。

titleClass = 'blog-list-box-top'
likeClass = 'give-like-num'
Titles = [t.text for t in driver.find_elements_by_class_name(titleClass)]
Likes = [int(L.text.split(' ')[0]) for L in driver.find_elements_by_class_name(likeClass)]

在文章内容里,标题位于h1中的title-article类;阅读量为read-count类的一个span。比较尴尬的是我选的这篇文章竟然没人收藏。不得已打开一个有收藏的文章,发现收藏数被放在一个get-collection的span中,则按照此前的方法不难得到各种信息

infoDict = {
    
    
    "title":'title-article',
    "time":"time",
    "read":'read-count',
    "collection":'get-collection'}
getElement = lambda value : driver.find_element_by_class_name(value)[0].text
tmp = {
    
    key:getElement(infoDict[key]) for key in infoDict}

从而得到

{'title': '【C标准库】stdio.h', 'time': '2021-12-20 11:46:45', 'read': '6', 'collection': ''}

接下来可以逐一对所有的链接执行此项操作

infos = []
for url in links:
    driver.get(url)
    infos.append({
    
    key:getElement(infoDict[key]) for key in infoDict})

最后将Likes写入infos

likeDict = {
    
    Titles[i]:Likes[i] for i in range(len(Titles))}
for info in infos:
    info['like'] = likeDict[info['title']]

在爬取完成后,将infos写入csv

import csv
f = open('blogs.csv','w',newline='')
w = csv.writer(f)
for info in infos:
    w.writerow(list(info.values()))

f.close()

所有代码

获取文章数

from selenium import webdriver
url = 'https://tinycool.blog.csdn.net/?type=blog'
driver = webdriver.Edge()
findClass = driver.find_elements_by_class_name
driver.get(url)
num = int(findClass('nav-li-num')[0].text)

接下来进入循环,得到所有页面的链接

import time
titleClass = 'blog-list-box-top'
likeClass = 'give-like-num'
scriptDown = "window.scrollTo(0,document.body.scrollHeight)"
scriptUp = "window.scrollTo(0,-500)"
Titles = findClass(titleClass)

while len(Titles) < num:
    driver.execute_script(scriptUp)
    time.sleep(1)   #发出命令后等待2秒
    driver.execute_script(scriptDown)
    time.sleep(1)   #发出命令后等待2秒
    Titles = findClass(titleClass)

Titles = [t.text for t in findClass(titleClass)]
Likes = [L.text.split(' ')[0] for L in findClass(likeClass)]

xpath = '/html/body/div[2]/div/div[1]/div/div/div/div/div/div[2]/div/div[2]/div/div[2]/div/article/a'
links = driver.find_elements_by_xpath(xpath)
links = [L.get_attribute('href') for L in links]

进入每个页面,并获取我们需要的信息

infoDict = {
    
    
    "title":'title-article',
    "time":"time",
    "read":'read-count',
    "collection":'get-collection'}
infos = []
for url in links:
    driver.get(url)
    infos.append({
    
    key:findClass(infoDict[key])[0].text for key in infoDict})

likeDict = {
    
    Titles[i]:Likes[i] for i in range(len(Titles))}
for info in infos:
    info['like'] = likeDict[info['title']]

# 将时间和日期分开
for info in infos:
    dt = info['time'].split(" ")
    info['date'] = dt[1]
    info['time'] = dt[2]

import csv
f = open('blogs.csv','w',newline='')
w = csv.writer(f)
for info in infos:
    w.writerow(list(info.values()))

f.close()

分析

获取这些数据之后,就可以进行分析了,例如想知道阅读量和收藏量的关系,如下图所示
在这里插入图片描述
阅读量和点赞量之间的关系
在这里插入图片描述

可见每100个阅读,有1.3人收藏,而只有0.45人点赞,可见相对于点赞,大家还是喜欢收藏的。

由于评论人数实在太少,就没爬取。

也可以更加直观地查看每篇博客的阅读量,横轴为博客发布的时间顺序。

在这里插入图片描述
所以比较希望这些尖尖的部分再多一些哈。

猜你喜欢

转载自blog.csdn.net/m0_37816922/article/details/124362036