问题描述:在爬取一些反爬机制做的比较好的网站时,经常会遇见一个问题就网站代码是通过js写的,这种就无法直接使用一般的爬虫工具爬取,这种情况一般有两种解决方案

第一种:把js代码转为html代码,然后再使用html代码解析工具爬取,目前常用的工具是selenium和scrapy-splash,我使用的是第一个工具,第二个还有搞个docker服务,太麻烦

第二种:自己观察js代码,找到存放数据的地方,直接获取,这种方式需要有js基础,反正我看到一堆乱七八糟的js就头大,这种方式pass

下面就是第一种实现方式:

技术架构:scrapy-redis + selenium + webdriver

解释:使用scrapy-redis进行分布式爬虫效率高,而且直接把url放到redis中,这种方式对于请求链接的管理非常简单, selenium这工具可以直接融入到scrapy中,作为一个中间件,至于这个中间件的原理,网上有很多资料,其实原理很简单,就是每次请求进来,先让selenium这中间件处理一下,把js代码转为html,然后直接return一个对象给spider进行爬虫,这个对象里面放的就是html,

下面就是这个中间件的代码:

  1. class SeleniumMiddleware(object):
  2.  
  3. def __init__(self,timeout=25):
  4. profile = FirefoxProfile()
  5. profile.set_preference('permissions.default.image', 2)
  6. self.browser = webdriver.Firefox(profile)
  7. self.timeout = timeout
  8. self.browser.maximize_window()
  9. # # self.browser.implicitly_wait(20)
  10. self.browser.set_page_load_timeout(self.timeout)
  11. self.wait = WebDriverWait(self.browser, self.timeout)
  12. def __del__(self):
  13. self.browser.close()
  14.  
  15. def process_request(self, request, spider):
  16. """
  17. 用WebDriver抓取页面
  18. :param request: Request对象
  19. :param spider: Spider对象
  20. :return: HtmlResponse
  21. """
  22. logging.info('******WebDriver is Starting******')
  23. try:
  24.     #这里的ip和port可以根据自己的情况填充,比如通过api获取的代理ip,或者从代理池中获取也可以
  25. ip = '60.182.17.174'
  26. port = ''
  27.     #user_agent仍然可以动态修改,这里测试写死,网上有很多每次请求随机修改代理的user-agent的方法
  28.     user_agent ='Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)'
  29. self.browser.get("about:config")
  30. script = '''
  31. var prefs = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefBranch);
  32. prefs.setIntPref("network.proxy.type", 1);
  33. prefs.setCharPref("network.proxy.http", "{ip}");
  34. prefs.setIntPref("network.proxy.http_port", "{port}");
  35. prefs.setCharPref("network.proxy.ssl", "{ip}");
  36. prefs.setIntPref("network.proxy.ssl_port", "{port}");
  37. prefs.setCharPref("network.proxy.ftp", "{ip}");
  38. prefs.setIntPref("network.proxy.ftp_port", "{port}");
  39.        prefs.setBoolPref("general.useragent.site_specific_overrides",true);
  40.        prefs.setBoolPref("general.useragent.updates.enabled",true);
  41.       prefs.setCharPref("general.useragent.override","{user_agent}");
  42. '''.format(ip = ip,port=portuser_agent=user_agent)
  43. self.browser.execute_script(script);
  44. time.sleep(1);
  45. self.browser.get(request.url)
  46. self.wait.until(EC.presence_of_element_located((By.XPATH, '//div[@class="s-result-list sg-row"]')))
  47. return HtmlResponse(url=request.url, body=self.browser.page_source, request=request, encoding='utf-8',
  48. status=200)
  49. except TimeoutException:
  50. return HtmlResponse(url=request.url, status=500, request=request)
  1.     
    -------------------------------------------------姑娘滑溜溜的马甲线------------------------------------------------------

  1.  
  2. 注意:这是网上目前可以找到的唯一个完整代码的解决方案,可以直接复制粘贴,上面都没有说重点,其实这里最重要的就是动态修改代理ip,网上很多资料都是当浏览器启动的时候指定代理ip,那如果想要更换代理ip,不好意思,重启浏览器,这种方式效率非常低,对于一个有追求的程序员来说就是种耻辱

    然后把这个中间件配置到settings中:
  1.  
  1. DOWNLOADER_MIDDLEWARES = {
  2. 'scrapy.contrib.downloadermiddleware.useragent.UserAgentMiddleware' : None, # 必需 ,禁用默认的middleware
  3. 'amazon.custom_rewrite.SeleniumMiddlewares.SeleniumMiddleware': 541, #自定义selenium中间件
  4. }
  1. -------------------------------------------------姑娘滑溜溜的马甲线------------------------------------------------------
    更新:上面只是解决了动态代理ip的问题,那如何解决动态修改浏览器头呢,很简单,只需要在上面的js中添加
  1. prefs.setBoolPref("general.useragent.site_specific_overrides",true);
  2. prefs.setBoolPref("general.useragent.updates.enabled",true);
  3. prefs.setCharPref("general.useragent.override","{user_agent}");
  1. -------------------------------------------------姑娘滑溜溜的马甲线------------------------------------------------------

