前言

前几天有个朋友托我帮忙爬一个网站,第一次打开那个网站时,我去,它竟然就要验证码,不过当时是想加几个header应该就能解决,不过事实证明我还是错了。接下来将记录下爬虫中遇到的一些坑以及解决办法。

开始

相关

目标网站:AVADA – Avada Commerce

使用了Cloudflare的cdn服务,而且Cloudflare又和百度有合作,所以我们的访问异常时,就会被百度的云加速服务给拦截下来。

乱码问题

本来是准备用比较拿手的java写此次爬虫,java请求返回的内容总是出现一些乱码的问题。已经设置为utf-8方式并且像gzip、br等解压缩都尝试了,稍微好点的情况只有body标签内的内容为乱码,糟糕的情况就是整个返回的内容皆为乱码。后来就用python试了试,乱码问题直接没了,有点迷!

验证码问题

之前用python解决乱码问题后,紧接着又出现的就是访问需要验证码了。当时我是浏览器里访问不需要验证码,但python访问不管如何,一直出现百度云加速的验证码认证。出现这种情况,我的第一反应是python中是不是少了某些关键头部,于是将浏览器中的header带到python中一 一去试,但并没有起到啥作用。这里我就贼纳闷了,究竟为甚吗???后来才突然想起来我浏览器走了代理,于是我干脆给电脑设置了个全局代理,然后用python继续访问,让人感动的一幕发生了-----> 命令行中返回了目标网站的页面源代码!这时我才察觉,我的本地IP已经进入了目标网站的黑名单 。到这里,验证码也就绕过了。

JS导致页面url发生重定向

在把前面的目标网站的页面下载到本地后,然后用浏览器打开该文件,浏览器会加载页面中的一些图片css还有js等资源文件,其中有个js会检测当前页面url中的协议是否是https,如果不是,将重定向至对应的https协议的页面。这里显然,我们打开的本地文件url是文件的目录,不是以https开始的。

比如火狐浏览器中打开目标文件,地址栏的url如下

file:///C:/Users/Asche/vscode/Shopify/temp/Customers/How%20to%20add%20or%20edit%20a%20customer%E2%80%99s%20address.html

被重定向后的url如下

https://c/Users/Asche/vscode/Shopify/temp/Customers/How%20to%20add%20or%20edit%20a%20customer%E2%80%99s%20address.html

显然,重定向后的页面是不存在的。当然,我们也可以在页面重定向前手动取消重定向的请求,不过这样毕竟体验不好,所以继续想办法解决重定向问题。

于是,准备寻找起重定向作用的·js代码,浏览一番渲染后的页面源代码,发现在body标签结束前,多了这样一段代码:

<script type="text/javascript" id="">"https:"!=location.protocol&&(location.href="https:"+window.location.href.substring(window.location.protocol.length));</script>

而且这段代码在最初的页面内是没有的,说明是被别的js动态加载进来的。所以我就选择其中的一段代码‘location.protocol‘,在其余几个可疑的js文件内搜索,遗憾的是没有找到。

另外本来想使用js的debug功能,奈何一到dubug页面,浏览器就未响应!!!

最后没有办法,我就直接在目标文件上选择性的注释js引入,可疑的js文件都被注释掉了,却发现任然存在重定向!!!最后,只剩下一个google相关的js,把那个js注释掉,重定向终于消失了!那段js代码大概如下:

<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-NPVH4QZ');</script>

本来以为这段代码就像google分析那样的一些没啥影响的Google服务,结果却让人有点意外!可能是出于安全的考虑把。

到这里,重定向也解决!

主要部分Python代码

import requests
import os
from bs4 import BeautifulSoup # Author: Asche
# date: 2019年7月6日
print('Shopify start...') BASE_URL = 'https://avada.io'
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36',
'Cookie': '__cfduid=db73a1a3b63a54e86f435f615f5ec37791562300679; _ga=GA1.2.1048718546.1562300686; _gid=GA1.2.312498482.1562300686',
'Accept': '*/*', 'Accept-Encoding': 'gzip', 'Accept-Language': 'en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7,mt;q=0.6'} def getHtml(url):
req = requests.get(url, headers=headers)
return req.text def saveFile(name, dir, content):
folder = os.path.exists(dir)
if not folder:
os.mkdir(dir)
with open( dir + '/' + name.replace('/', '_') + '.html', 'w', encoding='utf-8') as f:
f.write(content) def crawlSubpage(url, dir):
subPage = requests.get(url, headers=headers)
# print(strHome.headers) soup = BeautifulSoup(subPage.content, 'lxml')
print(soup.title) titles = soup.select('div.collection a')
for title in titles:
print(title.text, title['href'])
saveFile(title.text, dir, getHtml(title['href'])) strHome = requests.get(BASE_URL, headers=headers)
# print(strHome.text)
print(strHome.headers) soup = BeautifulSoup(strHome.content, 'lxml')
# print(soup.prettify)
print(soup.title) titles = soup.select('h3.header a')
for title in titles:
print(title.text, title['href'])
crawlSubpage(title['href'], title.text)

