爬虫学习日记3-构建免费代理池

爬虫学习日记3-构建免费代理池

学习目标:工作中许多指标数据来源自多个网站,而且由于开发厂家不同,这些系统数据网站没有整合。由于各种原因,我只能拿到其中一小部分API接口,剩余大量数据需要手动下载。所以学习爬虫技术增加工作里的自动化程度,减少人力成本。

这两天主要完成了两个学习任务,当然大部分时间都用在钻研构建代理池了。
一、学习任务a: 安装selenium并学习

  1. 安装selenium并学习。

  2. 使用selenium模拟登陆163邮箱。

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import userInfo #处于保密性考虑,邮箱名称和密码从文件里导入
user = userInfo.user
pwd = userInfo.pwd

browser = webdriver.Chrome()            #实例化一个Chrome浏览器对象
browser.get("https://mail.163.com/")
browser.switch_to_frame(0)                 #不进入字frame无法进入登录界面,frame id为动态的,不能靠id获取
wait = WebDriverWait(browser,20)    #引入一个WebDriverWait对象,timeout设为20s
# browser.implicitly_wait(10)
# 调用until方法,传入要等待的条件expected_conditions.此处使用
#presence_of_element_located,代表节点出现的意思,注意传入1个元祖参数来定位
email_input = wait.until(EC.presence_of_element_located((By.NAME,'email'))) #传一个tuple
print(email_input.get_attribute('data-type'))
email_input.send_keys(user)
pwd_input = browser.find_element_by_name('password')
pwd_input.send_keys(pwd)
login_em = browser.find_element_by_id('dologin')#找到登陆按钮
login_em.click()#点击登陆按钮
#browser.implicitly_wait(10)  #隐式等待
#print(browser.page_source)

起初未考虑switch_to_frame时报错如下,参考https://blog.youkuaiyun.com/weixin_42937385/article/details/88150379知道了先进入子frame中。
在这里插入图片描述

二、学习任务b: 抓取西刺代理,并构建自己的代理池
查找网络资料,说代理分类如下

  • 透明代理
  • 匿名代理
  • 高匿代理
    透明代理在HTTP头里设置了你的真实IP,服务器可以通过HTTP头知晓你真实的IP。
    匿名代理虽然隐藏了你的真实IP,但服务器还是知道你使用了代理。
    高匿代理不仅隐藏了你的真实IP,而且让服务器无法发现你在使用代理,这是我们自建代理池的最佳的选择,我们下一步自建代理池的步骤中用到的也是高匿代理。
    HTTP 代理,只代理 HTTP 网站,对于 HTTPS 的网站不起作用,也就是说,用的是本机 IP,反之亦然。所以本次任务建立的代理池计划用结构化数据,方便验证代理类型
    https://www.xicidaili.com/nn/2,不过此次学习只是体验一把,仅抓取第一页数据。
思路和目标:
  • 使用requests拿到html页面
  • 使用我用起来最习惯的BeautifulSoup解析html数据
  • 输出结构化数据,这里尝试使用了collecitons模块中的OrderedDict。
  • 尝试使用多线程,减少爬取时间
西刺站点网页分析:
  • 西刺站点信息非常规整,高匿代理页面地址如下https://www.xicidaili.com/nn,url后面加数字可以翻页
  • 每页100条数据,加上1个标题。
  • 每条代理所有信息包裹在在1个tr标签里。该条代理10项分类信息包裹在10个td标签里。
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')
    # ['国家', 'IP地址', '端口', '服务器地址', '是否匿名', '类型', '速度', '连接时间', '存活时间', '验证时间']
    info_names = tag_tr_all[0].get_text().strip().split('\n')
    # global proxy_list
    t_list = []
    for tag_tr in tag_tr_all[1:]:    #从第1行开始遍历,应该遍历100次。
        tag_td = tag_tr.find_all('td')#
        try:
            country = tag_td[0].img['alt'] #td字标签img里的属性值,为国家缩写,但有的没有需处理异常
        except TypeError:#
            country = 'None'
        try:
            ip_info_list = [td.get_text(strip=True) for td in tag_td[1:]] #遍历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 = [] #所有有效代理都存到一个list中
    get_xici_proxy(url,headers)

    print("有效代理数量:",len(proxy_list))
    print("第二个代理地址:",proxy_list[1].get('proxy'))
    print("第二个代理地址是否匿名:",proxy_list[1].get('是否匿名'))
    print("第二个代理地址类型:",proxy_list[1].get('类型'))
    print("检测的第二个代理地址存活时间:",proxy_list[1].get('存活时间'))
    print("_"*20)
    use_time = datetime.now()- start_time
    print("程序运行共计耗时:{}秒".format(use_time.seconds))

拿到proxy_list这个机构化数据,可以pickle到本地或到数据库,或者干脆存放在缓存里,在此基础上甚至可以构建一个自动运行的、动态的代理地址池。
print一下部分结果,是我想要的效果。
![在这里插入图片描述](https://img-blog.csdnimg.cn/20190515183327512.png在这里插入图片描述
程序多次运行的结果居然不一样,是因为部分代理不稳定造成的?还是网页又刷新了?如果部分代理不稳,
在这里插入图片描述

三、pd.read_html尝试

网页呈现给我们的是一个表格,那有什么方法可以把它们导出来啊。最后想到了pandas里的read_html方法,尝试一下:

col_names = ['国家', 'IP地址', '端口', '服务器地址', '是否匿名', '类型', '速度', '连接时间', '存活时间', '验证时间']
df2 = pd.read_html(res,skiprows=1)
df2[0].columns = col_names
df2[0]

效果如下,感觉真是太太好用了,解析网页只需一行代码啊!!!以后做爬虫项目,表格类的事情就靠pandas了。在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值