您的位置:首页 > 编程语言 > Python开发

Python 抓取可用代理IP

2018-03-07 11:39 330 查看

问题描述

在做数据抓取的时候,经常会碰到有些网站对同一IP的访问频率做限制。遇到这种情况一般只有两种解决方案:
降低抓取频率。这种方法在数据变化不频繁,数据量不大的情况下还好,但是,如果数据变化频繁或者数据量庞大,此方法明显不能满足需求。
使用代理IP。抓取的过程中,经常更换代理IP,这种方法基本可以有效解决同一IP访问频率限制的问题。此方案的难点在于如何获取大量可用的代理IP。

代理IP获取

代理IP的获取途径基本也就两种:
购买付费代理IP。一般都是按使用时长和代理IP数收费,优点就是可靠性高。
使用免费代理。可以从免费代理网站获取,但是稳定性不好,绝大部分都会很快失效。
付费代理没什么好讲的,付款之后一般就可以拿到数据接口,程序里边直接调用即可。
下面讲一下免费代理IP的获取及筛选。这种出力不讨好的繁琐工作当然应该交给程序来自动完成。
这里以西刺代理为例讲一下获取https代理的分析过程并给出示例程序。
通过对页面请求进行分析,可以找到包含https代理的实际请求地址是: http://www.xicidaili.com/wn/{page},第一页page=1,第二页page=2...以此类推。西刺代理的IP每几分钟都会更新一次,所以每次只抓取前几页基本就可以了。
网络请求使用Python的requests库,页面解析使用pyquery。也可以使用urllib和beautifulSoup,不过个人感觉稍微麻烦一些。
废话不多说了,下面直接上程序,代码基于Python3编写,如果要在Python2下运行需要稍作修改。"""
该程序用于从代理网站获取可用ip
使用方法1: 直接运行该文件,会在同目录下生成ips.txt文件,文件内包含可用的代理
使用方法2: 其他程序导入该文件,然后直接使用该文件内定义的全局变量'proxies'
"""
import random
import threading
import time
from concurrent import futures

import requests
from pyquery import PyQuery

headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) \
Chrome/53.0.2785.104 Safari/537.36 Core/1.53.2306.400 QQBrowser/9.5.10530.400'}
# 检测代理ip有效性的网站
CHECK_URL = 'https://ip.cn'
# 抓取地址(西刺代理)
FETCH_URL = 'http://www.xicidaili.com/wn/{}'
# 抓取页数,每页100条
PAGES = 3
# 代理类型(http/https)
PROXY_TYPE = 'https'
# 有效代理ip列表
proxies = []
# 线程池,用于同时验证多个代理ip
POOL = futures.ThreadPoolExecutor(max_workers=50)

def add_proxy(proxy: str):
"""
添加代理

:param proxy: 代理ip+端口号
:return:
"""
try:
r = requests.get(CHECK_URL, proxies={PROXY_TYPE: proxy}, timeout=30)
print(PyQuery(r.content.decode()).find('#result').text(), '\n')

if r.status_code == 200 and proxy not in proxies:
proxies.append(proxy)
except Exception as e:
if proxy in proxies:
proxies.remove(proxy)
print(proxy, e)

def fetch_proxy():
"""
抓取代理ip
:return:
"""
for page in range(1, PAGES + 1):
r = requests.get(FETCH_URL.format(page), headers=headers)
doc = PyQuery(r.content.decode('utf-8'))
# 获取数据列表对应的table
table = doc('#ip_list')
# 获取table中除了表头以外的所有行
rows = table('tr:nth-of-type(n+2)').items()
# 提取每一行中的ip和端口号
for row in rows:
ip = row('td:nth-of-type(2)').text()
port = row('td:nth-of-type(3)').text()
proxy = ip + ':' + port
# 在线程池中检测该代理是否可用
POOL.submit(add_proxy, proxy)
# 10秒钟后抓取下一页
time.sleep(10)

def run():
while True:
try:
fetch_proxy()
print('有效代理:', proxies)
# 将有效代理写入文件
with open('ips.txt', 'w', encoding='utf-8') as f:
f.write('\n'.join(proxies))
except Exception as e:
print(e)
# 抓取一次之后休息一段时间,防止被屏蔽
time.sleep(random.randint(100, 600))

# 启动抓取线程
threading.Thread(target=run).start()
程序运行一段时间之后,打开ips.txt文件即可看到抓取到的可用代理IP,如图:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Python代理IP抓取