本文主要内容:
以爬取微博点赞数为例,从零开始学习如何使用Python+Selenium爬取网页数据。
一、Selenium概述
Selenium是一个Web的自动化测试工具,最初是为网站自动化测试而开发的,Selenium可以直接运行在浏览器上,它支持所有主流的浏览器。
因为Selenium可以控制浏览器发送请求,并获取网页数据,因此可以应用于爬虫领域。
Selenium可以根据我们的指令,让浏览器自动加载页面,获取需要的数据,甚至页面截屏,或者判断网站上某些动作是否发生。
Selenium自己不带浏览器,不支持浏览器的功能,它需要与第三方浏览器结合在一起才能使用。
二、浏览器驱动
浏览器驱动用于使用selenium操控本地浏览器执行自动化操作。这里我使用Chrome浏览器,因此下载ChromeDriver。
2.1 下载
首先查看自己的Google Chrome版本。
在谷歌浏览器地址栏中输入 chrome://settings/help 查看版本信息
这里给出阿里的ChromeDriver下载镜像网站:
registry.npmmirror.com/binary.html…
找到自己浏览器以及系统的对应版本进行下载
对于更高版本的Google Chrome,使用这个网址:
googlechromelabs.github.io/chrome-for-…
2.2 配置环境变量(mac版)
先cd到自己chromeDriver所在的文件夹下,再将chromeDriver复制到/usr/local/bin目录下
输入chromedriver,如果显示下图说明配置成功
三、安装Selenium库
3.1 创建项目
先使用pycharm去创建一个普通的项目
3.2 安装Selenium库
- 选择pycharm右下角解释器设置
- 搜索Selenium并且安装
这里建议和我使用同一个版本,高版本每次运行都会去国外官网请求一遍。
四、思路 + 代码雏形
我们的大致思路是:通过定位网页元素获取点赞数目,将这些点赞数目作为数据收集起来。
4.1 定位网页元素
以点赞数为例,在微博的点赞按钮处右键,选择“检查”。我们可以看到他的一些CSS属性,像是class,id等。
4.2 在代码中使用网页元素
4.2.1 导入依赖库
from selenium import webdriver
from selenium.webdriver.common.by import By
4.2.2 拿到浏览器对象
driver = webdriver.Chrome()
4.2.3 访问微博页
# 访问微博页
driver.get("https://weibo.com/mygroups?gid=110007800021953")
# sleep 2s 确保网页能够加载完毕
sleep(2)
# 点击实时按钮, 切换到实时微博
driver.find_elements(By.CSS_SELECTOR, ".wbpro-textcut")[1].click()
# sleep 10s 确保网页能够加载完毕
sleep(10)
4.2.4 获取点赞数
# 找网页上的元素: 点赞数
likeCountList = driver.find_elements(By.CSS_SELECTOR, ".woo-like-count")
# 打印点赞数
for likeCount in likeCountList:
if likeCount.text == "赞":
print(0)
else:
print(likeCount.text)
4.3 运行结果
这是我们目前的运行结果,可以看到,虽然点赞数是被打印出来了,但是数据量很少,与我们的期望不符合。
五、优化
5.1 问题:为什么点赞数的数据量很少
通过f12检索元素发现,在用户不做任何操作的情况下,wrapper里面是只包括7个item的,刚好对应上我们刚才的打印结果。
而随着我们的下滑操作,item的数目也在跟着增加。所以我们需要模拟这个下滑操作。
5.2 代码实现
5.2.1 思路
- 不断下滑,获取新的item列表
- 比较「时间的href」,因为点击时间可以进入每条微博的详情页,所以每条微博的href是不相同的,当不相同的时候,说明是新的item,加入列表中。
5.2.2 完整代码
from time import sleep
from selenium import webdriver
from selenium.webdriver.common.by import By
# 将页面向下滑动px像素
def scroll_page(px):
driver.execute_script("window.scrollTo(0, {});".format(px))
# 更新href列表
def refresh_href_list(href_element_list):
hrefList.clear()
for href_element in href_element_list:
href = ""
try:
href = href_element.get_attribute("href")
except:
href = ""
finally:
hrefList.append(href)
# 访问微博实时页
def visit_weibo_live_page():
# 访问微博页
driver.get("https://weibo.com/mygroups?gid=110007800021953")
# sleep 2s 确保网页能够加载完毕
sleep(2)
# 点击实时按钮, 切换到实时微博
driver.find_elements(By.CSS_SELECTOR, ".wbpro-textcut")[1].click()
# sleep 5s 确保网页能够加载完毕
sleep(5)
# 拿到浏览器对象
driver = webdriver.Chrome()
# 访问微博实时页
visit_weibo_live_page()
# 找网页中时间的href
hrefList = []
refresh_href_list(driver.find_elements(By.CSS_SELECTOR, ".head-info_time_6sFQg"))
# 找网页上的元素: 点赞数
likeCountList = driver.find_elements(By.CSS_SELECTOR, ".woo-like-count")
# 找网页上的元素: 微博内容
wbContentList = driver.find_elements(By.CSS_SELECTOR, ".detail_wbtext_4CRf9")
totalCount = len(likeCountList) # 当前列表的总数
# 打印微博内容和点赞数
for i in range(totalCount):
if likeCountList[i].text == "赞":
print("微博内容:\n" + wbContentList[i].text + "\n点赞数:\n" + "0" + "\n")
else:
print("微博内容:\n" + wbContentList[i].text + "\n点赞数:\n" + likeCountList[i].text + "\n")
# 向下滑动100条微博的像素值
for i in range(200):
scroll_page(i * 450)
# 等待3s加载时间
sleep(3)
# 获取新的href list
newHrefList = driver.find_elements(By.CSS_SELECTOR, ".head-info_time_6sFQg")
# 获取新的item list
newLikeCountList = driver.find_elements(By.CSS_SELECTOR, ".woo-like-count")
newWbContentList = driver.find_elements(By.CSS_SELECTOR, ".detail_wbtext_4CRf9")
# 通过比较href判断是否有新的item
for j in range(len(newHrefList)):
currentHref = ""
# 这里得捕获异常, 不知道为什么会出现href属性拿不到的情况
try:
currentHref = newHrefList[j].get_attribute("href")
except:
currentHref = ""
finally:
if currentHref not in hrefList:
# 表示是新的item, 加入列表中
likeCountList.append(newLikeCountList[j])
wbContentList.append(newWbContentList[j])
# 打印一下内容
if newLikeCountList[j].text == "赞":
print("微博内容:\n" + newWbContentList[j].text + "\n点赞数:\n" + "0" + "\n")
else:
print("微博内容:\n" + newWbContentList[j].text + "\n点赞数:\n" + newLikeCountList[j].text + "\n")
# 更新href list
refresh_href_list(newHrefList)
sleep(500)
5.3 最终效果
可以看到我们已经能够不断地爬取数据了。