文章目录
- 写在前面
- 案例分析
- 代码实现
写在前面
前几天学习了selenium自动化以及CSS、Xpath元素定位,想着找个网站练练手,不用登录的B站就是个不错的选择,下面以B站的校园学习专栏为例进行视频标题及外链信息的爬取。
测试环境
Windows 10 x64
Python 3.6.8
VS code
案例分析
- 第一步当然是查看关键信息的定位,这里直接右键复制Xpath就OK,不过也需要思考Xpath的对应变化,比如翻页后哪些值变了而哪些值不变,找到翻页后的规律就能顺利写代码了。
- 接下来需要考虑翻页的实现,我一开始考虑的是从url入手,但是采用selenium的话会很浪费资源,于是就选择页面内翻页,这里就要想想具体怎么实现了。下面代码中的
函数是我的直接思路,就是直接用Xpath定位,但是在抓取到第五页时候其标签就发生变化了(采用标签序号定位稳定性较差),于是我直接定位网页中的页面跳转输入框,每次页码增1,就可以了。page_plus_1()
- 最后,是循环的处理,这里我用了while循环并设置跳出条件,内部嵌套了每一页的条目循环,感觉还可以提高代码运行效率,不过作为小白的我还是先打好基础吧。
不得不说selenium库的封装还是很便携的,除了Xpath要费点事,剩下的都可以直接调用现成的方法。下面是代码的具体实现。
代码实现
# 用于设置强制等待
from time import sleep
# 浏览器自动化引擎
from selenium import webdriver
def web_auto_gain_item(page_num, item_num):
# 每一页显示20个条目
# 定位待抓取文字
elems_title = driver.find_elements_by_xpath(
'//*[@id="videolist_box"]/div[2]/ul/li[%d]/div/div[2]/a'%(item_num)
)
for elem in elems_title:
# 抓取内容为:视频标题及外部链接(需要读取属性值)
content = elem.text + ': ' + elem.get_attribute("href") + '\n'
# 存储内容至文本文件,设置编码以存储文本字符串
with open('bilibili_tech_list.txt', 'a', encoding='utf-8') as file:
file.write(content)
print(content)
if item_num==20:
print("第%d页抓取完成\n"%(page_num)+'-'*30)
sleep(1)
def page_plus_1(page_num):
# 定位翻页按钮,进行翻页操作
# 第一页的翻页位于li[7], 之后的翻页位于li[8]
# (但是由于使用数字定位标签,导致其鲁棒性不高,所以下面考虑第二种办法)
if page_num==1:
# 点击翻页
driver.find_element_by_xpath(
'//*[@id="videolist_box"]/div[2]/div[2]/ul/li[7]/button'
).click()
else:
driver.find_element_by_xpath(
'//*[@id="videolist_box"]/div[2]/div[2]/ul/li[8]/button'
).click()
def page_plus_2(page_num):
# 定位元素:网页翻页的
driver.find_element_by_xpath(
'//*[@id="videolist_box"]/div[2]/div[2]/div/input'
).send_keys('%d\n'%(page_num+1))
if __name__ == '__main__':
# 待抓取的链接
url = '''https://www.bilibili.com/v/technology/campus/#
/all/stow/0/1/2020-08-07,2020-08-14'''
# 实例化自动化引擎
driver = webdriver.Edge(r"C:\msedgedriver.exe")
driver.get(url)
# 设置隐性等待
driver.implicitly_wait(15)
# 开始抓取
while True:
# 强制等待1s,便于读取页码信息
sleep(1)
page_num = eval(driver.current_url.split("/")[-2])
print("开始抓取第%d页"%(page_num))
# 循环提取item信息
for item_num in range(1,21):
web_auto_gain_item(page_num, item_num)
# 抓取一页完成后进行翻页
page_plus_2(page_num)
# 设置循环跳出的条件,这里以抓取5页,20*5=100条视频信息为例
if page_num == 5:
print("抓取完毕,关闭浏览器,谢谢使用!")
# 关闭浏览器,释放内存
driver.close()
break