python爬虫实战(八) 爬取CSDN博主信息——Selenium VS Webscraper

写博客也快一年了,突然想了解下同层次的博主的平均水平应该是什么样的(自己写的博客咋样没点B数么 ),今天就来分享下CSDN的博主信息的爬取方法~

一、项目介绍

爬取网址:CSDN首页的Python、Java、前端、架构以及数据库栏目,各栏目网址如下:

栏目网址
Pythonhttps://www.csdn.net/nav/python
Javahttps://www.csdn.net/nav/Java
前端https://www.csdn.net/nav/web
架构https://www.csdn.net/nav/arch
数据库https://www.csdn.net/nav/db

简单分析其各自的URL不难发现,都是https://www.csdn.net/nav/+栏目名样式,这样我们就可以爬取不同栏目了。

以Python目录页为例,如下图所示:
在这里插入图片描述

爬取内容:每篇文章的博主信息,如博主姓名、码龄、原创数、访问量、粉丝数、获赞数、评论数、收藏数
(考虑到周排名、总排名、积分都是根据上述信息综合得到的,对后续分析没实质性的作用,这里暂不爬取。)
在这里插入图片描述
不想看代码的朋友可直接跳到第三部分~

二、Selenium爬取

分析目录页可知文章是需要动态加载的,此时需要selenium模拟浏览器不断下拉才能获取新的文章。文章的链接如下所示:
在这里插入图片描述

1、第一种爬取思路(未果)

思路图如下:
在这里插入图片描述

执行的关键代码如下:

from selenium import webdriver
import time
driver = webdriver.Chrome()
driver.get('https://www.csdn.net/nav/python')

#下拉若干次
for i in range(10):
	driver.execute_script('window.scrollTo(0,document.body.scrollHeight)')
	time.sleep(1)

#定位所有链接
blog_url = driver.find_elements_by_css_selector('div.title > h2 > a') #注意:这里保存的是所有element对象

for i in range(len(blog_url)):
	url = blog_url[i].get_attribute('href')
	driver.get(url)
	#------------相关信息爬取(省略)----------
	driver.back() #返回目录页

理论上,这段代码看起来是可以实现要求的,但实际上会遇到以下两个问题!

(1)元素定位问题

报错的原因:selenium当打开新的页面后,原来定位过的元素都会失效,需要重新定位元素。上面的driver.back()相当于打开的新的页面(但是对于我们来说只是返回原来的页面)
详细内容可参考这篇博客的内容:selenium点击链接进入子页面抓取内容

解决方式:只要每次返回目录页后重新定位元素即可,如下所示:

for i in range(len(blog_url)):
	blog_refind_url = driver.find_elements_by_css_selector('div.title > h2 > a')  #重新定位
	url = blog_refind_url[i].get_attribute('href')
	driver.get(url)
	#------------相关信息爬取(省略)----------
	driver.back() #返回目录页

重新定位后,不难发现,这必须要求blog_url和blog_refind_url这两个列表的长度一致啊!那也就是:每次返回目录页后,需要保持在上一次浏览的位置! 由此引发了第二个问题:定位元素的不一致。

(2)定位元素不一致

我们在获取所有的文章链接之前,首先进行的下滑页面的操作。而每次driver.back()之后,页面都会回到最初的位置!这就很头疼,如果要保持一样的浏览位置,难道每次返回后都要下拉相同次数的页面么?那么此时我们需要解决的问题则是:如何保持上一级页面的浏览位置。emm,查了一些资料,发现这个需求是和javascript相关的。详细可参考这篇博客:js:返回到页面时滚动到上次浏览位置

大致解决思路:保存每次下滑的位置,然后最终调用最后一次下滑的位置。但归根到底,还是需要每次滑动页面,依旧很麻烦,这种思路到这也只能不了了之了。(会javascript的朋友可以尝试如何让页面直接恢复到上一级页面浏览的位置)

2、第二种爬取思路(成功)

不过,仔细思考一下,上面两个问题的来源关键在于selenium访问页面后,元素会重新定位。而我们第一步定位所有文章链接时保存的列表,里面的元素都是element对象(它是会随着页面变化而改变的!)。所以,我们只要保存每个文章的url到一个列表,挨个访问每个url,不就可以了?
思路图如下:
在这里插入图片描述
两种思路的对比与思考:前者装有所有文章的列表里都是element对象,而后者装有所有文章的列表里都是url。后者免去了再返回页面这一操作,相当于将一个爬取二级页面问题转化为一级页面问题!

全部代码如下:

from selenium import webdriver
import os
os.chdir('C:/Users/dell/Desktop')
import time
import pandas as pd

def scroll_down(driver,num):
    for i in range(num):
        driver.execute_script('window.scrollTo(0,document.body.scrollHeight)')
        time.sleep(1)

def save_data(df):
    data=pd.DataFrame(df,columns=['blog_name','code_time','blog_num',
                                'view_num','fans_num','likes_num',
                                'comments_num','collections_num'])
    data.to_csv('csdn_user.csv',index=False,encoding='gb18030')

