scrapy突破反爬的几种方式(二)

  1. 云栖社区>
  2. 博客>
  3. 正文

scrapy突破反爬的几种方式(二)

sixkery 2018-09-16 17:17:00 浏览801
展开阅读全文

上回说到设置随机 User-Agent ,这次来一个随机代理 ip 的设置。

代理ip

在爬虫中,为了避免网站将我们的 ip 封掉,我们就要使用代理 ip 。虽然说代理 ip 没有原装的好,但是有些时候还是要使用代理ip 来获取数据的。

原理

随机代理 ip 简单来说就是爬取网上的免费代理ip ,然后存入数据库,在数据库中随机拿到一个代理ip来用。具体结合到 scrapy 中,我们就要在 Middleware.py 文件中修改,原理跟上文代理的设置一样,不懂的可以去上篇文章看一下。

实战演练

在上文的 scrapydownloadertest 项目基础上操作。
在 spiders 的同级目录下,新建一个 Python Package 。还要新建python文件,具体名称参考图片。目录结构如下:


img_d94145eb7d5364608e09d805a69c7e3d.png
目录结构

从西刺网上获取免费的代理ip 保存到数据库中。

import requests
from scrapy.selector import Selector
import pymysql

# 连接数据库
conn = pymysql.connect(host='',user='',password='',db='proxy',charset='utf8')
cursor = conn.cursor()
# 爬取西刺网站上的代理ip

def crawler_ips():
    headers = {
        'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36'
    }
    for i in range(100):
        url = 'http://www.xicidaili.com/nn/'.format(i)
        r = requests.get(url,headers=headers)
        selector = Selector(text=r.text)
        all_ips = selector.css('#ip_list tr')
        ip_list = []
        for tr in all_ips[1:]: # 这里由于第一个是标题,舍弃
            speed_str = tr.css('.bar::attr(title)').extract_first()[0]
            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,proxy_type,speed))

        for ip_info in ip_list:
            # 插入数据
            cursor.execute(
                "insert proxy_ip(ip,port,speed,proxy_type) VALUES('{0}','{1}',{2},'HTTP')".format(
                ip_info[0],ip_info[1],ip_info[3]
                )
            )
            conn.commit()

数据库我用的是MySQL,在 navivat for mysql 中连接 MySQL ,新建一个数据库,名称随意,这里就叫做 proxy 吧,在代码中把连接数据库的代码补充完整。
新建一个数据表 proxy_ip 并写下如下字段:


img_26a607a5c90f8a28c5fbb7f708a24f83.png
proxy_ip

这里我已经新建好了,并且运行的代码。

新建之后,我们运行上述代码,这时候会看到数据库中已经有了数据。接下来就是从数据库中随机获取一个代理 ip ,供我们程序使用。


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

    def judge_ip(self,ip,port):
        # 判断ip 是否可用
        http_url = 'http://www.baidu.com'
        proxy_url = 'http://{0}:{1}'.format(ip,port)
        try:
            proxy_dict = {
                'http':proxy_url
            }
            r = requests.get(http_url,proxies=proxy_dict)
            print('effective ip')
            return True
        except Exception as e:
            print('invalid ip and port 无效')
            self.delete_ip(ip)
            return False
        else:
            code = r.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 delete_ip(self,ip):
        # 删除无效的ip
        delete_sql = "delete from proxy_ip where ip = '{0}'".format(ip)
        cursor.execute(delete_sql)
        conn.commit()

if __name__ == '__main__':
    get_ip = GetIP()
    print(get_ip.get_random_ip())

这里从数据库中随机获取一个代理ip,并测试代理ip是否可用,不可用的删掉。这里有个小技巧,如果你爬取的是其他网站,就把百度的链接换成你要爬取的网站,这样会提高代理ip的可用性。
运行此代码会随机获取一个可用的ip代理。

接下来在 Middleware.py 中把代理ip 加上:

class RandomProxyMiddleware(object):
    # 动态设置ip代理
    def process_request(self, request, spider):
        get_ip = GetIP()

        request.meta['proxy'] = get_ip.get_random_ip()

在 settings.py 文件中配置一下:


DOWNLOADER_MIDDLEWARES = {
    'scrapy.contrib.downloadermiddleware.useragent.UserAgentMiddleware': None,
    'scrapydownloadertest.middlewares.RandomUserAgentMiddleware': 543,
    'scrapydownloadertest.middlewares.RandomProxyMiddleware': 544,

}

运行spider文件,就可以在输出的日志上面看到代理ip在使用了。

2018-09-16 16:57:46 [urllib3.connectionpool] DEBUG: http://123.249.88.153:9000 "GET http://www.baidu.com/ HTTP/1.1" 200 None
effective ip

总结

  • 使用这样的方法可以用到代理 ip 从而有效的隐藏了自己的真实 ip 。免费从网上获取的代理通常来说没有付费得到的 ip 稳定性好。如果有条件,还是建议自费获取一些代理 ip。

  • 自己的代理还是最好用的,我们在爬取的时候可以放慢速度,增加延迟等方式以避免自己的 ip 被封。同时不要让网站的压力太大。这样才能共存。

网友评论

登录后评论
0/500
评论
sixkery
+ 关注