反反爬的主要思路
1.尽可能的去模拟浏览器,浏览器在如何操作,代码中就如何去实现。
2.wap 和app的数据反反爬一般不厉害
通过headers字段来反爬
把headers的信息copy到程序的headers:如常见的User-Agent Content-type referer Cookie 等字段
通过User-Agent字段反爬的话,只需要给他在请求之前添加User-Agent即可,更好的方式是使用User-Agent池来解决,我们可以考虑收集一堆User-Agent的方式,或者是随机生成User-Agent
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
import random def get_ua(): first_num = random.randint(55, 62) third_num = random.randint(0, 3200) fourth_num = random.randint(0, 140) os_type = [ '(Windows NT 6.1; WOW64)', '(Windows NT 10.0; WOW64)', '(X11; Linux x86_64)', '(Macintosh; Intel Mac OS X 10_12_6)' ] chrome_version = 'Chrome/{}.0.{}.{}'.format(first_num, third_num, fourth_num) ua = ' '.join(['Mozilla/5.0', random.choice(os_type), 'AppleWebKit/537.36', '(KHTML, like Gecko)', chrome_version, 'Safari/537.36'] ) return ua
通过js来反爬
在请求目标网站的时候,我们看到的似乎就请求了一个网站,然而实际上在成功请求目标网站之前,中间可能有通过js实现的跳转,我们肉眼不可见,这个时候可以通过点击perserve log按钮实现观察页面跳转情况
在这些请求中,如果请求数量很多,一般来讲,只有那些response中带cookie字段的请求是有用的,意味着通过这个请求,对方服务器有设置cookie到本地
通过js生成了请求参数
对应的需要分析js,观察加密的实现过程。学习了selenium这个问题会变得很容易
通过js实现了数据的加密
对应的需要分析js,观察加密的实现过程,学习了selenium这个问题会变得很容易
通过验证码来反爬
通过打码平台或者是机器学习的方法识别验证码,其中打码平台廉价易用,更值得推荐,后面的课程回来学习如何使用
通过ip地址来反爬
同一个ip大量请求了对方服务器,有更大的可能性会被识别为爬虫,对应的通过购买高质量的ip的方式能够结局问题
通过账号来反爬
如果某些网站要求必须登录才能访问某些数据,那还可以检测账号的流量,可以通过注册多个账号来解决
selenium的使用
Selenium是一个Web的自动化测试工具,最初是为网站自动化测试而开发的,Selenium 可以直接运行在浏览器上,它支持所有主流的浏览器(包括PhantomJS这些无界面的浏览器),可以接收指令,让浏览器自动加载页面,获取需要的数据,甚至页面截屏
PhantomJS
是一个基于Webkit的“无界面”(headless)浏览器,它会把网站加载到内存并执行页面上的 JavaScript
下载地址:http://phantomjs.org/download.html
Chromedriver的介绍
Chromedriver 也是一个能够被selenium驱动的浏览器,但是和PhantomJS的区别在于它是有界面的
下载地址:https://npm.taobao.org/mirrors/chromedriver
selenium的入门使用
掌握如何发送请求,加载网页
掌握如何进行简单的元素定位
掌握如何从获取浏览器中的数据
加载网页: selenium通过控制浏览器,所以对应的获取的数据都是elements中的内容
from selenium import webdriver
driver = webdriver.PhantomJS(“c:…/pantomjs.exe”) # pantomjs安装的位置
driver.get("http://www.baidu.com/")
定位和操作
find_element_by_id (返回一个元素)
find_elements_by_xpath (返回一个包含元素的列表)
find_elements_by_link_text (根据连接文本获取元素列表)
find_elements_by_partial_link_text (根据连接包含的文本获取元素列表)
find_elements_by_tag_name (根据标签名获取元素列表)
find_elements_by_class_name (根据类名获取元素列表)
查看请求信息:
driver.page_source
driver.get_cookies()
driver.current_url
退出
driver.close() #退出当前页面
driver.quit() #退出浏览器
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
from selenium import webdriver driver = webdriver.Chrome(executable_path="E:/webdriver/chromedriver.exe") driver.get("https://www.douban.com/") ret1 = driver.find_element_by_id("anony-nav") print(ret1) # 输出为:<selenium.webdriver.remote.webelement.WebElement (session="ea6f94544ac3a56585b2638d352e97f3", element="0.5335773935305805-1")> ret2 = driver.find_elements_by_id("anony-nav") print(ret2) # 输出为:[<selenium.webdriver.remote.webelement.WebElement (session="ea6f94544ac3a56585b2638d352e97f3", element="0.5335773935305805-1")>] ret3 = driver.find_elements_by_xpath("//*[@id='anony-nav']/h1/a") print(len(ret3)) # 输出为:1 ret4 = driver.find_elements_by_tag_name("h1") print(len(ret4)) # 输出为:1 ret5 = driver.find_elements_by_link_text("下载豆瓣 App") print(len(ret5)) # 输出为:1 ret6 = driver.find_elements_by_partial_link_text("豆瓣") print(len(ret6)) # 输出为:24 driver.close()
selenium的高级使用
使用selenium切换switch_to_window
手动打开一个chrome界面,先手动操作一下(因为代码很难模拟)
1. 打开chrome在cmd运行如下命令
chrome.exe --remote-debugging-port=9222 --user-data-dir="C:\selenum\AutomationProfile"
2.利用第一步打开的浏览器继续操作
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
import time from selenium import webdriver from newdex_lastprice import get_last_pirce # options = webdriver.ChromeOptions() # options.add_extension( # "C:\\Users\ZXZ\AppData\Local\Google\Chrome\\User Data\Default\Extensions\\ammjpmhgckkpcamddpolhchgomcojkle\\6.2.0_0.crx") chrome_options = webdriver.ChromeOptions() chrome_options.add_experimental_option("debuggerAddress", "127.0.0.1:9222") driver = webdriver.Chrome(executable_path="E:/webdriver/chromedriver.exe", options=chrome_options) print(driver.title) main_window = driver.current_window_handle def trade(last_pirce, volume, side): print('start {}'.format(side)) buy_tag = driver.find_element_by_id('pane-first').find_element_by_class_name(side) input_tags = buy_tag.find_elements_by_class_name('place-order-info-input') price_buy_tag = input_tags[0].find_element_by_tag_name('input') volume_buy_tag = input_tags[1].find_element_by_tag_name('input') button_bug = buy_tag.find_element_by_tag_name('button') price_buy_tag.clear() volume_buy_tag.clear() price_buy_tag.send_keys(str(last_pirce)) volume_buy_tag.send_keys(str(volume)) button_bug.click() print(driver.current_window_handle) time.sleep(10) if len(driver.window_handles) > 1: sub_handle = driver.window_handles[1] # 获取所有窗口句柄 driver.switch_to_window(sub_handle) print(driver.current_window_handle) driver.find_element_by_class_name('actions').find_elements_by_tag_name('button')[1].click() print(666) if len(driver.window_handles) > 1: driver.close() time.sleep(10) driver.switch_to_window(main_window) if __name__ == '__main__': while True: last_pirce = 0.0043 # get_last_pirce() 需修改 volume = 100 # 需修改 trade(last_pirce, volume, 'buy') trade(last_pirce, volume, 'sell')
使用selenium切换frame
frame是html中常用的一种技术,即一个页面中嵌套了另一个网页,selenium默认是访问不了frame中的内容的,对应的解决思路是 driver.switch_to.frame()
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
# coding=utf-8 from selenium import webdriver import time driver = webdriver.Chrome(executable_path="E:/webdriver/chromedriver.exe") driver.get("https://mail.qq.com/") driver.switch_to.frame("login_frame") driver.find_element_by_id("u").send_keys("598779784@qq.com") driver.find_element_by_id("p").send_keys("liu1314@.qq") driver.find_element_by_id("login_button").click() driver.quit()
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
__author__ = 'hy' import time from selenium import webdriver browser = webdriver.Chrome(executable_path="E:/webdriver/chromedriver.exe") # browser.get("https://www.zhihu.com/signin") time.sleep(2) # 点击QQ # browser.find_element_by_css_selector(".qrcode-signin-cut-button").click() browser.find_element_by_css_selector(".Login-socialLogin").click() time.sleep(2) browser.find_elements_by_tag_name("g")[-1].click() time.sleep(5) browser.switch_to.window(browser.window_handles[-1]) browser.switch_to.frame("ptlogin_iframe") # iframe必须逐级切入 # 用户名 密码 # 隐藏初始界面 browser.execute_script('document.getElementById("qlogin").style="display: none;"') browser.execute_script('document.getElementsByClassName("authLogin").style="display: none;"') # 显示用户、密码输入界面 browser.execute_script('document.getElementById("web_qr_login").style="display: block;"') # browser.evaluate_script('document.getElementById("batch_quto").contentEditable = true') time.sleep(5) # 输入用户、密码 elem_user = browser.find_element_by_name("u").send_keys("598779784") elem_pwd = browser.find_element_by_name("p").send_keys("598779784@qq.com") elem_but = browser.find_element_by_id("login_button").click() time.sleep(5)
QQ登录到第三方平台详解 https://github.com/ecithy/selenium-QQ
打码平台的使用
1.为什么需要了解打码平台的使用
现在很多网站都会使用验证码来进行反爬,所以为了能够更好的获取数据,需要了解如何使用打码平台爬虫中的验证码.
2.见的打码平台
云打码:http://www.yundama.com/
能够解决通用的验证码识别
极验验证码智能识别辅助:http://jiyandoc.c2567.com/
能够解决复杂验证码的识别
云打码的使用
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
import os import time import random from selenium import webdriver from PIL import Image import requests from bs4 import BeautifulSoup from scripts.helper import YDMHelper def set_header(): '设置header' agent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:51.0) Gecko/20100101 Firefox/51.0" header = { "HOST": "testnet-faucet.mempool.co", "Origin": "testnet-faucet.mempool.co", "Referer": "https://testnet-faucet.mempool.co", 'User-Agent': agent } return header def get_token(url): resp = requests.get(url, url, headers=set_header()) s1 = BeautifulSoup(resp.text, 'html.parser') token = s1.find(name='input', attrs={'name': 'tauth'}).get('value') return token def get_image_url(): r1 = requests.get(url, headers=set_header()) s1 = BeautifulSoup(r1.text, 'html.parser') image_url = s1.find(name='form').find(name='img').get('src') return image_url def pre_handle(filename): current_files = os.listdir() if filename in current_files: os.remove(filename) if __name__ == '__main__': # 参数设置 taddress_list = ['2NBMEXTKGxz5jyYGSPUXMrG3HxFap2PQK7i', '2NBMEXcuArNqkPJXV9ENuXjHSPtQcfm7mTA', '2NBMEXLFktCYC5jWnBibky6CLUGWowVddqt'] interval_list = [300, 500] taddress = random.choice(taddress_list) filename = 'code.png' url = 'https://testnet-faucet.mempool.co/' while True: try: driver = webdriver.Chrome(executable_path="E:/webdriver/chromedriver.exe") driver.maximize_window() # 删除上次的验证码文件 pre_handle(filename) # 得到图片验证码 image_url = url # get_image_url() driver.get(image_url) element = driver.find_element_by_css_selector(".center").find_element_by_tag_name('img') # driver.save_screenshot(filename) left = element.location['x'] + 30 top = element.location['y'] + 80 # right = element.location['x'] + element.size['width'] # bottom = element.location['y'] + element.size['height'] # left = 178 # top = 488 right = left + element.size['width'] + 30 bottom = top + element.size['height'] + 10 im = Image.open(filename) im = im.crop((left, top, right, bottom)) # x0, y0, x1, y1 im.save(filename) time.sleep(2) # 保存完再关闭 captcha = YDMHelper.get_code(filename) if len(captcha) > 2: first_char, second_char, third_char = captcha[0], captcha[1], captcha[2] if first_char.isdigit() and third_char.isdigit(): print('再次运算') if second_char.lower() == 'x': captcha = int(first_char) * int(third_char) print('乘法结果: {}'.format(captcha)) if second_char.lower() == '+' or second_char.lower() == 't': captcha = int(first_char) + int(third_char) print('加法结果: {}'.format(captcha)) else: driver.close() time.sleep(interval_list[1]) continue driver.find_element_by_name("captcha").send_keys(captcha) driver.find_element_by_id('taddress').send_keys(taddress) driver.find_element_by_id('amount').send_keys('0.01') time.sleep(3) driver.find_elements_by_tag_name('input')[3].click() time.sleep(interval_list[1]) driver.close() except Exception as e: print(e)
4.常见的验证码的种类 4.1 url地址不变,验证码不变 这是验证码里面非常简单的一种类型,对应的只需要获取验证码的地址,然后请求,通过打码平台识别即可 4.2 url地址不变,验证码变化 这种验证码的类型是更加常见的一种类型,对于这种验证码,大家需要思考: 在登录的过程中,假设我输入的验证码是对的,对方服务器是如何判断当前我输入的验证码是显示在我屏幕上的验证码,而不是其他的验证码呢? 在获取网页的时候,请求验证码,以及提交验证码的时候,对方服务器肯定通过了某种手段验证我之前获取的验证码和最后提交的验证码是同一个验证码,那这个手段是什么手段呢? 很明显,就是通过cookie来实现的,所以对应的,在请求页面,请求验证码,提交验证码的到时候需要保证cookie的一致性,对此可以使用requests.session来解决