PythonPython爬虫爬虫

Python爬虫学习(二十一)代理池

2018-03-19  本文已影响380人  弃用中

当你兴高采烈的运行着自己的爬虫时,一种很有可能出现的情况就是,没过多久它就爬取不到满足你需要的信息了,为什么呢?因为网站会有一些反爬虫手段呗!比如,后台对访问进行统计, 如果单个IP访问超过阈值, 予以封锁。这个时候我们就可以尝试使用代理服务器。

什么是代理服务器

Web代理(proxy)服务器是网络的中间实体。 代理位于Web客户端和Web服务器之间,扮演“中间人”的角色。
HTTP的代理服务器即是Web服务器又是Web客户端。

Fiddler就是个典型的代理

Fiddler 是以代理web服务器的形式工作的,它使用代理地址:127.0.0.1, 端口:8888. 当Fiddler退出的时候它会自动注销代理,这样就不会影响别的程序

代理作用一:翻墙

很多人都喜欢用Facebook, 看YouTube。但是我们在天朝,天朝有The Great of Wall(长城防火墙),屏蔽了这些好网站。 怎么办? 通过代理来跳墙,就可以访问了。
自己去寻找代理服务器很麻烦, 一般都是用翻墙软件来自动发现代理服务器的。

代理作用二:通过代理上网

比如局域网不能上网, 只能通过局域网内的一台代理服务器上网。

代理作用三:通过代理缓存,加快上网速度

大部分代理服务器都具有缓存的功能,就好像一个大的cache, 它有很大的存储空间,它不断将新取得数据存储到它本地的存储器上, 如果浏览器所请求的数据在它本机的存储器上已经存在而且是最新的,那么它就不重新从Web服务器取数据,而直接将存储器上的数据传给用户的浏览器,这样就能显著提高浏览速度。

等等。

有了上述基础知识后,我们不妨动手实践。首先我们得考虑几个问题:

整体的结构可以如下设计:


本文只是做个简单的演示,就不考虑这么多了,直接上源码:

import requests
from fake_useragent import UserAgent
from scrapy.selector import Selector
import MySQLdb

conn = MySQLdb.connect(host='localhost', user='root', passwd='admin', db='IPs', charset="utf8", use_unicode=True)
cursor = conn.cursor()
user_agent = UserAgent()


def crawl_ips():
    # 爬取西刺的免费ip代理
    header = {
        'User-Agent':user_agent.random
    }

    for page in range(1, 2175):
        response = requests.get('http://www.xicidaili.com/nn/{0}'.format(page), headers=header)
        selector = Selector(text=response.text)
        all_trs = selector.css('#ip_list tr')
        ip_list = []
        for tr in all_trs[1:]:
            speed_str = tr.css('.bar::attr(title)').extract_first()
            if speed_str:
                speed = float(speed_str.split('秒')[0])
            all_texts = tr.css('td::text').extract()
            ip = all_texts[0]
            port = all_texts[1]
            proxy_type = all_texts[5]
            ip_list.append((ip, port, speed, proxy_type))
        for ip in ip_list:
            print(ip)
            cursor.execute(
                """
                insert ip_list(ip,port,speed,proxy_type) values('{0}','{1}',{2},'{3}') ON DUPLICATE KEY 
                UPDATE ip=VALUES(ip), port=VALUES(port), speed=VALUES(speed), proxy_type=VALUES(proxy_type)
                """.format(ip[0], ip[1], ip[2], ip[3])
            )
            conn.commit()


class GetIP(object):
    def delete_ip(self, ip):
        delete_sql = """
        delete frome ip_list where ip='{0}'
        """.format(ip)
        cursor.execute(delete_sql)
        conn.commit()
        return True

    def judge_ip(self, ip, port, proxy_type):
        # 判断ip是否可用
        http_url = 'http://www.baidu.com'
        proxy_url = '{0}://{1}:{2}'.format(proxy_type, ip, port)
        try:
            proxy_dict = {
                proxy_type:proxy_url
            }
            response = requests.get(http_url, proxies=proxy_dict)
            return True
        except Exception as e:
            print('invalid ip and port')
            self.delete_ip(ip)
            return False
        else:
            code = response.status_code
            if code >= 200 and code < 300:
                print('effective ip')
                return True
            else:
                print('invalid ip and port')
                self.delete_ip(ip)
                return False

    def get_random_ip(self):
        # 从数据库中随机获取一个可用ip
        random_sql = """
        SELECT ip, port, proxy_type FROM ip_list
        ORDER BY RAND()
        LIMIT 1
        """
        result = cursor.execute(random_sql)
        for ip_info in cursor.fetchall():
            ip = ip_info[0]
            port = ip_info[1]
            proxy_type = ip_info[2]
            judge_re = self.judge_ip(ip, port, proxy_type)
            if judge_re:
                return '{0}://{1}:{2}'.format(proxy_type.lower(), ip, port)
            else:
                return self.get_random_ip()

推荐一个项目:


当然,如果你只是想用代理池的话,完全可以把它clone到本地,开启服务,接入你的爬虫,很六的哦!

参考文章:
Python爬虫代理池:http://python.jobbole.com/86994/
HTTP协议之代理:http://www.bkjia.com/headlines/491855.html

以上。

上一篇下一篇

猜你喜欢

热点阅读