利用自动化测试工具selenium自动搜索视频信息,自动翻页爬取搜索到的视频相关信息。
首先找到自己要爬取数据网页数据,如下
整个流程如下:
1.声明浏览器对象
2.声明浏览器最长等待时间
3.创建excel文件对象
4.新建excel sheet页,并写入头部标签
5.浏览器访问网页地址
6.定位输入窗口,输入文字并回车跳转
7.切换到新标签页
8.等待网页数据加载完成
9.beautifulSoup解析网页数据
10.找到要爬取的数据,并保存到excel中
11.获取搜索到的最大页数
12.等待下一页按钮加载完成,并点击下一页按钮切换到下一页
13.重复8-10步和12步,直到所有页数爬取完毕
browser = webdriver.Chrome()
#browser = webdriver.PhantomJS()
browser.set_window_size(1400, 900)
book = xlwt.Workbook(encoding='utf-8', style_compression=0)
sheet = book.add_sheet('蔡徐坤篮球', cell_overwrite_ok=True)
sheet.write(0, 0, '名称')
sheet.write(0, 1, '地址')
sheet.write(0, 2, '描述')
sheet.write(0, 3, '观看次数')
sheet.write(0, 4, '弹幕数')
sheet.write(0, 5, '发布时间')
在这里采用xlwt库对excel文件进行写入操作,xlwt库只能写入数据,无法读取数据
def search():
try:
print('开始访问b站....')
browser.get("https://www.bilibili.com/")
search = browser.find_element_by_xpath('//div[@class="nav-search"]/form/input')
search.send_keys("蔡徐坤 篮球")
search.send_keys(Keys.ENTER)
# 跳转到新的窗口
print('跳转到新窗口')
all_h = browser.window_handles
browser.switch_to.window(all_h[1])
html = browser.page_source
# print(html)
soup = BeautifulSoup(html, 'html.parser')
save_to_excel(soup)
total_index = soup.find(class_='page-item last').find(class_='pagination-btn')
return int(total_index.text)
except TimeoutException:
return search()
3.1 打开浏览器,访问B站
browser.get("https://www.bilibili.com/")
3.2 定位搜索框的位置,并填入要搜索的文本,并回车
search = browser.find_element_by_xpath('//div[@class="nav-search"]/form/input')
search.send_keys("蔡徐坤 篮球")
search.send_keys(Keys.ENTER)
selenium可以驱动浏览器代替人工完成各种操作,查找定位要操作的节点,填充数据,模拟点击,拖拽等
查找单个节点可以通过如下方法:
find_element_by_id 【通过元素的 id 来选择】
例:
find_element_by_name 【通过元素的 name 来选择】
例:,查找:driver.find_element_by_name(‘password’)
find_element_by_xpath 【通过 xpath 选择】
例:,查找:driver.find_element_by_xpath("//form[@id=‘loginForm’]")
find_element_by_link_text 【通过链接地址选择】
例:continue,查询:driver.find_element_by_link_text(‘continue’)
find_element_by_partial_link_text 【通过链接的部分地址选择】
例:continue,查询:driver.find_element_by_link_text(‘cont’)
find_element_by_tag_name 【通过元素的名称选择】
例:< h1>welcome< h1>,查询:driver.find_element_by_tag_name(‘h1’)
find_element_by_class_name 【通过元素的 class 选择】
例:< p class=“content”>welcome to TRHX’S BLOG!< /p>,查询:driver.find_element_by_class_name(‘content’)
find_element_by_css_selector 【通过元素的 class 选择】
例:< div class=‘bdy-inner’>test< /div>,查询:driver.find_element_by_css_selector(‘div.bdy-inner’)
find_element() 【通用方法,需要传递两个参数:查找方式 By 和值】
例:driver.find_element_by_id(‘inner’) 等价于 find_element(By.ID, inner),使用时需要from selenium.webdriver.common.by import By
selenium对浏览器的操作也可称之为节点交互,常用的节点交互方式有以下几种
send_keys:模拟按键输入
clear:清除元素的内容
click:单击元素
submit:提交表单
3.3 完成点击操作后,搜索结果会在新标签页中呈现,这时需要切换到新标签页中
print('跳转到新窗口')
all_h = browser.window_handles
browser.switch_to.window(all_h[1])
3.4 获取第一页的视频相关信息,并保存到excel文档中
html = browser.page_source
# print(html)
soup = BeautifulSoup(html, 'html.parser')
save_to_excel(soup)
这里采用beautifulSoup库对网页数据进行解析。
常用的解析器有四种,如下:
解析器 | 使用方法 |
---|---|
Python 标准库 | BeautifulSoup(markup, “html.parser”) |
LXML HTML 解析器 | BeautifulSoup(markup, “lxml”) |
LXML XML 解析器 | BeautifulSoup(markup, “xml”) |
html5lib | BeautifulSoup(markup, “html5lib”) |
3.5 返回搜索结果的页数
total_index = soup.find(class_='page-item last').find(class_='pagination-btn')
return int(total_index.text)
这里利用beautifulSoup解析器提取名为page-item last的class节点下的pagination-btn节点文本数据,得到总的搜索页数
4. 点击下一页按钮,并爬取下一页视频信息保存
WAIT = WebDriverWait(browser, 20)
def next_page(page_num):
try:
print('获取第(%d)页数据' % page_num)
next_btn = WAIT.until(EC.element_to_be_clickable((By.CSS_SELECTOR,
'li.page-item.next > button')))
next_btn.click()
get_source()
except TimeoutException:
browser.refresh()
return next_page(page_num)
引入 WebDriverWait 对象,指定最长等待时间,这里最长等待时间20秒,调用它的 until() 方法,传入要等待条件 expected_conditions。比如,这里传入了 element_to_be_clickable这个条件,代表节点被选中,并可以被点击的时候
4.1 定位下一页按钮位置,并发送点击事件切换到下一页
print('获取第(%d)页数据' % page_num)
next_btn = WAIT.until(EC.element_to_be_clickable((By.CSS_SELECTOR,
'li.page-item.next > button')))
next_btn.click()
4.2 切换到下一页后,等待ul.video-list.clearfix节点出现,再获取界面数据,爬取视频信息
def get_source():
WAIT.until(EC.presence_of_element_located(
(By.CSS_SELECTOR, 'ul.video-list.clearfix')))
# browser.refresh()
html = browser.page_source
# print(html)
soup = BeautifulSoup(html, 'html.parser')
save_to_excel(soup)
5.最后,保存爬取到的结果
def save_to_excel(soup):
list = soup.find(class_='video-list clearfix').find_all_next(class_='info')
for item in list:
item_title = item.find('a').get('title')
item_link = item.find('a').get('href')
item_dec = item.find(class_='des hide').text
item_view = item.find(class_='so-icon watch-num').text
item_biubiu = item.find(class_='so-icon hide').text
item_date = item.find(class_='so-icon time').text
print('爬取:' + item_title)
global n
sheet.write(n, 0, item_title)
sheet.write(n, 1, item_link)
sheet.write(n, 2, item_dec)
sheet.write(n, 3, item_view)
sheet.write(n, 4, item_biubiu)
sheet.write(n, 5, item_date)
n = n + 1
提取到名为视频信息节点名为video-list clearfix的class节点的所有下一级名为info的class节点信息后,在提取各个信息存入excel
6.完整代码如下
from selenium import webdriver
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.keys import Keys
from bs4 import BeautifulSoup
import xlwt
import time
browser = webdriver.Chrome()
#browser = webdriver.PhantomJS()
WAIT = WebDriverWait(browser, 20)
browser.set_window_size(1400, 900)
book = xlwt.Workbook(encoding='utf-8', style_compression=0)
sheet = book.add_sheet('蔡徐坤篮球', cell_overwrite_ok=True)
sheet.write(0, 0, '名称')
sheet.write(0, 1, '地址')
sheet.write(0, 2, '描述')
sheet.write(0, 3, '观看次数')
sheet.write(0, 4, '弹幕数')
sheet.write(0, 5, '发布时间')
n = 1
def search():
try:
print('开始访问b站....')
browser.get("https://www.bilibili.com/")
search = browser.find_element_by_xpath('//div[@class="nav-search"]/form/input')
search.send_keys("蔡徐坤 篮球")
search.send_keys(Keys.ENTER)
# 跳转到新的窗口
print('跳转到新窗口')
all_h = browser.window_handles
browser.switch_to.window(all_h[1])
html = browser.page_source
# print(html)
soup = BeautifulSoup(html, 'html.parser')
save_to_excel(soup)
total_index = soup.find(class_='page-item last').find(class_='pagination-btn')
return int(total_index.text)
except TimeoutException:
return search()
def next_page(page_num):
try:
print('获取第(%d)页数据' % page_num)
next_btn = WAIT.until(EC.element_to_be_clickable((By.CSS_SELECTOR,
'li.page-item.next > button')))
# time.sleep(5)
next_btn.click()
get_source()
except TimeoutException:
browser.refresh()
return next_page(page_num)
def save_to_excel(soup):
list = soup.find(class_='video-list clearfix').find_all_next(class_='info')
for item in list:
item_title = item.find('a').get('title')
item_link = item.find('a').get('href')
item_dec = item.find(class_='des hide').text
item_view = item.find(class_='so-icon watch-num').text
item_biubiu = item.find(class_='so-icon hide').text
item_date = item.find(class_='so-icon time').text
print('爬取:' + item_title)
global n
sheet.write(n, 0, item_title)
sheet.write(n, 1, item_link)
sheet.write(n, 2, item_dec)
sheet.write(n, 3, item_view)
sheet.write(n, 4, item_biubiu)
sheet.write(n, 5, item_date)
n = n + 1
def get_source():
WAIT.until(EC.presence_of_element_located(
(By.CSS_SELECTOR, 'ul.video-list.clearfix')))
# browser.refresh()
html = browser.page_source
# print(html)
soup = BeautifulSoup(html, 'html.parser')
save_to_excel(soup)
def main():
try:
total = search()
# print(total)
for i in range(2, int(total)+1):
next_page(i)
finally:
browser.close()
browser.quit()
if __name__ == '__main__':
main()
book.save(u'蔡徐坤篮球.xls')
最后将excel文档保存为xls格式,在有的电脑上面保存为xlsx格式时,本地打开文档出现格式错误的问题,将保存格式更改为xls可以解决该问题。