常见爬虫技术

875次阅读
没有评论

常见爬虫技术

1.降低请求频率

对于Scrapy框架来说,在配置文件settings.py中设置DOWNLOAD_DELAY即可。以下代码设置下载延迟时间为3秒,即两次请求间隔3秒。

DOWNLOAD_DELAY = 3

为了防止请求过于规律,可以使用RANDOMIZE_DOWNLOAD_DELAY设置一个介于0.5 *DOWNLOAD_DELAY和1.5 *DOWNLOAD_DELAY之间的随机延迟时间。

RANDOMIZE_DOWNLOAD_DELAY = True

2. 修改请求头

网站可能会对HTTP请求头的每个属性做检查。HTTP定义了十多个请求头类型,不过大多数都不常用,只有几个字段被大多数浏览器用来初始化所有的网络请求,如下表所示。其中最重要的参数是User-Agent,我们使用它来伪装成浏览器。如果你正在处理一个警觉性非常高的网站,就要注意那些经常用却很少检查的请求头,如Accept-Language属性。
常见爬虫技术

3. 禁用Cookie

有些网站会通过Cookie来发现爬虫的轨迹。因此,如果不是特殊需要,可以禁用Cookie,这样网站就无法通过Cookie来侦测到爬虫了。Scrapy中禁止Cookie功能也非常简单,在配置文件settings.py中做如下设置:

COOKIES_ENABLED = False

4. 伪装成随机浏览器

我们都是通过User-Agent将爬虫伪装成固定浏览器,但是对于警觉性高的网站,会侦测到这一反常现象,即持续访问网站的是同一种浏览器。因此,每次请求时,可以随机伪装成不同类型的浏览器。Scrapy中的中间件UserAgentMiddleware就是专门用于设置User-Agent的,在爬虫运行时,会自动将User-Agent添加到HTTP请求中,并且可以设置多个浏览器,请求时可以随机添加不同的浏览器。要实现此功能,只需要完成以下3步:

1)设定浏览器列表

MY_USER_AGENT = [ "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; AcooBrowser; .NET CLR 1.1.4322; .NET CLR 2.0.50727)", "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Acoo Browser; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.0.04506)", "Mozilla/4.0 (compatible; MSIE 7.0; AOL 9.5; AOLBuild 4337.35; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)", "Mozilla/5.0 (Windows; U; MSIE 9.0; Windows NT 9.0; en-US)", "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 2.0.50727; Media Center PC 6.0)", "Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 1.0.3705; .NET CLR 1.1.4322)", "Mozilla/4.0 (compatible; MSIE 7.0b; Windows NT 5.2; .NET CLR 1.1.4322; .NET CLR 2.0.50727; InfoPath.2; .NET CLR 3.0.04506.30)", "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN) AppleWebKit/523.15 (KHTML, like Gecko, Safari/419.3) Arora/0.3 (Change: 287 c9dfb30)", "Mozilla/5.0 (X11; U; Linux; en-US) AppleWebKit/527+ (KHTML, like Gecko, Safari/419.3) Arora/0.6", "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.2pre) Gecko/20070215 K-Ninja/2.1.1", "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9) Gecko/20080705 Firefox/3.0 Kapiko/3.0", "Mozilla/5.0 (X11; Linux i686; U;) Gecko/20070322 Kazehakase/0.4.5", "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.8) Gecko Fedora/1.9.0.8-1.fc10 Kazehakase/0.5.6", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) AppleWebKit/535.20 (KHTML, like Gecko) Chrome/19.0.1036.7 Safari/535.20", "Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; fr) Presto/2.9.168 Version/11.52", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.11 TaoBrowser/2.0 Safari/536.11", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.71 Safari/537.1 LBBROWSER", "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; LBBROWSER)", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; QQDownload 732; .NET4.0C; .NET4.0E; LBBROWSER)", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.84 Safari/535.11 LBBROWSER", "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)", "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; QQBrowser/7.0.3698.400)", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; QQDownload 732; .NET4.0C; .NET4.0E)", "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; SV1; QQDownload 732; .NET4.0C; .NET4.0E; 360SE)", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; QQDownload 732; .NET4.0C; .NET4.0E)", "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)", "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.89 Safari/537.1", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.89 Safari/537.1", "Mozilla/5.0 (iPad; U; CPU OS 4_2_1 like Mac OS X; zh-cn) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8C148 Safari/6533.18.5", "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:2.0b13pre) Gecko/20110307 Firefox/4.0b13pre", "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:16.0) Gecko/20100101 Firefox/16.0", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11", "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 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36", ]

