- 了解selenium
selenium是一个用于Web应用程序测试的工具,支持的浏览器包括IE(7, 8, 9, 10, 11),Mozilla Firefox,Safari,Google Chrome,Opera等
selenium常用的查找元素方法:
find_element_by_name
find_element_by_id
find_element_by_xpath
find_element_by_link_text
find_element_by_partial_link_text
find_element_by_tag_name
find_element_by_class_name
find_element_by_css_selector
获取元素属性
get_attribute(‘class’)
获取文本值
text
获取ID,位置,标签名
id
location
tag_name
size
Frame
在很多网页中都是有Frame标签,所以我们爬取数据的时候就涉及到切入到frame中以及切出来的问题,常用的是switch_to.from()和switch_to.parent_frame()
- 安装selenium
安装chromedriver查看chrome浏览器版本,再去找对应的chromedriver安装,我的版本是74.0.3729.131
http://chromedriver.storage.googleapis.com/index.html
找到自己的版本对应的chromedriver,win系统只有32位的,安装。
然后将.exe文件放到chrome的安装文件中,chrome安装路径我的是:C:\用户\ACER\AppData\Local\Google\Chrome\Application,可以在桌面选中chrome右击打开文件位置来找。
放好后将这个路径添加到环境变量中,
由于我的系统是win8,右键桌面这台电脑-系统-高级系统设置即可找到环境变量
安装selenium
启动annaconda prompt,命令行输入直接conda install selenium
试运行selenium
from selenium import webdriver
browser = webdriver.Chrome()
browser.get(“http://www.baidu.com”)
弹出chrome的窗口,并显示chrome正受到自动测试软件的控制
from selenium import webdriver
import time
from selenium.webdriver.common.keys import Keys
browser = webdriver.Chrome()
browser.get("https://mail.163.com/")
time.sleep(5)
browser.maximize_window()#打开网页窗口
time.sleep(7)
bowser.switch_to.frame(0)#找到邮箱账号登录框对应的iframe,由于网页中iframe的id是动态的,所以不能用id寻找
email = browser.find_element_by_name('email')#找到邮箱账号输入框
email.send_keys('XXXXX')#由于后面@163.com固定,将自己的邮箱地址前缀输入到邮箱账号框中
password = browser.find_element_by_name('password')#找到密码输入框
password.send_keys('******')#输入自己的邮箱密码
login_em = browser.find_element_by_id('dologin')#找到登陆按钮
login_em.click()#点击登陆按钮
time.sleep(10)
- 学习IP相关知识
IP是互联网协议网址,分配给用户上网使用的网际协议(英语:Internet Protocol, IP)的设备的数字标签。
地址格式为:IP地址=网络地址+主机地址或 IP地址=网络地址+子网地址+主机地址。
IP被封情况:
网站为了防止被爬取,会于同一个IP地址进行大量同类型访问行为设置反爬机制,封锁IP,过一段时间后,才能继续访问。
应对IP被封:
1.修改请求头,模拟浏览器(而不是代码去直接访问)去访问
2.设计代理池,采用代理IP并轮换
3.设置访问时间间隔 - 抓取西刺代理,并构建自己的代理池
抓取代理IP
结果如下:
使用代理
proxies的格式是一个字典:
{‘http’: ‘http://IP:port‘,‘https’:'https://IP:port‘}
把它直接传入requests的get方法中
web_data = requests.get(url, headers=headers, proxies=proxies)
def open_url_using_proxy(url, proxy):
headers = {'User-Agent':"Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.1.6) "}
proxies = {}
if proxy.startswith('HTTPS'):
proxies['https'] = proxy
else:
proxies['http'] = proxy
try:
r = requests.get(url, headers = headers, proxies = proxies, timeout = 10)
r.raise_for_status()
r.encoding = r.apparent_encoding
return (r.text, r.status_code)
except:
print('无法访问网页' + url)
return False
url = 'http://www.baidu.com'
text = open_url_using_proxy(url, proxy_ip_list[0])
确认代理IP地址有效性
无论是免费还是收费的代理网站,提供的代理IP都可能失效,我们应该验证一下,有效后,再放入我们的代理IP池中,以下通过几种方式:
1.访问网站,得到的返回码是200
2.真正的访问某些网站,获取title等,验证title与预计的相同
3.访问某些可以提供被访问IP的网站,类似于“查询我的IP”的网站,查看返回的IP地址是什么
4.验证返回码
from bs4 import BeautifulSoup
import requests
import re
import json
def open_proxy_url(url):
headers = {'User-Agent':"Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.1.6) "}
try:
r = requests.get(url, headers = headers, timeout = 10)
r.raise_for_status()
r.encoding = r.apparent_encoding
return r.text
except:
print('无法访问网页' + url)
def get_proxy_ip(response):
proxy_ip_list = []
soup = BeautifulSoup(response, 'html.parser')
proxy_ips = soup.find(id = 'ip_list').find_all('tr')
for proxy_ip in proxy_ips:
if len(proxy_ip.select('td')) >=8:
ip = proxy_ip.select('td')[1].text
port = proxy_ip.select('td')[2].text
protocol = proxy_ip.select('td')[5].text
if protocol in ('HTTP','HTTPS','http','https'):
proxy_ip_list.append(f'{protocol}://{ip}:{port}')
return proxy_ip_list
def open_url_using_proxy(url, proxy):
headers = {'User-Agent':"Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.1.6) "}
proxies = {}
if proxy.startswith(('HTTPS','https')):
proxies['https'] = proxy
else:
proxies['http'] = proxy
try:
r = requests.get(url, headers = headers, proxies = proxies, timeout = 10)
r.raise_for_status()
r.encoding = r.apparent_encoding
return (r.text, r.status_code)
except:
print('无法访问网页' + url)
print('无效代理IP: ' + proxy)
return False
#使用title确认IP有效性
def check_proxy_avaliability(proxy):
url = 'http://www.baidu.com'
result = open_url_using_proxy(url, proxy)
VALID_PROXY = False
if result:
text, status_code = result
if status_code == 200:
r_title = re.findall('<title>.*</title>', text)
if r_title:
if r_title[0] == '<title>百度一下,你就知道</title>':
VALID_PROXY = True
if VALID_PROXY:
check_ip_url = 'https://jsonip.com/'
try:
text, status_code = open_url_using_proxy(check_ip_url, proxy)
except:
return
print('有效代理IP: ' + proxy)
with open('valid_proxy_ip.txt','a') as f:
f.writelines(proxy)
try:
source_ip = json.loads(text).get('ip')
print(f'源IP地址为:{source_ip}')
print('='*40)
except:
print('返回的非json,无法解析')
print(text)
else:
print('无效代理IP: ' + proxy)
if __name__ == '__main__':
proxy_url = 'https://www.xicidaili.com/'
proxy_ip_filename = 'proxy_ip.txt'
# text = open_proxy_url(proxy_url)
# with open(proxy_ip_filename, 'w') as f:
# f.write(text)
text = open(proxy_ip_filename, 'r').read()
proxy_ip_list = get_proxy_ip(text)
proxy_ip_list.insert(0, 'http://172.16.160.1:3128') #我自己的代理服务器
for proxy in proxy_ip_list:
check_proxy_avaliability(proxy)
结果如下:
关于http和https代理
proxies中有两个键值对:{‘http’: ‘http://IP:port‘,‘https’:'https://IP:port‘}
其中 HTTP 只代理 HTTP 网站
例如:验证的网站是https://jsonip.com, 是HTTPS网站
所以探测到的有效代理中,如果是https代理,则返回的是代理地址,若是http代理,将使用本机IP进行访问,返回的是公网IP地址。