反反爬虫利器!教你怎么用代理,拨号换IP……

我是创始人李岩:很抱歉!给自己产品做个广告,点击进来看看。  

反反爬虫利器!教你怎么用代理,拨号换IP……

作者:蚍蜉撼大树

0x01 前言

一般而言,抓取稍微正规一点的网站,都会有反爬虫的制约。反爬虫主要有以下几种方式:

  1. 通过UA判断。这是最低级的判断,一般反爬虫不会用这个做唯一判断,因为反反爬虫非常容易,直接随机UA即可解决。
  2. 通过单IP频繁访问判断。这个判断简单,而且反反爬虫比较费力,反爬虫绝佳方案。需采用多IP抓取。
  3. 通过Cookie判断,例如通过会员制账号密码登陆,判断单账号短时间抓取次数判断。这个反反爬虫也很费力。需采用多账号抓取。
  4. 动态页面加载。这个考验前端工程师的功底,如果前端写的好,各种JS判断,各种逻辑,像百度淘宝一样,post登录很难。较好的方法,但是对于大牛,还是防不胜防。反反爬虫多采用渲染浏览器抓取,效率低下。
  5. 采用验证码。这里要么是登录的时候有验证码,要么是判断是爬虫时,不封IP,而是采用验证码验证,例如链家网。验证码是反爬虫性价比较高的方案。反反爬虫一般接入OCR验证码识别平台或者人工打码平台,亦或者利用Tesseract OCR识别,亦或者采用神经网络训练识别验证码等。

0x02 概要

今天我们先主要来讲一讲,如何应对第2条的反反爬虫,如何通过多IP抓取。

通过多IP爬虫,又分为以下几种形式:

  1. 通过ADSL拨号换IP。每拨一次就会有一个新IP,较好解决IP单一问题。
  2. 如果是局域网,带路由器的,第一种方法可能不好用。这个时候可以模拟登陆路由器,控制路由器重新拨号,换IP,这其实是一种折中的办法,曲线救国。
  3. 代理IP,利用购买的或者网上抓取的免费代理IP,实现多IP爬虫。
  4. 分布式爬虫。采用多个服务器,多个IP,多个slave爬虫同时运行,由master负责调度。效率较高,属于大型分布式抓取,一般用redis分布式抓取,不表。
  5. 最近了解到一种新的加密的代理网络。Tor匿名网络,利用这个也能匿名换IP。这个还没有详细了解,不表。

0x03 正文

1. ADSL拨号

我一般是在windows平台ADSL拨号,其他平台暂时没用过。windows平台拨号,我一般用python的代码为:

					
						# -*- coding: utf-8 -*-
						import
						os
						g_adsl_account
						=
						{
						"name"
						:
						u"宽带连接"
						,
						"username"
						:
						"xxxx"
						,
						"password"
						:
						"xxxx"
						}
						class
						Adsl
						(
						object
						):
						# =============================
						# __init__ : name: adsl名称
						# =============================
						def
						__init__
						(
						self
						):
						self
						.
						name
						=
						g_adsl_account
						[
						"name"
						]
						self
						.
						username
						=
						g_adsl_account
						[
						"username"
						]
						self
						.
						password
						=
						g_adsl_account
						[
						"password"
						]
						# =============================
						# set_adsl : 修改adsl设置
						# =============================
						def
						set_adsl
						(
						self
						,
						account
						):
						self
						.
						name
						=
						account
						[
						"name"
						]
						self
						.
						username
						=
						account
						[
						"username"
						]
						self
						.
						password
						=
						account
						[
						"password"
						]
						# =============================
						# connect : 宽带拨号
						# =============================
						def
						connect
						(
						self
						):
						cmd_str
						=
						"rasdial
						%s
						%s
						%s
						"
						%
						(
						self
						.
						name
						,
						self
						.
						username
						,
						self
						.
						password
						)
						os
						.
						system
						(
						cmd_str
						)
						time
						.
						sleep
						(
						5
						)
						# =============================
						# disconnect : 断开宽带连接
						# =============================
						def
						disconnect
						(
						self
						):
						cmd_str
						=
						"rasdial
						%s
						/disconnect"
						%
						self
						.
						name
						os
						.
						system
						(
						cmd_str
						)
						time
						.
						sleep
						(
						5
						)
						#=============================
						# reconnect : 重新进行拨号
						#=============================
						def
						reconnect
						(
						self
						):
						self
						.
						disconnect
						()
						self
						.
						connect
						()
					
				

2. 路由器拨号