2019-04-17更新:

  上面的配置在运行的过程中,浏览器一般运行几天之后就会崩溃, 我定位了很久才发现是浏览器内存泄露导致的,因为firefox浏览器默认是可以使用缓存的,随着爬虫的运行,这就会使浏览器的缓存越来越大,从而导致内存

泄露,那怎么解决呢?很简单,直接把缓存给禁用了就可以,不过有的爬虫需要用缓存加快爬虫的速度,这种情况下我还没有想到好的处理办法,一个思路是定时启动浏览器,比如定时5个小时重启一次浏览器,但是这样子有点麻烦吧,下面是禁用

缓存的代码

  1. prefs.setBoolPref("browser.cache.disk.enable", false);
  2. prefs.setBoolPref("browser.cache.memory.enable", false);
  3. prefs.setBoolPref("browser.cache.offline.enable", false);

说明:火狐浏览器从25版本之后就已经在about:config中无法找到general.useragent.override属性了,解决办法就是在about:config右键,新建-->字符串,添加这个属性就可以

scrapy-redis+selenium+webdriver解决动态代理ip和user-agent的问题(全网唯一完整代码解决方案)的更多相关文章

  1. python3 selenium模块Chrome设置代理ip的实现

    python3 selenium模块Chrome设置代理ip的实现 selenium模块Chrome设置代理ip的实现代码: from selenium import webdriver chrome ...

  2. 做了一个动态代理IP池项目,邀请大家免费测试~

    现在出来创业了,目前公司在深圳. 做了啥呢, 做了一个动态代理 IP 池项目 现在邀请大家免费测试体验! 免费激活码:关注微信公众号:2808proxy (每人每天限领一次噢~) 网站:https:/ ...

  3. scrapy怎么设置带有密码的代理ip base64.encodestring不能用 python3.5,base64库里面的encodestring()被换成了什么?

    自己写爬虫时买的代理ip有密码,在网上查了都是下面这种: 1.在Scrapy工程下新建"middlewares.py": import base64 # Start your mi ...

  4. 【音乐爬虫】Python爬虫-selenium+browsermob-proxy 解决动态网页 js渲染问题

    1.一般的python爬虫很简单,直接请求对应网址,解析返回的数据即可,但是有很多网站的数据的js动态渲染的,你直接请求是得不到对应的数据的 这时就需要其它手段来处理了. 2.以一个例子来说明,整个过 ...

  5. node.js 爬虫动态代理ip

    参考文章: https://andyliwr.github.io/2017/12/05/nodejs_spider_ip/ https://segmentfault.com/q/10100000081 ...

  6. 爬虫实战【13】获取自己的动态代理ip池

    在爬取一些比较友好的网站时,仍然有可能因为单位时间内访问次数过多,使服务器认定为机器访问,导致访问失败或者被封.如果我们使用不同的ip来访问网站的话,就可以绕过服务器的重复验证,使服务器以为使不同的人 ...

  7. selenium爬虫设置headers,代理IP等方法

    https://blog.csdn.net/xc_zhou/article/details/80823855

  8. 关于selenium添加使用代理ip

    最近在爬某个网站,发现这个网站的反爬太厉害了,正常时候的访问有时候都会给你弹出来验证,验证你是不是蜘蛛,而且requests发的请求携带了请求头信息,cookie信息,代理ip,也能识别是爬虫,他应该 ...

  9. GuozhongCrawler看准网爬虫动态切换IP漫爬虫

    有些关于URL去重的方面代码没有提供,须要自己去实现.主要这里提供思路 项目地址:http://git.oschina.net/woshidaniu/GuozhongCrawler/tree/mast ...