def crawler_csdn(parts_list):
    opt = webdriver.ChromeOptions()
    opt.add_experimental_option('excludeSwitches',['enable-automation'])
    opt.add_argument('--headless')
    opt.add_argument('--disable-gpu')
    opt.add_argument('blink-settings=imagesEnabled=false')
    driver = webdriver.Chrome(options=opt)
    df = []
    for part in parts_list:
        count=0
        url_des='https://www.csdn.net/nav/'+part
        driver.get(url_des)
        scroll_down(driver,30)
        time.sleep(2)
        print('开始爬取{}部分'.format(part))
        blog_list=[]
        blog_url = driver.find_elements_by_css_selector('div.title > h2 > a')
        for url in blog_url:
            blog_list.append(url.get_attribute('href'))
        print('共{}个博主'.format(len(blog_list)))
        for i in range(len(blog_list)):
            try:
                driver.get(blog_list[i])
                blog_name = driver.find_element_by_css_selector('div.profile-intro-name-boxTop > a >span.name').text
                code_time = driver.find_element_by_css_selector('span.personal-home-page.personal-home-years').text
                blog_num = driver.find_element_by_css_selector(
                    'div.data-info.d-flex.item-tiling>dl.text-center>a>dt>span.count').text
                inf_list = driver.find_elements_by_css_selector('div.data-info.d-flex.item-tiling>dl.text-center>dt>span.count')
                df.append([blog_name, code_time, blog_num,
                           inf_list[0].text, inf_list[2].text, inf_list[3].text,
                           inf_list[4].text, inf_list[5].text])
                count += 1
                print('第{}个博主信息爬取完成'.format(count))
            except:
                print('相关信息不全')
        print('{}部分爬取完成'.format(part))
    return df


if __name__ =='__main__':
    start = time.time()
    parts_list=['Python','Java','web','arch','db']
    df = crawler_csdn(parts_list)
    save_data(df)
    end = time.time()
    spend_time = int((end-start)/60)
    print('共花费{}分钟'.format(spend_time))

爬取结果如下:
在这里插入图片描述

三、Webscraper爬取

之前的博客分享过Webscraper是一种轻量级的爬取软件。不想看代码的朋友可以用它来复现上述爬取过程。(注:以下爬取过程只是针对首页的某一个栏目)

最终的爬取线路图如下
在这里插入图片描述

依旧以首页的Python栏为例:

1、创建下拉对象

这个container只是一个ID,它可以取任意名字的。其他的设置如下图所示:

在这里插入图片描述

  • Type勾选Element_scroll_down(负责下拉页面)
  • 勾选上Multiple后,点击多个文章所在模块后,则会出现红色选定。此时点击Done selecting,完成selector的配置。
  • Delay设置为2000毫秒(给予页面反应时间)

此外,需要在selector后面加上:nth-of-type(-n+300),控制爬取的条数,否则它会一直下拉页面!(这里的300则代表需要爬取的总条数)最终,selector的配置如下:
在这里插入图片描述

2、创建文章链接对象

保存container的selector后,点击进入下一层,创建如下selector
在这里插入图片描述
具体内容如下:
在这里插入图片描述

  • Type选择Link
  • Selector中不勾选Multiple,h2 a则是文章链接定位的位置

Link不方便定位的话,可以先选择text进行定位,然后得到位置后,再复制到link这即可。

3、创建博主信息对象

同理,保存完inf的selector后,再点击进入下一层,依次创建各类信息的selector,如下所示:
在这里插入图片描述
以name为例,其内容如下:
在这里插入图片描述
type选择text,相应的选择器内容只要鼠标点击博主姓名即可获得。

这样,我们就完成了所有的准备工作,接下来就可爬取啦~所有延迟时间均设置为2000ms
在这里插入图片描述
最终爬取结果如下(这里仅作演示,只爬取了七条):
在这里插入图片描述
本次创建的sitemap如下,有兴趣的朋友可以自己实验下,只需要import sitemap即可
在这里插入图片描述

{"startUrl":"https://blog.csdn.net/nav/python","selectors":[{"parentSelectors":
["_root"],"type":"SelectorElementScroll","multiple":true,"id":"container","selector":"ul.feedlist_mod li.clearfix:nth-of-type(-n+300)","delay":"2000"},{"parentSelectors":
["container"],"type":"SelectorLink","multiple":false,"id":"inf","selector":"h2 a","delay":""},{"parentSelectors":
["inf"],"type":"SelectorText","multiple":false,"id":"name","selector":"div.profile-intro-name-boxTop span.name","regex":"","delay":""},{"parentSelectors":
["inf"],"type":"SelectorText","multiple":false,"id":"blog_num","selector":"dl.text-center:nth-of-type(1) a span.count","regex":"","delay":""},{"parentSelectors":
["inf"],"type":"SelectorText","multiple":false,"id":"code_time","selector":"span.personal-home-page.personal-home-years","regex":"","delay":""},{"parentSelectors":
["inf"],"type":"SelectorText","multiple":false,"id":"views_num","selector":"div.data-info:nth-of-type(2) dl.text-center > dt span.count","regex":"","delay":""},{"parentSelectors":
["inf"],"type":"SelectorText","multiple":false,"id":"fans","selector":"dl#fanBox.text-center span.count","regex":"","delay":""},{"parentSelectors":
["inf"],"type":"SelectorText","multiple":false,"id":"agreement","selector":"dl.text-center:nth-of-type(3) > dt span.count","regex":"","delay":""},{"parentSelectors":
["inf"],"type":"SelectorText","multiple":false,"id":"comment","selector":"div.data-info:nth-of-type(4) dl.text-center:nth-of-type(4) span.count","regex":"","delay":""},{"parentSelectors":["inf"],"type":"SelectorText","multiple":false,"id":"collection_num","selector":"dl.text-center:nth-of-type(5) span.count","regex":"","delay":""}],"_id":"csdn"}

