使用selenium,xpath,线程池爬取斗鱼主播信息
使用xpath,线程池爬取斗鱼主播信息:
主要爬取主播昵称,直播内容分类,房间名称,房间号以及人气,共爬取了大概110多页数据,大概15000条,保存在txt文本中,
import timefrom selenium import webdriver
from multiprocessing.dummy import Pool #导入线程池
from lxml import etreeclass DouYuSpider(object):def __init__(self):self.url = ""#创建一个Chrome浏览器对象self.driver = webdriver.Chrome()# 进行计数self.count = 0#创建线程池 默认最大5个self.pool=Pool()# 解析数据def parse_data(self, data):# 1.转类型element = etree.HTML(data)# 2.解析# 主播昵称nick_name_list = element.xpath('//*[@id="listAll"]/section[2]/div[2]/ul/li/div/a[1]/div[2]/div[2]/h2/text()')# 直播所属分类category_list = element.xpath('//*[@id="listAll"]/section[2]/div[2]/ul/li/div/a[1]/div[2]/div[1]/span/text()')# print(category_list)# 主播房间名称room_name_list = element.xpath('//div[@class="DyListCover-info"]/h3/text()')# 主播房间号room_id_list = element.xpath('//*[@id="listAll"]/section[2]/div[2]/ul/li/div/a[2]/@href')# 主播人气hot_list = element.xpath('//*[@id="listAll"]/section[2]/div[2]/ul/li/div/a[1]/div[2]/div[2]/span/text()')li = []for nick_name, category, room_name, room_id, hot in zip(nick_name_list, category_list, room_name_list,room_id_list, hot_list):s = '主播名:' + nick_name.strip() + " " + '直播内容:' + category.strip() + " " + '房间名称:' + room_name.strip() + " " + '房间号:' + room_id.strip() + " " + '人气:' + hot.strip() + "\n"self.count += 1li.append(s)return li# 保存数据def write_file(self, data):with open('douyu03.txt', 'a') as f:for s in data:f.write(s)def execute_request_save(self):# 1.获取下一页的class属性的值# 最后的下一页的父级li标签中的 aria-disabled=true# 而开始的下一页的 aria-disabled=falseres = self.driver.find_element_by_xpath('//span[text()="下一页"]/..').get_attribute('aria-disabled')if res == 'false':# 1.1点击下一页按钮 进行翻页next = self.driver.find_element_by_xpath('//span[text()="下一页"]')time.sleep(1)next.click()# 1.2js代码 滚动到最后位置time.sleep(1.5)code_js = 'window.scrollTo(0,document.body.scrollHeight)'self.driver.execute_script(code_js)# 2.获取数据data = self.driver.page_source# 3.解析数据result_list = self.parse_data(data)# 4.保存数据self.write_file(result_list)def _callback(self, temp):#apply_async是异步非阻塞的self.pool.apply_async(self.execute_request_save, callback=self._callback)# 调度def run(self):#开始时间self.start_time=time.time()# 1.请求self.driver.get(self.url)# 2.获取数据data = self.driver.page_source# 3.解析数据result_list = self.parse_data(data)# 4.保存数据self.write_file(result_list)# 循环发送请求 获取所有页面的数据#多线程 实现异步任务for i in range(5):self.pool.apply_async(self.execute_request_save,callback=self._callback)#阻塞主线程 python3中主线程结束,子线程不结束。while True:#防止cpu空转time.sleep(0.001)if self.driver.find_element_by_xpath('//span[text()="下一页"]/..').get_attribute('aria-disabled')=='true':break# 关闭浏览器self.driver.quit()print('总共{}条数据'.format(self.count))#结束时间self.end_time = time.time()print('运行程序总共花了{}s'.format(self.end_time-self.start_time))if __name__ == '__main__':DouYuSpider().run()