如果是局域网,带路由器的。直接调用windows的rasdial命令无法拨号时,这个时候可以模拟登陆路由器,控制路由器重新拨号,换IP,这其实是一种折中的办法,曲线救国。下面以登录小米路由器示例:

					
						# -*- coding: utf-8 -*-
						import
						requests
						import
						urllib
						from
						Crypto.Hash
						import
						SHA
						import
						time
						import
						json
						import
						re
						import
						random
						import
						datetime
						class
						Adsl
						():
						def
						__init__
						(
						self
						):
						self
						.
						host
						=
						'192.168.31.1/'
						self
						.
						username
						=
						'admin'
						self
						.
						password
						=
						'huangxin250'
						def
						connect
						(
						self
						):
						host
						=
						self
						.
						host
						homeRequest
						=
						requests
						.
						get
						(
						'http://'
						+
						host
						+
						'/cgi-bin/luci/web/home'
						)
						key
						=
						re
						.
						findall
						(
						r'key:
						\'
						(.*)
						\'
						,'
						,
						homeRequest
						.
						text
						)[
						0
						]
						mac
						=
						re
						.
						findall
						(
						r'deviceId =
						\'
						(.*)
						\'
						;'
						,
						homeRequest
						.
						text
						)[
						0
						]
						aimurl
						=
						"http://"
						+
						host
						+
						"/cgi-bin/luci/api/xqsystem/login"
						nonce
						=
						"0_"
						+
						mac
						+
						"_"
						+
						str
						(
						int
						(
						time
						.
						time
						()))
						+
						"_"
						+
						str
						(
						random
						.
						randint
						(
						1000
						,
						10000
						))
						pwdtext
						=
						self
						.
						password
						pwd
						=
						SHA
						.
						new
						()
						pwd
						.
						update
						(
						pwdtext
						+
						key
						)
						hexpwd1
						=
						pwd
						.
						hexdigest
						()
						pwd2
						=
						SHA
						.
						new
						()
						pwd2
						.
						update
						(
						nonce
						+
						hexpwd1
						)
						hexpwd2
						=
						pwd2
						.
						hexdigest
						()
						data
						=
						{
						"logtype"
						:
						2
						,
						"nonce"
						:
						nonce
						,
						"password"
						:
						hexpwd2
						,
						"username"
						:
						self
						.
						username
						}
						response
						=
						requests
						.
						post
						(
						url
						=
						aimurl
						,
						data
						=
						data
						,
						timeout
						=
						15
						)
						resjson
						=
						json
						.
						loads
						(
						response
						.
						content
						)
						token
						=
						resjson
						[
						'token'
						]
						webstop
						=
						urllib
						.
						urlopen
						(
						'http://192.168.31.1/cgi-bin/luci/;stok='
						+
						token
						+
						'/api/xqnetwork/pppoe_stop'
						)
						#time.sleep(1)
						webstart
						=
						urllib
						.
						urlopen
						(
						'http://192.168.31.1/cgi-bin/luci/;stok='
						+
						token
						+
						'/api/xqnetwork/pppoe_start'
						)
						date
						=
						datetime
						.
						datetime
						.
						now
						()
						nowtime
						=
						str
						(
						date
						)[:
						-
						10
						]
						print
						nowtime
						+
						', congratulations, the IP is changed !'
					
				

利用这个方法,就实现了用路由器换IP的目的。该方法的缺陷也是很明显的。就是不像第一种方法那样通用。基本上一个路由器就得编一套代码,属于定制代码。

3. 代理IP

代理IP是最常见的一种多IP爬虫方法。在请求Headers中加入代理IP地址,即可实现代理IP抓取。缺陷是爬取速度和代理IP的速度息息相关。而且好的IP费用较高,免费的速度普遍不高。

附上requests抓取携带代理IP和selenium抓取携带代理IP的代码。

requests:

					
						# -*- coding: utf-8 -*-
						import
						requests
						reload
						(
						sys
						)
						sys
						.
						setdefaultencoding
						(
						'utf-8'
						)
						type
						=
						sys
						.
						getfilesystemencoding
						()
						s
						=
						requests
						.
						session
						()
						proxie
						=
						{
						'http'
						:
						'http://122.193.14.102:80'
						}
						url
						=
						'xxx'
						response
						=
						s
						.
						get
						(
						url
						,
						verify
						=
						False
						,
						proxies
						=
						proxie
						,
						timeout
						=
						20
						)
						print
						response
						.
						text
					
				

selenium:

					
						from
						selenium
						import
						webdriver
						from
						selenium.webdriver.common.proxy
						import
						Proxy
						from
						selenium.webdriver.common.proxy
						import
						ProxyType
						proxy
						=
						Proxy
						(
						{
						'proxyType'
						:
						ProxyType
						.
						MANUAL
						,
						'httpProxy'
						:
						'ip:port'
						}
						)
						desired_capabilities
						=
						DesiredCapabilities
						.
						PHANTOMJS
						.
						copy
						()
						proxy
						.
						add_to_capabilities
						(
						desired_capabilities
						)
						driver
						=
						webdriver
						.
						PhantomJS
						(
						executable_path
						=
						"/path/of/phantomjs"
						,
						desired_capabilities
						=
						desired_capabilities
						)
						driver
						.
						get
						(
						'http://httpbin.org/ip'
						)
						print
						driver
						.
						page_source
						driver
						.
						close
						()
					
				

0x04 尾言

本节主要讲了反爬虫的一些概念,常用的方法,反反爬虫的一些方法,并且主要介绍了 多IP爬虫的实现方式 ,属于爬虫领域基础内容。掌握了这些基础内容,以后爬虫步伐才能迈得坚实。

End.

转载请注明来自36大数据(36dsj.com): 36大数据 » 反反爬虫利器!教你怎么用代理,拨号换IP……

随意打赏

提交建议
微信扫一扫,分享给好友吧。