selenium 和 IP代理池

selenium 和 IP代理池3.1seleniumselenium:Selenium是一个自动化测试工具,利用它可以驱动浏览器执行特定的动作,如点击、下拉等操作(模拟浏览器操作)同时还可以获取浏览器当前呈现的页面的源代码,做到可见即可爬Selenium支持非常多的浏览器,如Chrome、Firefox、PhantomJS等浏览器对象的初始化并将其赋值为browser对象。接下来,我们要做的就是调用…

大家好,又见面了,我是你们的朋友全栈君。

3.1 selenium

selenium:
Selenium 是一个自动化测试工具,利用它可以 驱动浏览器 执行特定的动作,如点击、下拉等操作(模拟浏览器操作)
同时还可以获取浏览器当前呈现的页面的源代码,做到可见即可爬

Selenium支持非常多的浏览器,如 Chrome、Firefox、PhantomJS等

浏览器对象的初始化 并将其赋值为 browser 对象。接下来,我们要做的就是调用 browser 对象,让其执行各个动作以模拟浏览器操作
eg:要使用google浏览器

——browser = webdriver.Chrome()

访问页面:get方法
eg:

from selenium import webdriver
 #声明
browser = webdriver.Chrome()
#请求网页
browser.get('https://www.taobao.com')
#打印源码
print(browser.page_source)
#关闭网页
browser.close()
#效果:弹出Chrome,自动访问tb,打印源码,关闭页面

查找节点(比如 找到账号输入框):
1:单个节点
返回:WebElement 类型
find_element_by_id
find_element_by_name
find_element_by_xpath
find_element_by_link_text
find_element_by_partial_link_text
find_element_by_tag_name
find_element_by_class_name
find_element_by_css_selector
变式:
find_element(By.a,b)——参数a输入属性,参数b输入值

 find_element_by_id(id)
 ==
 find_element(By.ID, id)

2:多个节点(淘宝左边所有的导航栏条目):
如果我们用 find_element()方法,只能获取匹配的第一个节点
如果用 find_elements()方法,返回:列表类型,包含所有符合要求的节点,列表中的每个节点是 WebElement 类型

find_elements_by_id
find_elements_by_name
find_elements_by_xpath
find_elements_by_link_text
find_elements_by_partial_link_text
find_elements_by_tag_name
find_elements_by_class_name
find_elements_by_css_selector

节点交互(模拟人的操作—有特定对象):
输入文字—— send_keys()方法
清空文字—— clear()方法
点击按钮—— click()方法

动作链(模拟人的操作—无特定对象):
没有特定的执行对象,比如鼠标拖曳、键盘按键等
用另一种方式来执行——动作链
http://selenium-python.readthedocs.io/api.html#module-selenium.webdriver.common.action_chains

获取节点信息:
Selenium 提供了选择节点的方法,返回的是 WebElement 类型
它也有相关的方法和属性来直接提取节点信息,如属性、文本等。
这样的话,我们就可以不用通过解析源代码来提取信息了,方便
属性值:
get_attribute() 方法来获取节点的属性,但是其前提是先选中这个节点
通过get_attribute()方法,然后传入想要获取的属性名,就可以得到它的值
文本:
每个 WebElement 节点都有 text 属性,直接调用这个属性就可以得到节点内部的文本信息
——相当于 Beautiful Soup 的 get_text()方法

WebElement 节点还有一些其他属性
比如
id 属性可以获取节点 id
location 属性可以获取该节点在页面中的相对位置
tag_ name 属性可以获取标签名称
size 属性可以获取节点的大小,也就是宽高

繁琐一点的话,就用page_source 属性获取网页的源代码,接着使用解析库

切换Frame(子页面):
switch_to.frame()方法
Selenium在一个 页面中,完成 对这个页面 的操作。在父页面无法对子Frame操作

延时等待:
确保节点已经加载出来——在 Selenium 中,get()方法会在网页框架加载结束后
结束执行,此时可能并不是浏览器完全加载完成的页面
1:隐式
换句话说,当查找节点 而节点并没有立即出现的时候,隐式等待 将等待一段时间再查找DOM,默认的时间是0
implicitly_ wait()
2:显式
隐式等待的效果并没有那么好,因为我们只规定了一个 固定时间,而页面的加载时间会受到网络条件的影响

显式——它指定一个等待条件(要查找的节点),然后指定一个最长等待时间。
如果在规定时间内满足 等待条件(加载出来了这个节点),就返回要查找的节点;
如果到了规定时间还没有 等待条件(没有加载出该节点),则抛出超时异常
eg:

