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)


相关推荐

  • Java中的增强型for循环「建议收藏」

    Java中的增强型for循环「建议收藏」增强型for循环定义如下:for(ElementTypeelement:arrayName){};上述for循环可被读为:foreachelementinarrayNamedo{…}——————————————————————————————-…

  • linux查看crontab状态_crontab -e

    linux查看crontab状态_crontab -elinux下定时执行任务的方法在LINUX中,周期执行的任务一般由cron这个守护进程来处理[ps-ef|grepcron]。cron读取一个或多个配置文件,这些配置文件中包含了命令行及其调用时间。cron的配置文件称为“crontab”,是“crontable”的简写。一、cron在3个地方查找配置文件:1、/var/spool/cron/这个目录下存放的是每个用户包括root的cron…

  • VS2010序列号正式版附激活成功教程方法详细攻略

    VS2010序列号正式版附激活成功教程方法详细攻略全球开发者最为瞩目的VisualStudio2010开发工具在4月12日正式发布,现为大家制作一个简单的激活成功教程教程有两种方法,操作不一样,原都一样(针对旗舰版,其他版本方法一样):教程一:步骤1.下载VS2010正式版,下载地址:页面:http://www.microsoft.com/downloads/details.aspx?displaylang=en&Fam

  • 前端参数用MD5加密[通俗易懂]

    前端参数用MD5加密[通俗易懂]今天来讲一下如何用这个MD5来加密第一步:两种导入MD5.js一种你可以到以下这个地址去下载MD5的js路径:https://www.bootcdn.cn/blueimp-md5/另一种下面是md5的js,直接复制下去放到js文件里。亲测可用varhexcase=0;varb64pad="";varchrsz=8;functionhex_md…

  • 怎么复制一台虚拟机到另外一台电脑上

    怎么复制一台虚拟机到另外一台电脑上怎么复制一台虚拟机到另外一台电脑上

  • createfont函数_windows程序设计基于.net平台

    createfont函数_windows程序设计基于.net平台CFont * f; f = new CFont; f->CreateFont(10, // nHeight 0, // nWidth 0, // nEscapement 0, // nOrientation FW_BOLD, // nWeight FALSE, // bItalic …

发表回复

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

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