欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

记一次基于Cloudflare服务的爬虫

程序员文章站 2022-05-23 19:14:31
前言 前几天有个朋友托我帮忙爬一个网站,第一次打开那个网站时,我去,它竟然就要验证码,不过当时是想加几个header应该就能解决,不过事实证明我还是错了。接下来将记录下爬虫中遇到的一些坑以及解决办法。 开始 相关 目标网站: "AVADA – Avada Commerce" 使用了Cloudflar ......

前言

前几天有个朋友托我帮忙爬一个网站,第一次打开那个网站时,我去,它竟然就要验证码,不过当时是想加几个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)