这是笔者在selenium中爬取哔哩哔哩鬼畜区的一个案例,注释十分清晰,基本上每一个函数都有注释。希望对学习这一块的同志有帮助。
采用无头浏览器:
chrome_options = Options()
chrome_options.add_argument('--no-sandbox') # 解决DevToolsActivePort文件不存在的报错
chrome_options.add_argument('window-size=1920x3000') # 指定浏览器分辨率
chrome_options.add_argument('--disable-gpu') # 谷歌文档提到需要加上这个属性来规避bug
chrome_options.add_argument('--hide-scrollbars') # 隐藏滚动条, 应对一些特殊页面
chrome_options.add_argument('blink-settings=imagesEnabled=false') # 不加载图片, 提升速度
chrome_options.add_argument('--headless') # 浏览器不提供可视化页面. linux下如果系统不支持可视化不加这条会启动失败
driver = webdriver.Chrome(chrome_options=chrome_options)
#https://www.bilibili.com/v/kichiku/guide/#/all/click/0/1/2020-1-01,2021-01-01
获取指定部分的url
page_text1=html_page.xpath('//*[@id="videolist_box"]/div[2]')[0]
page_text1= etree.tostring(page_text1, encoding='utf-8')
正则匹配不到的情况:
** #注意这里笔者一直正则匹配一直匹配不到,打印page_text1才知道是指定范围内的url的错误**
打印page_text1的情况
you-get的封装函数:
def download(url):
path='C:/Users/mzy/Desktop/鬼畜爬取'
sys.argv = ['you-get', '-o', path, url]
you_get.main()
采用多线程
pool = Pool(100) # c参数放有几个需要爬取的对象
pool.map(download,list_download)
# 关闭线程池
pool.close()
pool.join()
总和代码:
import re
import os
import sys
import you_get
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from multiprocessing.dummy import Pool
from lxml import etree
#you-get方法下载视频
def download(url):
path='C:/Users/mzy/Desktop/鬼畜爬取'
sys.argv = ['you-get', '-o', path, url]
you_get.main()
chrome_options = Options()
chrome_options.add_argument('--no-sandbox') # 解决DevToolsActivePort文件不存在的报错
chrome_options.add_argument('window-size=1920x3000') # 指定浏览器分辨率
chrome_options.add_argument('--disable-gpu') # 谷歌文档提到需要加上这个属性来规避bug
chrome_options.add_argument('--hide-scrollbars') # 隐藏滚动条, 应对一些特殊页面
chrome_options.add_argument('blink-settings=imagesEnabled=false') # 不加载图片, 提升速度
chrome_options.add_argument('--headless') # 浏览器不提供可视化页面. linux下如果系统不支持可视化不加这条会启动失败
driver = webdriver.Chrome(chrome_options=chrome_options)
#https://www.bilibili.com/v/kichiku/guide/#/all/click/0/1/2020-1-01,2021-01-01
#通过测试1.py知到此页面数据是动态加载出来的所以用selenium模块爬取
#也可以用json数据但是为了练selenium自动化
#selenium开发者文档https://www.xugj520.cn/archives/selenium-api.html
driver.get("https://www.bilibili.com/v/kichiku/guide/#/all/click/0/1/2020-1-01,2021-01-01") # **网址输入**
driver.maximize_window() # 将窗口最大化
#显示数据总数和页数//*[@id="videolist_box"]/div[2]/div[2]/div/div/span
print(driver.find_element_by_xpath('//*[@id="videolist_box"]/div[2]/div[2]/div/div/span').text)
#这里想做一个爬取指定个数的视频,可以用下列公式
#页面数=数据数/12+1
#最后一个页面爬取的数量=数据数%12
#第一页urlhttps://www.bilibili.com/v/kichiku/guide/#/all/click/0/2/2020-1-01,2021-01-01
#第二页urlhttps://www.bilibili.com/v/kichiku/guide/#/all/click/0/2/2020-1-01,2021-01-01
#通过url的改变可以实现翻页功能,这里也可以用selenium自动化来做
#提取第一页url
c=input("你想要下载几个年度鬼畜:")
num=int(c)/20+1
num1=int(c)%20
print(num,num1)
list_download = []
path='C:/Users/mzy/Desktop/鬼畜爬取'
#获得当前视频的播放量//*[@id="videolist_box"]/div[2]/ul/li[1]/div/div[2]/div[2]/span[1]/span
#第二个视频的播放量//*[@id="videolist_box"]/div[2]/ul/li[2]/div/div[2]/div[2]/span[1]/span
#第三个视频的播放量//*[@id="videolist_box"]/div[2]/ul/li[3]/div/div[2]/div[2]/span[1]/span
#获取当前视频的弹幕数//*[@id="videolist_box"]/div[2]/ul/li[1]/div/div[2]/div[2]/span[2]/span
#第二个视频的弹幕数//*[@id="videolist_box"]/div[2]/ul/li[2]/div/div[2]/div[2]/span[2]/span
#这是所有的弹幕(在里面的所有p标签)//*[@id="videolist_box"]/div[2]/ul/li[1]/div/div[1]/div/a/div/div[4]
#获取该网站的url//*[@id="videolist_box"]/div[2]/ul/li[1]/div/div[2]/a/@href
#第二个视频的url//*[@id="videolist_box"]/div[2]/ul/li[2]/div/div[2]/a/@href
#当然我们可以用for循环一个一个来获取当前视频的信息但身为一个代学生怎么能这样当然用正则啦
for i in range(1,int(num)+1):
#下载时间范围可以由url调整
driver.get("https://www.bilibili.com/v/kichiku/guide/#/all/click/0/"+str(i)+"/2020-1-01,2021-01-01")
page_text=driver.page_source
html_page=etree.HTML(page_text)
#这一步是获取指定范围内的url
page_text1=html_page.xpath('//*[@id="videolist_box"]/div[2]')[0]
page_text1= etree.tostring(page_text1, encoding='utf-8')
#注意这里笔者一直正则匹配一直匹配不到,打印page_text1才知道是指定范围内的url的错误
#p1=re.compile(r'<span>(.+?万)</span>',re.S)
#打印出来是一串奇奇怪怪的字符这里记录一下避免在犯这种错误
#这里匹配出来的数据是两两成对的一个代表浏览量,一个代表观看量
p1=re.compile(r'<span>(.+?)\\.+?</span>',re.S)
#这里是匹配url的
p2=re.compile(r'<a href="(//www.*?)"',re.S)
print(page_text1)
page_inf=re.findall(p1,str(page_text1))
url_inf=re.findall(p2,str(page_text1))
print(page_inf)
print(url_inf)
if i==num:
d=num1
else:
d=19
for k in range(1,int(d)):
# 获取文章标题//*[@id="videolist_box"]/div[2]/ul/li[1]/div/div[2]/a
page_title = html_page.xpath('//*[@id="videolist_box"]/div[2]/ul/li['+str(k)+']/div/div[2]/a/text()')
content=page_title[0]+'\n'+'播放量'+page_inf[2*k-1]+'万'+'\t'+'弹幕数:'+page_inf[2*k]+'万'+'\n'
filename1=path+'/年度鬼畜视频.text'
os.makedirs(os.path.dirname(filename1), exist_ok=True)
with open(filename1,'a',encoding='utf-8') as fp:
fp.write(content)
print(page_title[0])
list_download.append(url_inf[i-1])
#多线程下载:
pool = Pool(100) # c参数放有几个需要爬取的对象
pool.map(download,list_download)
# 关闭线程池
pool.close()
pool.join()
#print(page_text)
#退出driver
driver.quit()
selenium开发者文档
删去注释后的代码如下:
import re
import os
import sys
import you_get
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from multiprocessing.dummy import Pool
from lxml import etree
def download(url):
path='C:/Users/mzy/Desktop/鬼畜爬取'
sys.argv = ['you-get', '-o', path, url]
you_get.main()
chrome_options = Options()
chrome_options.add_argument('--no-sandbox')
chrome_options.add_argument('window-size=1920x3000')
chrome_options.add_argument('--disable-gpu')
chrome_options.add_argument('--hide-scrollbars')
chrome_options.add_argument('blink-settings=imagesEnabled=false')
chrome_options.add_argument('--headless')
driver = webdriver.Chrome(chrome_options=chrome_options)
driver.get("https://www.bilibili.com/v/kichiku/guide/#/all/click/0/1/2020-1-01,2021-01-01") # **网址输入**
driver.maximize_window() # 将窗口最大化
print(driver.find_element_by_xpath('//*[@id="videolist_box"]/div[2]/div[2]/div/div/span').text)
c=input("你想要下载几个年度鬼畜:")
num=int(c)/20+1
num1=int(c)%20
print(num,num1)
list_download = []
path='C:/Users/mzy/Desktop/鬼畜爬取'
for i in range(1,int(num)+1):
driver.get("https://www.bilibili.com/v/kichiku/guide/#/all/click/0/"+str(i)+"/2020-1-01,2021-01-01")
page_text=driver.page_source
html_page=etree.HTML(page_text)
page_text1=html_page.xpath('//*[@id="videolist_box"]/div[2]')[0]
page_text1= etree.tostring(page_text1, encoding='utf-8')
p1=re.compile(r'<span>(.+?)\\.+?</span>',re.S)
p2=re.compile(r'<a href="(//www.*?)"',re.S)
print(page_text1)
page_inf=re.findall(p1,str(page_text1))
url_inf=re.findall(p2,str(page_text1))
print(page_inf)
print(url_inf)
if i==num:
d=num1
else:
d=19
for k in range(1,int(d)):
page_title = html_page.xpath('//*[@id="videolist_box"]/div[2]/ul/li['+str(k)+']/div/div[2]/a/text()')
content=page_title[0]+'\n'+'播放量'+page_inf[2*k-1]+'万'+'\t'+'弹幕数:'+page_inf[2*k]+'万'+'\n'
filename1=path+'/年度鬼畜视频.text'
os.makedirs(os.path.dirname(filename1), exist_ok=True)
with open(filename1,'a',encoding='utf-8') as fp:
fp.write(content)
print(page_title[0])
list_download.append(url_inf[i-1])
pool = Pool(100)
pool.map(download,list_download)
pool.close()
pool.join()
driver.quit()