记一次基于Cloudflare服务的爬虫的更多相关文章

  1. 微服务架构:基于微服务和Docker容器技术的PaaS云平台架构设计(微服务架构实施原理)

    版权声明:本文为博主原创文章,转载请注明出处,欢迎交流学习! 基于微服务架构和Docker容器技术的PaaS云平台建设目标是给我们的开发人员提供一套服务快速开发.部署.运维管理.持续开发持续集成的流程 ...

  2. 【ShoppingWebCrawler】-基于Webkit内核的爬虫蜘蛛引擎概述

    写在开头 在各个电商平台发展日渐成熟的今天.很多时候,我们需要一些平台上的基础数据.比如:商品分类,分类下的商品详细,甚至业务订单数据.电商平台大多数提供了相应的业务接口.允许ISV接入,用来扩展自身 ...

  3. 【java爬虫】---爬虫+基于接口的网络爬虫

    爬虫+基于接口的网络爬虫 上一篇讲了[java爬虫]---爬虫+jsoup轻松爬博客,该方式有个很大的局限性,就是你通过jsoup爬虫只适合爬静态网页,所以只能爬当前页面的所有新闻.如果需要爬一个网站 ...

  4. 基于微服务的DevOps落地指南 交付效率提升40%

    基于微服务的DevOps落地指南 交付效率提升40% 2015-2016年,珍爱线下门店已新增覆盖城市9个,与此同时,CRM系统大小故障却发生了数十起... ... 珍爱网是以“网络征选+人工红娘”模 ...

  5. python 全栈开发,Day140(RabbitMQ,基于scrapy-redis实现分布式爬虫)

    一.RabbitMQ 队列 在生产者消费模型中,比如去餐馆吃饭的例子.生产者相当于厨师,队列相当于服务员,消费者就是你. 我们必须通过服务员,才能吃饭! 如果队列满了,队列会一直hold住.必须让消费 ...

  6. Windows下基于IIS服务的SSL服务器的配置

    Windows下基于IIS服务的SSL服务器的配置 实验环境 Windows Server 2008 R1(CA) Windows Server 2008 R2(web服务器) Windows 7 x ...

  7. 基于Rest服务实现的RPC

    前言:现在RPC成熟的框架已经很多了,比喻Motan和Dubbo,但是今天我这里提供一种基于Rest服务的Rpc.和上一篇连着的http://www.cnblogs.com/LipeiNet/p/58 ...

  8. 基于RMI服务传输大文件的完整解决方案

    基于RMI服务传输大文件,分为上传和下载两种操作,需要注意的技术点主要有三方面,第一,RMI服务中传输的数据必须是可序列化的.第二,在传输大文件的过程中应该有进度提醒机制,对于大文件传输来说,这点很重 ...

  9. Glue4Net简单部署基于win服务的Socket程序

    smark 专注于高并发网络和大型网站架规划设计,提供.NET平台下高吞吐的网络通讯应用技术咨询和支持 Glue4Net简单部署基于win服务的Socket程序 在写一些服务应用的时候经常把要它部署到 ...

随机推荐

  1. top(k,n)—db kernel队解题思路

    0. 比赛 公司里的第三届XX中间件性能挑战赛 我和另外两个P5组队参加,队名为"db kernel".最后获得了第八,应该是P5里的最高排名. 以下简单扼要地介绍一下题目,以及我 ...

  2. DevOps技术路线图

    来自roadmap.sh github地址 自己整理的百度脑图中文版

  3. 读BeautifulSoup官方文档之与bs有关的对象和属性(2)

    上一节说到tag, 这里接着讲, tag有个属性叫做string, tag.string其实就是我们要掌握的四个对象中的第二个 ---- NavigableString,  它代表的是该tag内的te ...

  4. .NET CORE EnvironmentVariable

    .NET CORE System variables SETIn System variablese.g1:Variable name: ASPNETCORE_ENVIRONMENTVariable ...

  5. 起调UWP的几种方法

    原文:起调UWP的几种方法 由于种种原因吧,我需要使用一个WPF程序起调一个UWP程序,下面总结一下,给自己个备份. 启动UWP程序的关键是协议启动 给我们的UWP应用添加一个协议,like this ...

  6. Qt 事件处理 快捷键(重写eventFilter的函数,使用Qt::ControlModifier判断)

    CTRL+Enter发送信息的实现 在现在的即时聊天程序中,一般都设置有快捷键来实现一些常用的功能,类似QQ可以用CTRL+Enter来实现信息的发送. 在QT4中,所有的事件都继承与QEvent这个 ...

  7. 零元学Expression Blend 4 - Chapter 36 来玩捉迷藏吧!!!看看ScrollBar的Disabled与Hidden之差异

    原文:零元学Expression Blend 4 - Chapter 36 来玩捉迷藏吧!!!看看ScrollBar的Disabled与Hidden之差异 本次要针对Disabled以及Hidden作 ...

  8. missing equal sign

    "UPDATE TB_BOOKINGSET REC_LOC_CODE = ?,CUSTOMER_ADDR?WHERE BOOKING_NO=? AND TRANSPORT_MODE=? &q ...

  9. winform picturebox设置布局样式

    这里分背景图和直接显示的图片的布局 背景图的布局为BackgroundImageLayout设置为strecth即为自动拉伸 图片的布局为SizeMode 设置为StretchImage即自动拉伸

  10. 在Delphi中创建线程,请一定使用BeginThread()代替CreateThread()创建线程!(更好的管理异常)

    在Delphi中创建线程,请一定使用BeginThread()代替CreateThread()创建线程! 如果直接使用Win32的API函数CreateThread()创建多个线程,也是可以创建的.但 ...