from selenium.webdriver.support import expected_conditions as EC
wait = WebDriverWait(browser, 10)
input = wait.until(EC.presence_of_element_located((By.ID, 'q')))
#首先引入WebDriverWait这个对象,指定最长等待时间,然后调用它的until()方法,传入要等待条件expected_conditions。比如,这里传入了presence_of_element_located这个条件,代表节点出现的意思,其参数是节点的定位元组,也就是ID为q的节点搜索框

更多等待条件的参数及用法,参考官方文档:http://selenium-python.readthedocs.io/api.html#module-selenium.webdriver.support.expected_conditions
前进后退:
back()方法后退,
forward()方法前进
eg:

import time
from selenium import webdriver

browser = webdriver.Chrome()
browser.get('https://www.baidu.com/')
browser.get('https://www.taobao.com/')
browser.get('https://www.python.org/')

browser.back()
time.sleep(1)
browser.forward()
browser.close()

Cookies:
对 Cookies 进行操作
例如获取、添加、删除 Cookies 等
get_cookies() ——获取
add_cookie()——添加
delete_all_cookies() ——删除所有的 Cookies

选项卡:
execute_ script()方法
switch_ to_ window()——切换选项卡

异常处理:
try except 语句——捕获异常,放置程序遇到异常而中断

实战:selenium模拟登陆163(126)邮箱

# 登陆,打开网页页面,加载成功后,找到账号密码框,输入账号密码,点击登陆
# 对应
#访问页面。查找输入框等节点。输入cookes等信息,模拟点击(交互)

from selenium import webdriver
import time

url = 'https://www.126.com/'
def open_page(url):
    browser = webdriver.Chrome()
    browser.get('https://www.126.com/') #打开网页
    time.sleep(2)
    #以上代码OK
    browser.switch_to.frame(0)#关键
    
    #找到账号框,密码框,登陆按钮。然后输入信息
    card = browser.find_element_by_name('email')#账号框
    card.send_keys('dengzhanh')
    
    password = browser.find_element_by_name('password') #密码框
    password.send_keys('*******')
    
    login = browser.find_element_by_id('dologin')#登陆按钮
    login.click()

def main():
    open_page(url)
    
if __name__=='__main__':
    main()

问题:
1—browser.switch_to.frame(0) 是在同一界面选择一个子界面么?()内的参数怎么填?
2—账号密码框 在源码中,如何快捷地找到其 属性?

3.2 IP ——参考:网络爬虫开发实战
IP(代理):
网站为了防止被爬取,会有反爬机制
服务器会检测某个IP在单位时间内的请求次数,如果超过了这个阈值,就会直接拒绝服务,返回一些错误信息——可以称为封IP

应对IP被封的问题:
修改请求头,模拟浏览器(把你当做是个人)访问
采用代理IP 并轮换
设置访问时间间隔(同样是模拟人,因为人需要暂停一会)

代理:在本机 和 服务器 之间搭桥
本机不直接发送请求,通过桥(代理服务器)发送请求
web代理 通过桥 返回 响应

请求库的代理设置方法
1:requests 的代理设置:只需要构造代理字典,然后通过 proxies
数即可,而不需要重新构建 pener

