在入了python爬虫的坑之后….继两个月前网易大佬问我你怎么解决异步加载的网页爬虫问题….最近终于学习了一下新知识解决了这个问题….
之前一直是用request库,监听network和js请求来找到想要的加载…当然现在看了一个厉害的东西叫selenuim…果断入坑
selenuim本来是一个测试型的第三方库…但是用在爬虫上它的作用极其强大….其实就是模拟点击或者之类的操作而已…这样可以解决需要找请求包或者是解析js之类的繁琐事情
————————————————————————————————————————————————
当然安装之类的过程就跳过了….需要安装的是selenuim库和网上下载一个对应chrome版本的chromedriver.exe放到python/script/目录下就可以了
1.定义一个driver对象
正常定义的方式和chrome无头定义方式,如果使用注释里的三行定义对象的话,是不会出现图形界面的
driver = webdriver.Chrome()
# opt = webdriver.ChromeOptions()
# opt.set_headless()
# driver = webdriver.Chrome(options=opt)
2.对对象的cookies初始化
跟使用变量一样,虽然不进行初始化也可以,但是进行初始化总归是一个好的代码习惯,在清除cookies后,跳转到目标界面
driver.delete_all_cookies()
driver.get(start_url)
3.登录
爬腾讯的网站最大的问题就是登录…因为不能像入门时的简单的发出登录请求包,获取cookies后再用cookies来访问,因为先不说腾讯的界面每次访问都需要登录,并且减少了cookies的生命周期,当你的浏览器关闭后,再次登录就不能使用之前的cookies了…就算没有这个问题,腾讯的请求包又多内容又多…反正凭我的肉眼是实在懒得去找也不一定找得到具体内容…
所以selenuim的强大就体现在这里,不需要去找请求,直接模拟登录就可以了
QQ的登录有两种方式,一种是在你电脑上本身登录了QQ,使用点击头像快捷登录和正常的输入账号密码登录
当然首先我们先定位到登录的iframe框,减小定位误差,time.sleep的作用不用多说,防止闪电侠出错也可以防止被认为是爬虫
driver.switch_to.frame("login_frame") #进入登录iframe
time.sleep(1);
1)点击头像快捷登录
这个很简单,我们完全可以知道点击的头像位置,然后在F12中找到对应的头像框的位置,然后右键获取这个框的xpath,然后直接使用driver.find_element_by_xpath()定位到这个位置并且.click()模拟点击,就可以做到快捷登录
如果不使用xpath,那么使用常规定位方式也是可以定位到这个位置的
比如使用driver.find_element_by_class(“face”)也是可以定位到这个位置的,如果为了定位准确,那么当然按层级定位自然会更加准确
driver.find_element_by_xpath('//*[@id=\"qlogin_list\"]/a[1]').click();
time.sleep(1);
2)使用账号密码登录
使用账号密码登录的话自然就需要先切换到输入账号密码的页面,所以我们先通过id=”switcher_plogin”定位到切换账号密码登录,然后模拟点击,切换到账号密码登录界面后,输入账号密码并且点击登录
change = driver.find_element_by_id("switcher_plogin")
change.click()
driver.find_element_by_id('u').clear()#选择用户名框
driver.find_element_by_id('u').send_keys(user)
driver.find_element_by_id('p').clear()
driver.find_element_by_id('p').send_keys(userpsw)
driver.find_element_by_class_name("login_button").click()
当然做完以上步骤登录完成后,我们可以切换到主界面,来防止某种特殊情况下出错
driver.switch_to_default_content()
3.动态加载下拉界面
比如登录到QQ群成员界面,网页上显示的只有40个左右的人数,当网页下拉时,每次更新会加载20个成员的信息,但是显然我们要的肯定不会只是这40个人的信息,我们需要所有人的信息..那么我们需要模拟下拉界面…这时候selenuim另一个功能出现了…它可以在页面上运行js脚本
def scroll_foot(driver):
js="var q=document.documentElement.scrollTop=100000"
return driver.execute_script(js)
def sroll_multi(driver,times=20,loopsleep=1):
#40 titles about 3 times
for i in range(times):
time.sleep(loopsleep)
print ("Scroll foot %s time..." % i)
scroll_foot(driver)
time.sleep(loopsleep)
js模拟每次拉到当前页面的地步,加载后继续重复步骤直到全部加载完成…至于需要加载多少次也很简单..我们只要直到群有多少个成员就可以了…群成员人数/20就是需要下拉的次数
4.获取整个页面源代码并写入文件
f = open("html.txt",'w',encoding='utf-8')
f.write(driver.page_source)
f.close()
# print(driver.page_source)
driver.quit()
5.以上就是每个部分的作用以及代码块
6.整体代码
import os
import time
from selenium import webdriver
def scroll_foot(driver):
if driver.name == "chrome":
js="var q=document.documentElement.scrollTop=100000"
return driver.execute_script(js)
def sroll_multi(driver,times=20,loopsleep=1):
#40 titles about 3 times
for i in range(times):
time.sleep(loopsleep)
print ("Scroll foot %s time..." % i)
scroll_foot(driver)
time.sleep(loopsleep)
def main(start_url,number):
driver = webdriver.Chrome()
# opt = webdriver.ChromeOptions()
# opt.set_headless()
# driver = webdriver.Chrome(options=opt)
print("登录")
driver.delete_all_cookies()
driver.get(start_url)
driver.switch_to.frame("login_frame") #进入登录iframe
time.sleep(1);
# driver.find_element_by_xpath('//*[@id=\"qlogin_list\"]/a[1]').click();
# time.sleep(1);
change = driver.find_element_by_id("switcher_plogin")
change.click()
driver.find_element_by_id('u').clear()#选择用户名框
driver.find_element_by_id('u').send_keys(user)
driver.find_element_by_id('p').clear()
driver.find_element_by_id('p').send_keys(userpsw)
driver.find_element_by_class_name("login_button").click()
driver.switch_to_default_content()
# print(driver.name)
sroll_multi(driver,(int)((int)(number)/20 + 3))
f = open("html.txt",'w',encoding='utf-8')
f.write(driver.page_source)
f.close()
# print(driver.page_source)
driver.quit()
if __name__ == '__main__':
# user=input("账号:")
# userpsw=input("密码:")
number = input("当前群人数:")
url = input("url")
main(url,number)
7.selenium的十八种定位方式
前八种是大家都熟悉的,经常会用到的
- id定位:findelement_by_id(self, id)
- name定位:find_element_by_name(self, name)
- class定位:find_element_by_class_name(self, name)
- tag定位:find_element_by_tag_name(self, name)
- link定位:find_element_by_link_text(self, link_text)
- partial_link定位find_element_by_partial_link_text(self, link_text)
- xpath定位:find_element_by_xpath(self, xpath)
- css定位:find_element_by_css_selector(self, css_selector)
这八种是复数形式
- id复数定位findelements_by_id(self, id)
- name复数定位find_elements_by_name(self, name)
- class复数定位find_elements_by_class_name(self, name)
- tag复数定位find_elements_by_tag_name(self, name)
- link复数定位find_elements_by_link_text(self, text)
- partial_link复数定位find_elements_by_partial_link_text(self, link_text)
- xpath复数定位find_elements_by_xpath(self, xpath)
- css复数定位find_elements_by_css_selector(self, css_selector
这两种就是快失传了的
- find_element(self, by=’id’, value=None)
- find_elements(self, by=’id’, value=None)