爬虫技术 - 代理

使用爬虫的时候肯定会有频繁访问某一网站的情况,这个时候有些服务器会识别到这是非正常访问,就会把请求的IP禁掉,这个时候就需要用代理了。就好比现实生活中,我需要向A借一件东西,但是我跟A是仇人,直接向他借的话他不会借给我,这个时候我就让B帮我向A借,就说他要用,然后B借到东西之后再把东西给我用,这时,B就是我的代理了。


代理选择

针对不需要用户登录,cookie验证的网站,一般选择动态高匿代理。
对于需要用户登录,身份认证的。一般选择静态IP。

代理获取

使用代理时一般需要建一个代理池,从代理池中获取有效代理,然后通过代理去访问内容网站。
本节将结合代码介绍代理池的使用。

为了使用方便,web框架简单使用flask。api接口类如下:

from flask import Flask, jsonify
from proxy.ProxyManager import ProxyManager

app = Flask('ProxyPool')


@app.route("/")
def hello():
    return "Hello coder"

# 随机返回一个代理
@app.route("/get")
def get():
    return jsonify(ProxyManager().get())

# 返回所有有效代理
@app.route("/get_all")
def get_all():
    return jsonify(ProxyManager().get_all())

# 返回代理数据库代理数量
@app.route("/get_status")
def get_status():
    return jsonify(ProxyManager().get_status())


if __name__ == '__main__':
    app.run()

代理管理类ProxyManager如下:

# coding=utf-8
from ProxyGetter import ProxyGetter
from dao.RedisClient import RedisClient


class ProxyManager(object):
    """
    代理管理类
    """
    def __init__(self):
        self.db_client = RedisClient()

    def refresh(self):
        for proxy in ProxyGetter.get_proxy_one():
            self.db_client.put(proxy, 'raw')

    def get(self):
        return self.db_client.get()

    def get_all(self):
        return self.db_client.get_all()

    def get_status(self):
        return self.db_client.get_status()


if __name__ == '__main__':
    m = ProxyManager()
    m.refresh()
    print(m.get_all())
    print(m.get_status())

db使用redis做数据库:

# coding: utf-8
from base.base_redis import redis_client


class RedisClient(object):

    def __init__(self):
        self.redis_client = redis_client

    def get(self):
        # 随机返回集合成员
        proxy = self.redis_client.srandmember('useful')
        if proxy:
            return proxy.decode('ascii')
        return None

    def put(self, proxy, sname='useful'):
        return self.redis_client.sadd(sname, proxy)

    def get_all(self):
        # 返回全部集合成员
        proxies = self.redis_client.smembers('useful')
        if proxies:
            proxy_list = []
            for i in proxies:
                proxy_list.append(i.decode('ascii'))
            return proxy_list
        return None

    def get_status(self):
        status = dict()
        # 获取集合的成员数
        status['useful'] = self.redis_client.scard('useful')
        status['raw'] = self.redis_client.scard('raw')
        return status


if __name__ == '__main__':
    r = RedisClient()
    print r.get()

redis_client如下:

import redis
import settings

redis_host = settings.get('redis', 'host')
redis_port = settings.get('redis', 'port')

redis_client = redis.Redis(redis_host, redis_port)

其中settings为配置解析文件,在config配置文件中配置参数,通过settings进行解析。settings文件在博主之前的ORM框架之Sqlalchemy一文中介绍过。

代理获取类如下:

import logging
from util.UtilFunction import get_html_tree


class ProxyGetter(object):

    def __init__(self):
        pass

    @classmethod
    def get_proxy_one(cls):
        url = "http://www.xicidaili.com/nn/"
        html_tree = get_html_tree(url)
        proxies = html_tree.xpath('//table[@id="ip_list"]//tr')[1::]
        for p in proxies:
            try:
                ip = p.xpath('.//td[2]/text()')[0]
                port = p.xpath('.//td[3]/text()')[0]
                yield ip + ":" + port
            except Exception, e:
                logging.exception(e)


if __name__ == '__main__':
    for i in ProxyGetter.get_proxy_one():
        print i

这里以西刺为例,获取其提供的高匿代理。当然,实际上免费代理很多都是无效的,无法使用的,因此在使用之前需要进行验证代理有效性。

代理解析工具类UtilFunction.py如下:

from WebRequest import WebRequest
from lxml import etree


def get_html_tree(url):
    wr = WebRequest()
    html = wr.get(url).content
    return etree.HTML(html)

WebRquest类如下:

# coding:utf-8
import requests


class WebRequest(object):
    def __init__(self):
        pass

    @property
    def header(self):
        headers = {
            'Accept-Encoding': 'gzip, deflate',
            'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',
            'Connection': 'keep-alive',
            'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
            'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) ' \
                          'Chrome/62.0.3202.94 Safari/537.36'
        }
        return headers

    def get(self, url, header=None):
        headers = self.header  # 公共header
        if header and isinstance(header, dict):
            headers.update(header)
        html = requests.get(url, headers=headers)
        return html

至此一个简单的原始代理收集模块已经完成,执行ProxyManager主函数之后,就从代理网站获取到原始代理,并存储到redis数据库中了。查询redis中数据:
在这里插入图片描述
运行程序后通过api接口返回get_status,结果如下:

{"raw":100,"useful":0}

原始代理库中有100条代理记录,有效代理库中无代理记录。

接下来就需要进一步对原始代理进行验证,移除掉无效代理,将有效代理保存到useful表中。

参考资料

[1]https://blog.csdn.net/sinat_34200786/article/details/79451499

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值