将settings.py中设置固定浏览器代码删除或注释掉,添加上面内容。

2)在中间件UserAgentMiddleware中从浏览器列表中随机获取一个浏览器

在middlewares.py中定义基于UserAgentMiddleware的类,实现对User-Agent的随机设置,代码如下:

#导入UserAgentMiddleware组件模块 from scrapy.downloadermiddlewares.useragent import UserAgentMiddleware import random#导入随机模块 from xx.settings import MY_USER_AGENT#导入浏览器列表 #定义类xxUserAgentMiddleware,用于设置随机设置user-agent #继承于UserAgentMiddleware class xxUserAgentMiddleware(UserAgentMiddleware): #处理Request请求函数 def process_request(self, request, spider): #使用random模块的choice函数从列表MY_USER_AGENT中随机获取一个浏览器类型 agent = random.choice(list(MY_USER_AGENT)) print("user-agent:",agent) #将User-Agent附加到Reqeust对象的headers中 request.headers.setdefault('User-Agent', agent)

3)启用中间件UserAgentMiddleware。

在settings.py中,启用中间件xxtUserAgentMiddleware。

更简单的办法: 使用fake_useragent库实现浏览器的随机获取

# 导入UserAgentMiddleware组件模块 from scrapy.downloadermiddlewares.useragent import UserAgentMiddleware # 导入fake-useragent库 from fake_useragent import UserAgent

# 定义类xxUserAgentMiddleware,用于设置随机设置user-agent class xxUserAgentMiddleware(UserAgentMiddleware): #处理Request请求函数 def process_request(self, request, spider): # 生成UserAgent对象 ua = UserAgent() # 随机获取User-Agent request.headers['User-Agent'] = ua.random print(request.headers['User-Agent'])#打印

5.更换IP地址

有的网站会设置一个IP访问频率的阈值,一旦IP访问频率超过这个阈值,就会被认定为机器人程序,进而封杀IP,禁止访问网站的任何信息。一个很简单的方法就是设置延时,但这显然会降低爬虫的效率,而IP地址又无法伪造。这时,就只能使用HTTP代理服务器了。

HTTP代理服务器(HTTP Proxy Server)其功能就是代理网络用户去取得网络信息,它是客户端浏览器和网站服务器之间的信息中转站。

可以通过以下几种方式获取代理服务器:

  • 自行搭建代理服务器
    可以购买阿里云或者腾讯云服务器,自行搭建代理服务器。这种方式的优点是可靠、稳定;缺点是资金、时间和技术成本都比较高。

  • 使用免费代理服务器
    网络上有许多免费的代理服务器供大家使用,搜索“代理”就能找到不少代理服务平台,这些平台一般都会提供免费代理服务器信息。这种方式的优点是免费、省心、省力;缺点是代理服务器有效期短、不稳定、不可控。

  • 购买付费代理服务器
    付费代理服务平衡了上述两种方案,即在花费较少资金的情况下,提供可靠、稳定、时效较长的代理服务器。以下为部分免费和付费代理服务平台:

    • ipipgo代理:提供免费代理,不提供付费代理服务

    • ipipgo代理:提供免费代理和付费代理服务

    • ipipgo:只提供付费代理服务。

Scrapy设置代理服务器非常简单,只需在Request请求中将代理服务器的URL赋给meta参数的键proxy。

Request(url,meta={"proxy": 'http://119.101.117.163:99999', "download_timeout": 10})

