一、前言 近期,我参与了一个需要爬取国家食品药品监督局数据的项目,但该网站存在IP屏蔽机制。因此,我需要在Scrapy框架中实现自动IP切换,才能完成任务。然而,尽管我使用了第三方库scrapy-proxys和代理API接口,但测试并不成功。 爬取药监局数据是一项不容易完成的任务。这是因为该网站采用了多种反爬虫机制,如IP屏蔽、频率限制等,以避免窃取机密数据信息。因此,在实施这项任务时,我们需要使用各种技术工具和方法来克服这些障碍。 对于大多数企业,使用爬虫程序和库工具是一项不错的选择,其中最常用的是Scrapy和Python3。这些工具具有强大的功能,可以轻松地爬取网站上的数据。但要想成功抓取药监局的数据,我们还需要实现IP自动切换的功能,以确保IP被屏蔽后,程序可以顺利地继续运行下去。 亿牛云官方给出了python3和scrapy的参考示例 python3示例 - import requests,random
- #要访问的目标页面
- target_url = "https://www.nmpa.gov.cn/"
- #代理信息
- proxy_host = "u6791.5.tn.16yun"
- proxy_port = "31111"
- proxy_user = "16EDRSSX"
- proxy_pass = "214575"
- proxy_meta = "http://%(user)s:%(pass)s@%(host)s:%(port)s" % {
- "host" : proxy_host,
- "port" : proxy_port,
- "user" : proxy_user,
- "pass" : proxy_pass,
- }
- #设置http和https访问都是用HTTP代理
- proxies = {
- "http": proxy_meta,
- "https": proxy_meta
- }
- #设置IP切换头
- tunnel = random.randint(1, 10000)
- headers = {"Proxy-Tunnel": str(tunnel)}
- try:
- #访问目标页面
- resp = requests.get(target_url, proxies=proxies, headers=headers)
- #获取状态码和网页内容
- status_code = resp.status_code
- content = resp.text
- #输出状态码和网页内容
- print(f"status_code:{status_code}\ncontent:{content}")
-
- except requests.exceptions.RequestException as e:
- print(e)
复制代码以上是python的原本使用方式,下面提供scrapy的中间件示例 在项目中新建middlewares.py文件(./项目名/middlewares.py) - import base64
- import sys
- PY3 = sys.version_info[0] >= 3
- def base64ify(bytes_or_str):
- input_bytes = bytes_or_str if PY3 else bytes_or_str.encode('utf8')
- output_bytes = base64.urlsafe_b64encode(input_bytes)
- return output_bytes.decode('ascii') if PY3 else output_bytes
- class ProxyMiddleware2(object):
- def process_request(self, request, spider):
- # 选择一个代理服务器
- proxyHost = "u6791.5.tn.16yun"
- proxyPort = "31111"
- # 设置IP地址和端口号
- request.meta['proxy'] = "http://{0}:{1}".format(proxyHost, proxyPort)
- # 设置代理用户名和密码(根据需要开启/关闭)
- # proxyUser = "16EDRSSX"
- # proxyPass = "214587"
- # request.headers['Proxy-Authorization'] = 'Basic ' + base64ify(proxyUser + ":" + proxyPass)
-
- # 设置隧道(根据需要开启/关闭)
- # tunnel = random.randint(1,10000)
- # request.headers['Proxy-Tunnel'] = str(tunnel)
- # 修改连接方式为Close,每次都切换到新的IP
- request.headers['Connection'] = "Close"
复制代码
|