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

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

尽管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="">197span>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="{"spm":"3001.5502"}" data-report-query="spm=3001.5502"><div data-v-6fe2b6a7="" class="blog-list-box-top"><h4 data-v-6fe2b6a7="">【C标准库】get和puth4>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"> 阅读 ·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"> 点赞 ·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"> 评论span>
        span>
    div>
    

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

    <div class="bar-content">
    <span class="time"> 2021-10-24 11:13:03 发布span>
    <span class="read-count">15086span>
    <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人点赞,可见相对于点赞,大家还是喜欢收藏的。

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

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


    所以比较希望这些尖尖的部分再多一些哈。

    欢迎分享,转载请注明来源:内存溢出

    原文地址: https://outofmemory.cn/langs/728053.html

  • (0)
    打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
    上一篇 2022-04-26
    下一篇 2022-04-26

    发表评论

    登录后才能评论

    评论列表(0条)

    保存