proxies = {
'http': 'http ://'+ proxy,
'https': 'https://'+ proxy, 

如果需要 验证,下面的代码输入两个部分即可
proxy= ‘username:password@代理 ’

使用 SOCKS5 代理(需要安装SOCKS库)
1:

proxies = {
'http':'socks5 ://'+ proxy,
'http': 'socks5: // '+ proxy
}

2:全局设置

import requests
import socks
import socket
socks.set_default_proxy(socks . 50CKS5,’127.0 .0.1 ’, 9742)
socket.socket = socks.socksocket 

2:Selenium代理设置
以Chrome为例

from selenium import webdriver

proxy= 127.0.0.1:9743
chrome_ options = webdriver.ChromeOptions ()
chrome_options.add_argument('…proxy-server=http://'+ proxy)

browser = webdriver.Chro e(chrome_options=chrome_options)
browser.get(’ http://httpbin.org/get ' ) 

若是 认证代理:
需要在本地创建一个 manifest.json 配置文件 和 background.js 脚本来设置认证代理
运行代码之后本地会生成一个 proxy auth __plugin.zip 文件来保存当前配置

代理池:
不是所有的代理都能用,所以要进行 筛选,提出不可用代理,保留可用代理
∴ 建立代理池
设计代理的基本思路:(代理池的目标)
1:存储模块(存代理)——负责存储抓取下来的代理。首先要保证代理不重复,要标识代理的可用情况,还要动态实时处理每个代理。
所以一种比较高效方便的存储方式就是使用 Redis的Sorted Set,即有序集合

2:获取模块(抓代理)——需要定时在各大代理网站抓取代理。代理可以是免费公开代理也可以是付费代理,代理的形式都是 IP 加端口,此模块尽量从不同来源获取,尽量抓取高匿代理,抓取成功之后将 可用代理 保存到数据库中

3:检测模块(能用否)——需要定时检测数据库中的代理。这里需要设置一个检测链接,最好是爬取哪个网站就检测哪个网站,这样更加有针对性,如果要做一个通用型的代理,那可以设置百度等链
接来检测。
另外,我们需要标识每一个代理的状态,如设置分数标识,100分代表可用,分数越少代表越不可用。——检测一次,如果代理可用,我们可以将分数标识立即设置为100分,也可以在原基础上加1分;如果代理不可用,可以将分数标识减1分,当分数减到一定阈值后,代理就直接从数据库移除。通过这样的标识分数,我们就可以辨别代理的可用情况,选用的时候会更有针对性

4:接口模块(拿出来)——需要用 API 来提供对外服务的接口。其实我们可以直接连接数据库采取对应的数据,但是这样就需要知道数据库的连接信息,并且要配置连接。
而比较安全和方便的方式就是提供一个 Web API 接口,我们通过访问接口即可拿到可用代理。另外,由于可用代理可能有多个,那么我们可以 设置一个 随机返回 某个可用代理 的接口,这样就能保证 每个可用代理都可以取到,实现 负载均衡。

根据以上,设计代理池架构
在这里插入图片描述
注:
存储模块——使用 Redis 有序集合,用来做代理的 去重 和 状态标识,同时它也是中心模块和基
础模块,将其他模块串联起来
获取模块——定时从代理网站获取代理,将获取的代理传递给存储模块,并保存到数据库
检测模块——定时通过存储模块获取所有代理,并对代理进行检测,根据不同的检测结果对代理
设置不同的标识
接口模块——通过 WebAPI 提供服务接口,接口通过连接数据库并通过Web 形式返回可用的代理

4个模块的实现

1:存储模块
这里我们使用 Redis 的有序集合,集合的每一个元素都是不重复的
对于代理池来说,集合的元素就变成了 个个代理,也就是 IP 加端口的形式,
eg:60.207.237.111 :8888 ,这样的一个代理就是集合的一个元素。
另外,有序集合的每一个元素都有一个分数字段,分数是可以重复的,可以是浮点数类,也可以是整数类型。
该集合会根据每一个元素的分数对集合进行排序,数值小的排在前面,数值大的排在后面,这样就可以实现集合元素的排序了。
对于代理池来说,这个分数可以作为判断一个代理是否可用的标志, 100 为最高分,代表最可用,0为最低分,代表最不可用。
如果要获取可用代理,可以从代理池中随机获取分数最高的代理,注意是随机,这样可以保证每个可用代理都会被调用到
引入分数机制
定义常量,比如:分数(最大最小初始)、Redis的连接信息(地址、端口、密码)、有序集合的键名(获取)
定义类,用于操作Redis的有序集合,其中定义一些方法,用于处理集合中的元素。

获取模块:
定义一个 Crawler 来从各大网站抓取代理
将获取代理的每个方法统一定义为以Crawl 开头,这样扩展的时候只需要添加Crawl 开头的方法即可。
这些方法都定义成了生成器,通过 yield返回代理。程序首先获取网页,然后用解析,解析出 IP加端口的形式的代理 然后返回
然后定义了一个 get_proxies ()方法,将所有以 crawl 开头的方法调用一遍,获取每个方法返回的代理 并 组合成列表形式返回
依次通过 get_proxies方法调用,得到各个方法抓取到的代理,然后再利用 Redi sClien的add方法加入数据库,这样获取模块的工作就完成了
检测模决:
使用异步请求库aiohttp
接口模块:
代理池可以作为一个独立服务运行,我们最好增加一个接口模块,并以 WebAPI的形式暴露可用代理——获取代理只需要请求接口即可
调度模块:
调度模块就是调用以上所定义的 3个模块,将这 个模块通过多进程的形式运行起来
实战:

import requests
from bs4 import BeautifulSoup
from collections import OrderedDict
from threading import Thread
from datetime import datetime
start_time = datetime.now()

def get_xici_proxy(url,headers):
    response = requests.get(url, headers=headers).content
    res = response.decode('utf-8')
    soup = BeautifulSoup(res, 'lxml')
    tag_tr_all = soup.find_all('tr')

    info_names = tag_tr_all[0].get_text().strip().split('\n')
    # global proxy_list
    t_list = []
    for tag_tr in tag_tr_all[1:]:  
        tag_td = tag_tr.find_all('td')#
        try:
            country = tag_td[0].img['alt'] 
        except TypeError:#
            country = 'None'
        try:
            ip_info_list = [td.get_text(strip=True) for td in tag_td[1:]] 
            ip_info_list.insert(0,country)
            ip_info_dict = OrderedDict(zip(info_names,ip_info_list))
            t = Thread(target =check_proxy,args=(ip_info_dict,))
            t_list.append(t)
        except Exception as e:
            print("登录错误",e)
    for i in range(len(tag_tr_all[1:])):
        t_list[i].start()
    for i in range(len(tag_tr_all[1:])):
        t_list[i].join()

def check_proxy(info):
    proxy = {info['类型'].lower():r"{}://{}:{}".format(info['类型'].lower(),info['IP地址'],info['端口']),}
    try:
        response1 = requests.get(r"http://httpbin.org/get",proxies=proxy,timeout=10)
        print(response1.status_code)
        if response1.status_code==200:
            info['proxy'] = proxy
            proxy_list.append(info)
    except Exception as e:
        pass#
if __name__ == "__main__":
    url = r"https://www.xicidaili.com/nn"
    headers = {
        'User-Agent': "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50"
    }
    proxy_list = [] 
    get_xici_proxy(url,headers)

    print("有效代理数:",len(proxy_list))
    print("第二个代理地址:",proxy_list[1].get('proxy'))
    print("第二个代理地址类型:",proxy_list[1].get('类型'))
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/134465.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • 电容作用分类_电容的分类与识别

    电容作用分类_电容的分类与识别电容分类的N种详解,有图有“真相”电子发烧友网今天一、瓷介电容器(CC)1.结构用陶瓷材料作介质,在陶瓷表面涂覆一层金属(银)薄膜,再经高温烧结后作为电极而成。瓷介电容器又分1类电介质(NPO、CCG));2类电介质(X7R、2X1)和3类电介质(Y5V、2F4)瓷介电容器。2.特点1、类瓷介电容器具有温度系数小、稳定性高、损耗低、耐…

  • 这些最常用的Linux命令,每一条都应该学会!

    点击上方“全栈程序员社区”,星标公众号 重磅干货,第一时间送达 作者:陈良 cnblogs.com/chenliangchaoshuai/p/11827383.html linux…

  • scl语言用plc脉冲做定时器_PLC编程,如何学习SCL语言?SCL语言编程入门「建议收藏」

    scl语言用plc脉冲做定时器_PLC编程,如何学习SCL语言?SCL语言编程入门「建议收藏」随着现代工控技术的不断发展,可能很多使用过PLC的技术人员都有这么一个感受:传统的‘梯形图’编程方式在面对越来越复杂的控制要求时,已显得力不从心。其实,现在很多大品牌的中高级PLC都支持国际电工委员会IEC61131标准中规范的五种编程语言的混合编程,即梯形图(LD)、结构化文本(ST)、流程图(SFC)、指令表(IL)和功能块(FB)。在这五种编程语言中,梯形图+结构化文本是一…

  • 服务器版dll修复工具,dll修复工具「建议收藏」

    服务器版dll修复工具,dll修复工具「建议收藏」winmm.dll是Windows多媒体相关应用程序接口,用于低档的音频和游戏手柄,缺少它可能造成部分软件无声音。当你的电脑提示“丢失winmm.dll”或者“没有找到winmm.dll”等类似错误信息。如果sqlite3.dll系统文件丢失、损坏,自行寻找选择适合系统的DLL系统文件,不但麻烦,还得冒着系统异常的风险。无主之地、荣誉勋章等游戏所需的physxcudart_20.Dll下载,解压后…

  • Java课程设计——学生成绩管理系统

    Java课程设计——学生成绩管理系统Java课程设计题目:学生成绩管理系统摘要在现今信息时代,生活速度的加快,使得人们越来越向信息化、数字化发展。随着学校的规模不断扩大,学生数量急剧增加,有关学生的各种信息量也成倍增长,尤其是学生的考试成绩数据。面对庞大的学生的成绩,需要有学生成绩管理系统来提高学生管理工作的效率。介于此提出了学生成绩管理系统,学生管理系统是计算机对学生档案信息进行管理,具有手工管理无可比拟的优点,如索检迅速、查找方便、可靠性高、存储量大等有点。现在我国的大中专院校的学生成绩管理水平正在不断提高,停留在纸介质

  • ip addr命令详解_c++中add是什么意思

    ip addr命令详解_c++中add是什么意思OverviewTheipcommandisaLinuxnet-toolforsystemandnetworkadministators.TheipcommandreplacesoldgoodandnowdeprecatedifconfigcommandonmodernLinuxdistributions.用法ip[options]OBJECTCOMMANDipaddr#查看ipethomeansEthernet,wl..

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号