总结:Webscraper虽然简单易操作,速度也和selenium差不多,但每次只能爬一个网址,需要连续爬取多个网址,还是得码代码~

分析实战请看下一篇~

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: Python爬虫中可以使用Selenium库来爬取网页信息Selenium可以模拟浏览器行为,能够爬取JavaScript渲染后的网页信息。使用Selenium爬取网页时,需要配合浏览器驱动(如ChromeDriver、FirefoxDriver)使用。 ### 回答2: Python是一种高级编程语言,吸引了大量编程人员和开发者使用Python进行Web开发、数据分析、机器学习和人工智能等领域的开发。爬虫技术正是其中的一项重要技术,用python编写爬虫程序通常更加便捷和灵活。而seleniumPython中主要的爬虫库之一,用于爬取动态Web页面,可以模拟用户在浏览器中的行为,从而获取大量数据。 使用selenium爬取信息可以分为以下几个步骤: 1.安装和导入seleniumwebdriver: 首先需要安装适合的版本的selenium包,并导入seleniumwebdriver模块: ```python from selenium import webdriver ``` 2.配置浏览器驱动: Selenium需要浏览器驱动(如Chrome,Firefox等)来与其进行交互,需要配置如下: ```python driver = webdriver.Chrome() ``` 其中,Chrome()表示使用Chrome浏览器驱动,如果使用Firefox,则需要改为Firefox()。 3.访问网页: 使用get()函数可以访问指定的网址: ```python driver.get("https://www.baidu.com/") ``` 4.查找元素: 使用selenium的查找元素功能,可以根据元素的ID、name、class、tag等属性进行查找: ```python element = driver.find_element_by_id("kw") # 根据ID查找 element = driver.find_element_by_name("wd") # 根据name查找 element = driver.find_element_by_class_name("s_ipt") # 根据class查找 element = driver.find_element_by_tag_name("input") # 根据tag查找 ``` 5.模拟用户输入/点击: 使用send_keys()函数模拟用户在搜索框中输入关键字,使用click()函数模拟用户在搜索按钮上点击: ```python element.send_keys("Python") element.click() ``` 6.解析数据: 使用webdriver的page_source属性可以获取网页的源代码,然后使用正则表达式或BeautifulSoup库等解析数据。 以上就是使用selenium进行爬虫的主要步骤。实际应用中,需要根据不同的网站和需要爬取的数据进行具体的配置和调整。在使用selenium过程中,需要了解一些常见的使用技巧和注意事项,例如模拟等待时间,处理弹窗、验证码等。同时,也需要遵循爬虫的法律和道德规范,不得进行非法、滥用等行为。 ### 回答3: selenium是一种自动化测试工具,它可以模拟浏览器行为,实现自动化操作。在Python爬虫中,selenium也可以用来爬取需要模拟人工操作的网站数据。 使用selenium可以实现以下操作: 1.自动模拟浏览器打开网页,获取网页源码。 2.模拟用户操作,如点击按钮、填写文本框、下拉选择框等。 3.通过获取网页源码进行数据解析。 基本流程比较简单,首先需要准备好selenium的环境,这需要下载对应的webdriver,这里我使用Chrome浏览器,并且下载了对应版本的chromedriver。 然后通过selenium启动浏览器,在浏览器中进行模拟操作,最后获取网页源码进行数据解析。 具体实现可以参考以下代码: ```python from selenium import webdriver from bs4 import BeautifulSoup # 创建一个Chrome浏览器实例 browser = webdriver.Chrome() # 访问目标网页 browser.get('https://www.example.com') # 模拟点击按钮,等待加载完成 button = browser.find_element_by_xpath('//button[@class="btn"]') button.click() browser.implicitly_wait(5) # 获取网页源码 html = browser.page_source soup = BeautifulSoup(html, 'html.parser') data = soup.find_all('div', class_='data') # 处理数据 for item in data: # do something # 关闭浏览器 browser.quit() ``` 总体来说,selenium是一个强大的爬虫工具,可以应对大部分需要模拟人工操作的场景,但也存在一些缺点,比如速度慢、占用资源高等。因此在具体应用中需要根据实际情况进行选择。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值