导语

前段时间在学习Python爬取豆瓣电影信息的过程中发现如果同一IP短时间内持续访问的话会导致IP地址被限制访问,页面提示要求登录。解决IP地址被封除了在爬取数据时增加延迟,另外一个方法就是使用代理。代理IP从何而来呢?一是网上购买,长期稳定使用;二是爬取代理网上的免费代理,绝大多数无法使用。

本文以爬取西刺代理-国内HTTP代理为例,爬取网页数据、验证代理IP有效性并将有效的IP写入CSV文件:


导入模块

import requests,random,csv,re,time
from multiprocessing import Pool,cpu_count
常见的User_Agent
这部分在网上搜索会找到很多,如常见浏览器User-Agent大全,我们可以将一些常见的添加到列表里并随机获取一个以模拟不同浏览器请求网页数据。
userAgentList =[
'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36 OPR/26.0.1656.60
Opera/8.0 (Windows NT 5.1; U; en)',
'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:34.0) Gecko/20100101 Firefox/34.0',
'Mozilla/5.0 (X11; U; Linux x86_64; zh-CN; rv:1.9.2.10) Gecko/20100922 Ubuntu/10.10 (maverick) Firefox/3.6.10',
'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534.57.2 (KHTML, like Gecko) Version/5.1.7 Safari/534.57.2',
'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11',
'Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko'
]
爬取代理及多进程验证IP是否可用
def getProxyList(url):
proxyIPs =[] #代理IP数组
headers = {'User-Agent': random.choice(userAgentList)}
try:
res= requests.get(url,headers=headers,timeout = 3)
if res.status_code ==200:
# 获取元组数组,元组是(ip,port)格式
results = re.findall(r'
(\d+\.+\d+\.+\d+\.+\d+).*?>(.*?)',res.text,re.S) # 使用正则表达式 
 
for (ip,port) in results:
proxyIP = 'http://{}:{}'.format(ip,port)
# 将所有代理IP 添加到数组里
proxyIPs.append(proxyIP)
# 创建进程池对代理IP验证
pool = Pool(cpu_count())
pool.map(verifyProxy,proxyIPs)
pool.join()
pool.close()
else:
print('无法获取网页内容')
except Exception as e:
print('出错啦:{}'.format(e))
我们爬取到的代理并不是都能正常使用的,我之前爬取了20页的数据,通过测试发现只有28个代理能用。
def verifyProxy(ip):
# 验证代理是否可用的网站(可以使用其他大型网站)
verifyUrl = 'https://www.baidu.com'
proxy = {'http' : ip,
'https': ip
}
headers = {'User-Agent': random.choice(userAgentList)}
with open('代理IP地址文件.csv', 'a+', newline='') as f:
writer = csv.writer(f)
try:
# 使用代理IP访问百度,如果能够正常访问,则将IP写入CSV
r = requests.get(verifyUrl,proxies = proxy,headers = headers,timeout = 5) #这边的超时时间自行定义
if r.status_code == 200:
writer.writerow([ip])
f.close()
except Exception as e:
print('出错啦{}'.format(e))
爬取多页并打印耗时时间
def main():
start = time.strftime('%Y-%m-%d %H:%M:%S',time.localtime((time.time())))
print('开始时间是:{}'.format(start))
for page in range(1,20):
url = 'http://www.xicidaili.com/wt/{}'.format(page)
getProxyList(url)
end = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime((time.time())))
print('结束时间是:{}'.format(end))
if __name__ == '__main__':
main()

结语

虽然我在程序中采用了多进程进行IP验证,但是爬取20页的数据、IP进行验证及写入CSV文件这整个过程耗时12分钟左右。

本文只使用了多进程对IP地址进行验证,如何使用多进程同时处理爬取代理和验证代理,以进一步提高效率呢?