# -*- coding:utf-8 -*-
import urllib2
import random
import lxml
from bs4 import BeautifulSoup
import time
import requests
from fake_useragent import UserAgent
from threading import *
import threading
import sys
screenLock = Semaphore(value=1)
# 信号量设置成 1
'''
2019/9/2
查看urllib2官方文档 BeautifulSoup 官方文档 lxml官方文档 重修爬虫基础知识
在使用 beautifulsoup的时候 推荐使用lxml作为解析器,因为效率更高,另外还有htmlparser python内置标准库
Beautiful Soup将复杂HTML文档转换成一个复杂的树形结构,每个节点都是Python对象,所有对象可以归纳为4种:
Tag , NavigableString , BeautifulSoup , Comment .
1.代理IP的获取/补充渠道,定期把获取到的代理ip加入到代理池中(这里可以考虑python跟数据库的交互
2.代理ip的验证机制,定期验证代理池中ip的有效性,并删除掉所有失效的ip
3.一个web服务,用以提供获取一个随机代理的api
#4.squid3的维持脚本,它定期获取代理池中的可用ip,更新squid中的可转发代理列表
#5.一个调度器,程序的入口,用来协调各组件的运行
'''
def check_IP(ip, http_type):
'''
在python中,requests使用代理要比urllib好用太多,urllib还是有些交互性差。
如果需要使用代理,你可以通过为任意请求方法提供 proxies 参数来配置单个请求:
你也可以通过环境变量 HTTP_PROXY 和 HTTPS_PROXY 来配置代理。
若你的代理需要使用HTTP Basic Auth,可以使用 http://user:password@host/ 语法:
要为某个特定的连接方式或者主机设置代理,使用 scheme://hostname 作为 key, 它会针对指定的主机和连接方式进行匹配。
在这里我们使用proxies参数来配置单个请求,检测ip地址的存活情况
'''
proxy_ip = {http_type: ip}
headers = headers_pool()
result = requests.get("http://www.baidu.com", headers=headers, proxies=proxy_ip)
if result.status_code == 200:
return True
else:
return False
def output(ip,port,web_type):
screenLock.acquire()
if (check_IP(str(ip + ":" + port), web_type)):
sys.stdout.write(str(web_type) + "://" + str(ip) + ":" + str(port) + " True\n")
else:
sys.stdout.write(str(web_type) + "://" + str(ip) + ":" + str(port) + " False\n")
screenLock.release()
def xici_catch_ip(rep):
'''
Beautiful Soup 是一个可以从HTML或XML文件中提取数据的Python库.
它能够通过你喜欢的转换器实现惯用的文档导航,查找,修改文档的方式.
Beautiful Soup会帮你节省数小时甚至数天的工作时间.
'''
soup = BeautifulSoup(rep.read(), 'lxml')
tr_list = soup.find_all('tr')[1:]
'''
最简单的过滤器是字符串.在搜索方法中传入一个字符串参数,Beautiful Soup会查找与字符串完整匹配的内容
在这里我们从第二个 <tr> 的地方开始搜索,具体原因看西刺代理网站的源代码就可以知道
如果传入正则表达式作为参数,Beautiful Soup会通过正则表达式的 match() 来匹配内容
'''
for tr in tr_list:
td_list = tr.find_all('td')
output(td_list[1].text,td_list[2].text,td_list[5].text)
# 在西刺代理的每一页上有100个代理ip地址
def kuaidaili_catch_ip(rep):
soup=BeautifulSoup(rep.read(),'lxml')
tr_list=soup.find_all('tr')[1:]
for tr in tr_list:
td_list=tr.find_all('td')
output(td_list[0].text,td_list[1].text,td_list[3].text)
def headers_pool():
'''
使用fake_useragent来每次随机生成不同的useragent 避免在爬取代理ip的时候被代理网站屏蔽
'''
ua = UserAgent()
headers = {'User-Agent': ua.random}
return headers
def log():
return '''
__ __ __________
_/ |_ ____ _______/ |_ \______ \_______ _______ ______.__.
\ __\/ __ \ / ___/\ __\ | ___/\_ __ \/ _ \ \/ < | |
| | \ ___/ \___ \ | | | | | | \( <_> > < \___ |
|__| \___ >____ > |__|____|____| |__| \____/__/\_ \/ ____|
\/ \/ /_____/ \/\/
'''
def check_url(url):
headers = headers_pool()
req = urllib2.Request(url, headers=headers)
try:
return urllib2.urlopen(req)
except urllib2.URLError:
pass
def xici_url():
url = "https://www.xicidaili.com/nn/"
for i in range(1, 10):
test_url = url + str(i)
rep=check_url(test_url)
if rep!=None:
t = threading.Thread(target=xici_catch_ip, args=(rep,))
t.start()
# 带参数的用args传元组类型(参数最后多加一个逗号“,”要不然会报错) 血的教训
def kuaidaili_url():
url2 = "https://www.kuaidaili.com/free/inha/"
for i in range(1, 10):
test_url = url2 + str(i)
rep=check_url(test_url)
if rep!=None:
t = threading.Thread(target=kuaidaili_catch_ip, args=(rep,))
t.start()
def main():
print log()
xici_url()
kuaidaili_url()
'''
发起请求的时候,使用urllib2里面的Requests方法 带url 和 headers
使用urllib2里面的urlopen方法的时候不需要带headers
我们客户端先对服务器端发起请求 带上自己的headers信息 服务器返回request 对应的 请求响应 response
'''
if __name__ == "__main__":
main()
后期编写添加API接口以及代理池与数据库的交互