通过爬虫,将ipipgo代理中的高匿代理服务器的URL爬取下来,经过验证后,将有效的URL持久化到Redis数据库中,提供给后续的爬虫项目使用,主要代码如下:

  • 创建Scrapy项目
  • scrapy startproject xici_proxy

  • 使用Item封装数据
  • class XiciItem(scrapy.Item): url = scrapy.Field()#url cryptonym = scrapy.Field()#是否高匿名

  • 创建Spider文件及Spider类
  • from scrapy import Request from scrapy.spiders import Spider from xx.items import XiciItem from twisted.internet.error import DNSLookupError,TimeoutError, TCPTimedOutError#导入错误模块

    class XiciSpider(Spider): name = 'xici' current_page = 1 # 当前页 def __init__(self,url): self.test_url = url # 从命令中获取测试网站的url

    #获取初始Request def start_requests(self): # 西祠代理免费代理的url地址 url = "https://www.shenlongip.com/nn" yield Request(url) # 数据解析 def parse(self, response): list_selector = response.xpath("//tr[@class='odd']") # 依次读取每条代理的信息,从中获取ip、端口、类型 for one_selector in list_selector: item = XiciItem() # 获取ip ip = one_selector.xpath("td[2]/text()").extract()[0] # 获取端口 port = one_selector.xpath("td[3]/text()").extract()[0] # 获取是否高匿 cryptonym = one_selector.xpath("td[5]/text()").extract()[0] # 获取类型(http或https) http = one_selector.xpath("td[6]/text()").extract()[0] # 拼接成完整的代理url url = "{}://{}:{}".format(http,ip,port) item["url"] = url # 一定要设置dont_filter=True不过滤重复请求 yield Request(self.test_url,#测试网站的url callback=self.test_parse,#回调函数 errback=self.error_back,#出错回调函数 meta={"proxy":url,#代理服务器地址 "dont_retry":True,#请求不重试 "download_timeout":10,#超时时间 "item":item}, dont_filter=True#不过滤重复请求 ) if self.current_page <= 5:#爬取5页代理信息 #获取下一页url next_url = response.xpath("//a[@class='next_page']/@href").extract()[0] next_url = response.urljoin(next_url) self.current_page+=1 yield Request(next_url)

    # 测试网站的数据解析 def test_parse(self, response): yield response.meta["item"] #请求失败的回调函数 def error_back(self,failure): #打印错误日志信息 self.logger.error(repr(failure)) #细化出错原因 if failure.check(DNSLookupError):# DNS出错 # 获取request request = failure.request #输出错误日志信息 self.logger.error('DNSLookupError on %s', request.url) elif failure.check(TimeoutError, TCPTimedOutError):#超时出错 # 获取request request = failure.request #输出错误日志信息 self.logger.error('TimeoutError on %s', request.url)

  • 使用Pipeline实现数据持久化
  • import redis class XiciProxyPipeline(object): # Spider开启时,获取数据库配置信息,连接redis数据库服务器 def open_spider(self, spider): if spider.name == "xici": # 获取配置文件中redis配置信息 host = spider.settings.get("REDIS_HOST") # 主机地址 port = spider.settings.get("REDIS_PORT",) # 端口 db_index = spider.settings.get("REDIS_DB_INDEX") # 索引 db_psd = spider.settings.get("REDIS_PASSWORD") # 密码 # 连接redis,得到一个连接对象 self.db_conn = redis.StrictRedis(host=host, port=port, db=db_index, password=db_psd, decode_responses=True) self.db_conn.delete("ip")

    # 将数据存储于redis数据库 def process_item(self, item, spider): if spider.name == "xici": # 将item转换为字典类型 item_dict = dict(item) # 将item_dict保存于key为ip的集合中 self.db_conn.sadd("ip", item_dict["url"]) return item

  • settings.py中配置项
  • # 1 设置robots协议:ROBOTSTXT_OBEY(False为不遵守协议 ROBOTSTXT_OBEY = False # 2 设置用户代理:USER_AGENT USER_AGENT = "Mozilla/5.0 (Windows NT 10.0;Win64; x64) " \ "AppleWebKit/537.36 (KHTML, like Gecko) " \ "Chrome/68.0.3440.106 Safari/537.36" # 3 启用管道:XiciProxyPipeline ITEM_PIPELINES = { 'xici_proxy.pipelines.XiciProxyPipeline': 300, }

    # 4 设置Redis数据库地址、端口、索引及密码信息 REDIS_HOST = "localhost" # 主机地址 REDIS_PORT = 6379 # 端口 REDIS_DB_INDEX = 0 # 索引 REDIS_PASSWORD = "" # 密码

    实现随机代理

    将免费可用的代理服务器信息保存到Redis数据库后,所有的Scrapy爬虫项目就可以使用它们了。需要注意的是,一个爬虫项目的所有请求不能委托给固定的一个代理服务器,因为目标网站依然会监测到同一IP频繁访问的异常现象。比较好的做法是每次请求时,随机指定一个代理服务器,将请求分散到多个代理服务器中。

    proxy = self.db_conn.srandmember("ip") # 随机获取一个代理url print("随机代理URL:", proxy) # 根据URL生成Request,使用yield返回给引擎 yield Request(next_url,#目标URL callback=self.qidian_parse, # 回调函数 errback=self.error_back, # 异常时调用的函数 meta={"proxy": proxy, # 代理服务器URL "download_timeout": 10 # 超时时间 } )

    阅读资料

    神龙|纯净稳定代理IP免费测试>>>>>>>>天启|企业级代理IP免费测试>>>>>>>>IPIPGO|全球住宅代理IP免费测试

    相关文章:

    版权声明:Python教程2022-10-24发表,共计10022字。
    新手QQ群:570568346,欢迎进群讨论 Python51学习