一、主体思路

一般的Python爬虫设计采用的是requests库,此方法的特点是利用程序代码模拟http请求进行访问,但是主要问题是,在一些反爬虫网站中能够监测出requests模拟请求,即使是伪装了请求头heads。另外这种方法遇到的最大问题是网站采用加密进行传输数据。例如在一些网站中,表格数据采用ajax异步传输模式,而且在 request和response中都进行了md5加密,这样就需要深入分析js文件,查找加密算法,这个有一定的难度,很难完成。

基于原因,可以采用selenium进行模拟浏览器操作,相当于用代码打开一个浏览器,然后用代码控制 浏览器中网页的访问,例如屏幕下滑、点击按钮,提交表单等。这样就可以完成模拟人的操作模式request数据,然后 从浏览器收到的response中进行数据分析。这样就可以避开加密和解密的过程。

二、selenium遇到的几个坑

(1)selenium方法的主要缺点是速度不能过快,需要浏览器进行页面加载只有加载完成了才能进行数据分析。

(2)页面等待的有三种方法,一是简单的就是添加sleep延时,根据经验控制延时。二是利用wait函数进行控制,等待某个元素加载完成,适用于异步传输。三是统一声明页面重新加载默认时间,如果加载成功就继续,没有就等待到时间截止,这种适用于静态网页,不能用于动态的异步传输网页

(3)最大的坑,异步传输遇到一个表格要点击下一页,这个是ajax异步传输,但是它在页面底部,必须用代码控制页面滚动到底部才能用代码点击这个按钮。最开始没有滑动页面,导致始终报click点击错误。

(4)很多网站都进行了反爬虫,现在这个任务是爬3万多个页面,最开始速度过快,导致爬了40多页就被网站封了IP。后来进行了延时,主要延时是模拟人的操作特点,新页面加载后要延时,滑动页面后要延时、最重要的点击“下一页”后一定也要延时,感觉就是页面的停顿跟人操作一下个效果。目前一个页面4秒左右,没有问题。

(5)不要并发访问同一个网站,虽然用了不同的程序,但是IP地址没变,还是会被发现的。

(6)网站可以反爬selenium,就是在客户端的js中隐含一个selenium检测语句,目前网上提供的配置Chrome浏览器参数的方案都是不行的。看资料是说利用ip动态代理才能解决,有一定的难度,目前没有遇到这种反爬技术。

(7)用Chrome浏览器需要下载一个浏览器模拟驱动器,网上搜索就可以了。注意Chrome的版本要跟驱动器的版本一致,目前最新是版本 81.0.4044.138(正式版本) (64 位)

三、基本步骤

(1)定义浏览器对象:driver = webdriver.Chrome(),注意浏览器的模拟驱动器文件最简单方法就是放在和py文件一个文件夹中就可以了。

(2)访问页面 :driver.get(myurl)#访问网页,要等到页面加载完成

(3)找页面元素:利用id,tag,class,text等进行元素查找。只有等页面加载完成了才可以访问到元素。例如等待方法,X1=WebDriverWait(driver,10).until(EC.presence_of_element_located((By.CLASS_NAME, "fypages")) )#等待元素加载。

(4)操作元素:例如点击x1.click(),或者利用x1.click()分析网页数据

(5)窗口操作:例如 ,滑动页面到底部, driver.execute_script("window.scrollTo(0, document.body.scrollHeight);") # 异步提交,必须把页面滚到最底部

(6)关闭浏览器:driver.quit()# 关闭浏览器




python selenium 调用浏览器慢 selenium启动浏览器太慢_10浏览器加载很慢

基于selenium的模拟浏览器操作爬虫



三、案例代码

目标网站不提供给大家了,自己分析代码吧。

from selenium import webdriverfrom time import sleepfrom selenium.webdriver.common.by import Byfrom selenium.webdriver.support.ui import WebDriverWaitfrom selenium.webdriver.support import expected_conditions as ECmycount=0myshengfen=["陕西","内蒙古","辽宁","吉林"]myshengfencount=[1258,347,1348,1234]#存储数据到文件中,以json格式存储。def myfun1(mystr,myfilename):    mystr001=str(mystr).split("")    global mycount    pass    myfilename2=myfilename+"_data_2018_001.txt"    myfile = open(myfilename2, "a", encoding="utf-8")    for k in range(1,len(mystr001)):        myl0=mystr001[k].split(" ")        mydict001={}        mydict001["school_name"]=myl0[0]        mydict001["zhuanye"] = myl0[1]        mydict001["shengfen"] = myl0[2]        mydict001["kaosheng"] = myl0[3]        mydict001["pici"] = myl0[4]        mydict001["ave_value"] = myl0[5]        mydict001["min_value"] = myl0[6]        mydict001["leixing"] = myl0[7]        mydict001["year"] = 2018        myfile.write(str(mydict001)+"")        print(mycount,k,str(mydict001)+"")        mycount=mycount+1    myfile.close()#访问网站# 后面是你的浏览器驱动位置,记得前面加r'','r'是防止字符转义的for ii in range(0,len(myshengfen)):    driver = webdriver.Chrome()    myurl=r"XXXXXXXXXXX"+myshengfen[ii]+r"&schoolyear=2018" #网站地址,自己更换就可以了    driver.get(myurl)#访问网页    sleep(5) #延时    driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")#异步提交,必须把页面滚到最底部    sleep(2)    mydata=[]    for j in range(0,myshengfencount[ii]):        try:            print("点击一下页后")            WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.CLASS_NAME, "fypages")) )#等待元素加载            driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")  # 异步提交,必须把页面滚到最底部            driver.page_source  # 异步更新数据源            x1=WebDriverWait(driver,10).until(EC.presence_of_element_located((By.CLASS_NAME,"search-table")) )        except:            print("没有发现页面")        #文本处理        myfun1(x1.text,myshengfen[ii])        print(myshengfen[ii],myshengfencount[ii],"1-页码:",j+1," ===x1"*10)        x3=driver.find_element_by_class_name("fypages")#查找class元素        x4=x3.find_elements_by_tag_name("li")#利用tag查找元素        for i in x4:            print(i.text)            if i.text=='下一页':                new=i.click()#模拟点击按钮                sleep(3)                WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.CLASS_NAME, "fypages")) )                #driver.page_source #异步更新数据源                ##sleep(1)                driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")  # 异步提交,必须把页面滚到最底部                #sleep(1)                driver.page_source  # 异步更新数据源                print("点击完下一页")                break    # driver.quit()# 关闭浏览器    print(myshengfen[ii],myshengfencount[ii],"1成功了--结束了")