随机推荐

  1. Beyond Compare 命令行生成目录下所有文件比对的Html网页report

    MAC环境下,使用Beyond Compare命令行生成两个文件夹差异的html,按目录递归生成. #1. 创建compare #2. 创建compare/old #3. compare/new #4 ...

  2. 微服务之配置中心ConfigKeeper

    在微服务架构中,配置中心是必不可少的基础服务.ConfigKeeper已开源,本文将深度分析配置中心的核心内容,错过「Spring Cloud中国社区北京沙龙-2018.10.28 」的同学将从本篇文 ...

  3. (Les16 执行数据库恢复)-重做日志文件恢复

    丢失重做日志文件         丢失了重做日志文件组中的某个成员,并且组中至少还有一个成员:             -不会影响实例的正常操作.             -预警日志中会收到一条信息, ...

  4. js中的冒泡排序

    <!-- 冒泡排序:把一组数列按照一定的顺序进行排列,从大到小,或者从小到大 -->          // 控制循环的轮数          arr = [3,14,55,2,1,4,5 ...

  5. 个人对js闭包的心得见解

    谈起闭包很多人都会挠头.我以前也是,因此我查阅了很多资料,综合分析和理解,自认现在已经识得了闭包的真面目.下面我就从闭包的产生条件,闭包的作用,闭包的实质,闭包的本质,闭包产生的时机,闭包的应用 等几 ...

  6. MySQL----navicat for mysql(破解版)可视化数据库操作

    本博文介绍破解版navicat for mysql的安装方法及常用操作 navicat for mysql是一个专业的MySQL数据库图形化界面工具. 百度云下载地址:https://pan.baid ...

  7. 结对编程总结by黄柏欣李斌

    在十一国庆期间(当然,还有国庆之前的几天),我们进行了一个结对编程的项目.对我受益良多,在伙伴面前发现自己的渺小,在知识面前,始终输给这浩瀚的海洋,及时发现了自己的不足,这次项目,对我来说就相当于一个 ...

  8. 大专生自学php到找到工作的前前后后

    先做个自我介绍,我13年考上一所很烂专科民办的学校,学的是生物专业,具体的学校名称我就不说出来献丑了.13年我就辍学了,我在那样的学校,一年学费要1万多,但是根本没有人学习,我实在看不到希望,我就退学 ...

  9. mkdir 的详细使用说明

    mkdir 是make directory [dɪˈrɛktəri, daɪ-]的缩写,directory--目录的意思 mkdir在linux中是指新建文件目录 例如:mkdir test3 如果要 ...

  10. 2.Hadoop集群安装进阶

    Hadoop进阶 1.配置SSH免密 (1)修改slaves文件 切换到master机器,本节操作全在master进行. 进入/usr/hadoop/etc/hadoop目录下,找到slaves文件, ...