首页 > 其他分享 >登陆京东(滑块验证),验证码识别,Scrapy框架介绍及其使用,持久化存储到本地

登陆京东(滑块验证),验证码识别,Scrapy框架介绍及其使用,持久化存储到本地

时间:2024-07-22 21:09:28浏览次数:14  
标签:novel 滑块 img self 验证码 Scrapy article div scrapy

Ⅰ 案例登陆京东(滑块验证)

【一】下载opencv库

pip install opencv-python

【二】数据准备

  • 先将京东的滑块图片下载到本地
  • 背景图background.png

  • 滑块图tag.png

【三】展示获取滑块的移动数据


import os.path

# 使用 opencv 识别图像计算滑块之间的距离
import cv2
import numpy as np


class CvImageDistance:

    def from_file_get_distanct(self, tag_img_path, background_img_path):
        '''
        根据文件进行识别
        :param tag_img_path: 滑块图片的文件路径
        :param background_img_path: 背景图片的文件路径
        :return:
        '''
        # 滑块
        target = cv2.imread(tag_img_path)
        # 读取到两个图片,进行灰值化处理
        # 背景缺口图
        template = cv2.imread(background_img_path, 0)
        # 转化到灰度
        target = cv2.cvtColor(target, cv2.COLOR_BGR2GRAY)
        # 返回绝对值
        target = abs(255 - target)
        # 单通道转3通道
        target = cv2.cvtColor(target, cv2.COLOR_GRAY2RGB)
        template = cv2.cvtColor(template, cv2.COLOR_GRAY2RGB)
        # 进行匹配
        result = cv2.matchTemplate(target, template, cv2.TM_CCOEFF_NORMED)
        # 通过np转化为数值,就是坐标
        x, y = np.unravel_index(result.argmax(), result.shape)
        return y, x

    def from_buffer_get_distanct(self, tag_img, background_img):
        '''
        根据二进制进行识别
        :param tag_img_path: 滑块图片的二进制
        :param bg: 背景图片的二进制
        :return:
        '''
        target = cv2.imdecode(np.frombuffer(tag_img, np.uint8), cv2.IMREAD_COLOR)

        # 如果是PIL.images就换读取方式
        template = cv2.imdecode(np.frombuffer(background_img, np.uint8), cv2.IMREAD_COLOR) if type(
            background_img) == bytes else cv2.cvtColor(
            np.asarray(background_img), cv2.COLOR_RGB2BGR)

        # 转化到灰度
        target = cv2.cvtColor(target, cv2.COLOR_BGR2GRAY)

        # 返回绝对值
        target = abs(255 - target)

        # 单通道转3通道
        target = cv2.cvtColor(target, cv2.COLOR_GRAY2RGB)

        # 进行匹配
        result = cv2.matchTemplate(target, template, cv2.TM_CCOEFF_NORMED)

        # 通过np转化为数值,就是坐标
        x, y = np.unravel_index(result.argmax(), result.shape)
        return y, x

    def get_distance(self, background_img_path, tag_img_path):
        # 读取到背景图片的 rgb
        background_rgb = cv2.imread(background_img_path)
        # 读取到滑块图片的 rgb
        tag_rgb = cv2.imread(tag_img_path)
        # 计算结果
        res = cv2.matchTemplate(background_rgb, tag_rgb, cv2.TM_CCOEFF_NORMED)
        # 获取最小长度
        lo = cv2.minMaxLoc(res)

        # 识别返回滑动距离
        return lo[2][0]


if __name__ == '__main__':
    tag_img_path = os.path.join(os.path.dirname(__file__), 'tag.png')
    background_img_path = os.path.join(os.path.dirname(__file__), 'background.png')
    with open(tag_img_path, 'rb') as f:
        tag_img = f.read()
    with open(background_img_path, 'rb') as f:
        background_img = f.read()
    cv_obj = CvImageDistance()

    print(cv_obj.from_buffer_get_distanct(tag_img, background_img))    # (np.int64(136), np.int64(24))
    print(cv_obj.get_distance(background_img_path, tag_img_path))   # 136
  • background.png

  • tag.png

【四】代码实现

import random
import time
import cv2
from urllib import request
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.action_chains import ActionChains
from cvImg import CvImageDistance
from selenium.webdriver.chrome.service import Service


class SpiderJd:
    def __init__(self, username, password):
        self.username = username
        self.password = password
        self.index_url = 'https://www.jd.com'
        self.cv_obj = CvImageDistance()
        self.browser = webdriver.Chrome(
            service=Service(executable_path="./chromedriver.exe")
        )

    def __sleep_time(self):
        time.sleep(random.randint(1, 3))

    def login(self):
        # 【一】访问京东官网
        self.browser.get(self.index_url)

        self.__sleep_time()

        # 【二】在页面上找到请登陆的按钮
        login_btn = self.browser.find_element(By.XPATH, '//*[@id="ttbar-login"]/a[1]')

        # 【三】点击登陆按钮跳转到登陆界面
        login_btn.click()
        self.__sleep_time()

        # 【四】获取到用户名和密码的输入框
        username_input = self.browser.find_element(By.XPATH, '//*[@id="loginname"]')
        password_input = self.browser.find_element(By.XPATH, '//*[@id="nloginpwd"]')

        # 输入用户名和密码
        username_input.send_keys(self.username)
        self.__sleep_time()
        password_input.send_keys(self.password)
        self.__sleep_time()

        # 【五】获取登陆按钮
        login_submit = self.browser.find_element(By.XPATH, '//*[@id="loginsubmit"]')

        # 【六】点击登陆按钮
        login_submit.click()
        self.__sleep_time()

        # 【七】弹出滑动验证码
        # (1)获取到当前验证码所在的标签
        # 需要移动的滑块的标签
        code_img_tag = self.browser.find_element(By.XPATH,
                                                 '//*[@id="JDJRV-wrap-loginsubmit"]/div/div/div/div[1]/div[2]/div[2]/img')
        # 滑块背景图完整的图片
        code_img_background_tag = self.browser.find_element(By.XPATH,
                                                            '//*[@id="JDJRV-wrap-loginsubmit"]/div/div/div/div[1]/div[2]/div[1]/img')
        code_btn_tag = self.browser.find_element(By.XPATH,
                                                 '//*[@id="JDJRV-wrap-loginsubmit"]/div/div/div/div[2]/div[3]')

        # (2)获取得到滑块背景图的完整图片和滑块图片
        background_img = code_img_background_tag.get_attribute("src")
        tag_img = code_img_tag.get_attribute("src")

        # (3)解析当前图片链接得到本地的图片
        request.urlretrieve(background_img, "background.png")
        request.urlretrieve(tag_img, "tag.png")
        self.__sleep_time()

        # (4)计算缺口之间的距离
        distance = self.cv_obj.get_distance(background_img_path="background.png", tag_img_path="tag.png")

        x_location = int(distance * 240 / 360)
        # 【八】准备滑块滑动
        # (1)创建滑块动作链对象
        action = ActionChains(self.browser)
        # (2)按住滑块
        action.click_and_hold(code_btn_tag)

        # (3)滑动到指定位置
        # 定义起始位置
        track = 0
        while track < x_location:
            # 每次只划一部分
            action.move_by_offset(2, 0).perform()
            # 累加
            track += 2
        self.__sleep_time()
        # (4)释放滑块
        action.release(code_btn_tag).perform()
        self.__sleep_time()


if __name__ == '__main__':
    spider = SpiderJd(
        username="15036883333",
        password="666666zczczczcz"
    )
    spider.login()

  • cvImg.py
import os.path

import cv2
import numpy as np


class CvImageDistance:

    def from_file_get_distanct(self, tag_img_path, background_img_path):
        '''
        根据文件进行识别
        :param tag_img_path: 滑块图片的文件路径
        :param background_img_path: 背景图片的文件路径
        :return:
        '''
        target = cv2.imread(tag_img_path)
        # 读取到两个图片,进行灰值化处理
        template = cv2.imread(background_img_path, 0)
        # 转化到灰度
        target = cv2.cvtColor(target, cv2.COLOR_BGR2GRAY)
        # 返回绝对值
        target = abs(255 - target)
        # 单通道转3通道
        target = cv2.cvtColor(target, cv2.COLOR_GRAY2RGB)
        template = cv2.cvtColor(template, cv2.COLOR_GRAY2RGB)
        # 进行匹配
        result = cv2.matchTemplate(target, template, cv2.TM_CCOEFF_NORMED)
        # 通过np转化为数值,就是坐标
        x, y = np.unravel_index(result.argmax(), result.shape)
        return y, x

    def from_buffer_get_distanct(self, tag_img, background_img):
        '''
        根据二进制进行识别
        :param tag_img_path: 滑块图片的二进制
        :param bg: 背景图片的二进制
        :return:
        '''
        target = cv2.imdecode(np.frombuffer(tag_img, np.uint8), cv2.IMREAD_COLOR)

        # 如果是PIL.images就换读取方式
        template = cv2.imdecode(np.frombuffer(background_img, np.uint8), cv2.IMREAD_COLOR) if type(
            background_img) == bytes else cv2.cvtColor(
            np.asarray(background_img), cv2.COLOR_RGB2BGR)

        # 转化到灰度
        target = cv2.cvtColor(target, cv2.COLOR_BGR2GRAY)

        # 返回绝对值
        target = abs(255 - target)

        # 单通道转3通道
        target = cv2.cvtColor(target, cv2.COLOR_GRAY2RGB)

        # 进行匹配
        result = cv2.matchTemplate(target, template, cv2.TM_CCOEFF_NORMED)

        # 通过np转化为数值,就是坐标
        x, y = np.unravel_index(result.argmax(), result.shape)
        return y, x

    def get_distance(self, background_img_path, tag_img_path):
        # 读取到背景图片的 rgb
        background_rgb = cv2.imread(background_img_path)
        # 读取到滑块图片的 rgb
        tag_rgb = cv2.imread(tag_img_path)
        # 计算结果
        res = cv2.matchTemplate(background_rgb, tag_rgb, cv2.TM_CCOEFF_NORMED)
        # 获取最小长度
        lo = cv2.minMaxLoc(res)

        # 识别返回滑动距离
        return lo[2][0]


if __name__ == '__main__':
    tag_img_path = os.path.join(os.path.dirname(__file__), 'tag.png')
    background_img_path = os.path.join(os.path.dirname(__file__), 'background.png')
    with open(tag_img_path, 'rb') as f:
        tag_img = f.read()
    with open(background_img_path, 'rb') as f:
        background_img = f.read()
    cv_obj = CvImageDistance()

    print(cv_obj.from_buffer_get_distanct(tag_img, background_img))
    print(cv_obj.get_distance(background_img_path, tag_img_path))

Ⅱ 验证码识别

【一】图鉴平台

【1】官网

【2】介绍

  • 比较好用的平台

【3】价格

【4】使用

import base64
import json
import requests
# 一、图片文字类型(默认 3 数英混合):
# 1 : 纯数字
# 1001:纯数字2
# 2 : 纯英文
# 1002:纯英文2
# 3 : 数英混合
# 1003:数英混合2
#  4 : 闪动GIF
# 7 : 无感学习(独家)
# 11 : 计算题
# 1005:  快速计算题
# 16 : 汉字
# 32 : 通用文字识别(证件、单据)
# 66:  问答题
# 49 :recaptcha图片识别
# 二、图片旋转角度类型:
# 29 :  旋转类型
#
# 三、图片坐标点选类型:
# 19 :  1个坐标
# 20 :  3个坐标
# 21 :  3 ~ 5个坐标
# 22 :  5 ~ 8个坐标
# 27 :  1 ~ 4个坐标
# 48 : 轨迹类型
#
# 四、缺口识别
# 18 : 缺口识别(需要2张图 一张目标图一张缺口图)
# 33 : 单缺口识别(返回X轴坐标 只需要1张图)
# 五、拼图识别
# 53:拼图识别
def base64_api(uname, pwd, img, typeid):
    with open(img, 'rb') as f:
        base64_data = base64.b64encode(f.read())
        b64 = base64_data.decode()
    data = {"username": uname, "password": pwd, "typeid": typeid, "image": b64}
    result = json.loads(requests.post("http://api.ttshitu.com/predict", json=data).text)
    if result['success']:
        return result["data"]["result"]
    else:
        #!!!!!!!注意:返回 人工不足等 错误情况 请加逻辑处理防止脚本卡死 继续重新 识别
        return result["message"]
    return ""


if __name__ == "__main__":
    img_path = "C:/Users/Administrator/Desktop/file.jpg"
    result = base64_api(uname='你的账号', pwd='你的密码', img=img_path, typeid=3)
    print(result)

【二】超级鹰

【1】官网

【2】介绍

【3】价格

【4】使用

import requests
from hashlib import md5

class Chaojiying_Client(object):

    def __init__(self, username, password, soft_id):
        self.username = username
        password = password.encode('utf8')
        self.password = md5(password).hexdigest()
        self.soft_id = soft_id
        self.base_params = {
            'user': self.username,
            'pass2': self.password,
            'softid': self.soft_id,
        }
        self.headers = {
            'Connection': 'Keep-Alive',
            'User-Agent': 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)',
        }

    def PostPic(self, im, codetype):
        """
        im: 图片字节
        codetype: 题目类型 参考 http://www.chaojiying.com/price.html
        """
        params = {
            'codetype': codetype,
        }
        params.update(self.base_params)
        files = {'userfile': ('ccc.jpg', im)}
        r = requests.post('http://upload.chaojiying.net/Upload/Processing.php', data=params, files=files,
                          headers=self.headers)
        return r.json()

    def PostPic_base64(self, base64_str, codetype):
        """
        im: 图片字节
        codetype: 题目类型 参考 http://www.chaojiying.com/price.html
        """
        params = {
            'codetype': codetype,
            'file_base64': base64_str
        }
        params.update(self.base_params)
        r = requests.post('http://upload.chaojiying.net/Upload/Processing.php', data=params, headers=self.headers)
        return r.json()

    def ReportError(self, im_id):
        """
        im_id:报错题目的图片ID
        """
        params = {
            'id': im_id,
        }
        params.update(self.base_params)
        r = requests.post('http://upload.chaojiying.net/Upload/ReportError.php', data=params, headers=self.headers)
        return r.json()


if __name__ == '__main__':
    chaojiying = Chaojiying_Client('超级鹰用户名', '超级鹰用户名的密码', '96001')  # 用户中心>>软件ID 生成一个替换 96001
    im = open('a.jpg', 'rb').read()  # 本地图片文件路径 来替换 a.jpg 有时WIN系统须要//
    print(chaojiying.PostPic(im, 1902))  # 1902 验证码类型  官方网站>>价格体系 3.4+版 print 后要加()
    # print chaojiying.PostPic(base64_str, 1902)  #此处为传入 base64代码

Ⅲ Scrapy框架介绍

【一】开源和协作的框架

  • 其最初是为了页面抓取 (更确切来说, 网络抓取 )所设计的,

  • 使用它可以以快速、简单、可扩展的方式从网站中提取所需的数据。

  • 但目前Scrapy的用途十分广泛,可用于如数据挖掘、监测和自动化测试等领域,也可以应用在获取API所返回的数据(例如 Amazon Associates Web Services ) 或者通用的网络爬虫。

  • Scrapy 是基于twisted框架开发而来,twisted是一个流行的事件驱动的python网络框架。

  • 因此Scrapy使用了一种非阻塞(又名异步)的代码来实现并发。

  • Scrapy框架类似于Django框架

【二】整体架构大致如下

【1】引擎(EGINE)

  • 引擎负责控制系统所有组件之间的数据流,并在某些动作发生时触发事件。

【2】调度器(SCHEDULER)

  • 用来接受引擎发过来的请求, 压入队列中, 并在引擎再次请求的时候返回.
  • 可以想像成一个URL的优先级队列, 由它来决定下一个要抓取的网址是什么, 同时去除重复的网址

【3】下载器(DOWLOADER)

  • 用于下载网页内容, 并将网页内容返回给EGINE,下载器是建立在twisted这个高效的异步模型上的

【4】爬虫(SPIDERS)

  • SPIDERS是开发人员自定义的类,用来解析responses,并且提取items,或者发送新的请求

【5】项目管道(ITEM PIPLINES)

  • 在items被提取后负责处理它们,主要包括清理、验证、持久化(比如存到数据库)等操作
  • 下载器中间件(Downloader Middlewares)位于Scrapy引擎和下载器之间,主要用来处理从EGINE传到DOWLOADER的请求request,已经从DOWNLOADER传到EGINE的响应response,

【6】爬虫中间件(Spider Middlewares)

  • 位于EGINE和SPIDERS之间,主要工作是处理SPIDERS的输入(即responses)和输出(即requests)

【三】官网链接

Ⅳ Scrapy框架之安装

# window系统
pip install scrapy
# macos / linux
pip install scrapy

【一】Windows平台

【1】安装wheel文件

  • 在 Windows 平台上安装 Scrapy 之前
    • 首先需要安装 wheel 文件。wheel 文件是一种 Python 包的分发格式,可以方便地进行安装。
    • 可以通过以下命令来安装 wheel:
pip3 install wheel

【2】安装 lxml 解析器

  • Scrapy 使用 lxml 解析器来进行 HTML 和 XML 的解析工作。
  • 要安装 lxml,可以执行以下命令:
pip3 install lxml

【3】安装 pyopenssl

  • Scrapy 在进行 HTTPS 请求时,需要使用 pyopenssl 模块来提供 SSL/TLS 支持。
  • 安装 pyopenssl 可以使用以下命令:
pip3 install pyopenssl

【4】下载并安装pywin32

【5】下载twisted的wheel文件

【6】安装twisted

  • 下载完成 twisted 的 wheel 文件后,可以使用以下命令安装 twisted:
pip3 install 下载目录\Twisted-17.9.0-cp36-cp36m-win_amd**.whl
  • 将 下载目录 替换为你实际下载 twistedwheel 文件所在的目录
  • 并根据您的 Python 环境选择正确的文件名进行替换。

【7】安装scrapy

  • 可以优先尝试这个命令,报错再按照上述安装对应的依赖
  • 当上述依赖项都安装完成后,可以使用以下命令来安装 Scrapy:
pip3 install scrapy

【二】Linux平台

  • 在 Linux 平台上安装 Scrapy,可以通过以下命令进行安装:
pip3 install scrapy

Ⅴ Scrapy框架之基本使用

# 【一】创建爬虫项目
# startproject 项目名字

# 【二】创建爬虫文件
# cd 项目
# scrapy genspider 爬虫文件名 允许访问的域名

# 【三】启动爬虫
# 执行爬虫程序

# 【四】创建一个 Request 对象
# 将 start_urls 列表里面的网址包装成 Request 对象 向目标地址发起请求

# 【五】去调度器引擎 把 请求交给引擎 让引擎分配任务

# 【六】调度器引擎 把 请求 拿过来 下一步 在会给引擎

# 【七】引擎交给下载器 下载器下载数据

# 【八】将下载好的数据返回给引擎并生成一个 Response 对象

# 【九】爬虫程序逻辑中
# 对数据进行解析和下载

# 【十】下载完成后又回到引擎 再调度 地址生成request 对象

【一】查看帮助

scrapy -h
scrapy <command> -h
  • 第一个命令用于查看全部可用命令的帮助信息
  • 第二个命令用于查看特定命令的帮助信息

【二】全局命令和项目命令

  • Project-only必须切到项目文件夹下才能执行
  • Global的命令则不需要
Global commands:
startproject #创建项目
genspider    #创建爬虫程序
settings     #如果是在项目目录下,则得到的是该项目的配置
runspider    #运行一个独立的python文件,不必创建项目
shell        #scrapy shell url地址  在交互式调试,如选择器规则正确与否
fetch        #独立于程单纯地爬取一个页面,可以拿到请求头
view         #下载完毕后直接弹出浏览器,以此可以分辨出哪些数据是ajax请求
version      #scrapy version 查看scrapy的版本,scrapy version -v查看scrapy依赖库的版本
Project-only commands:
crawl        #运行爬虫,必须创建项目才行,确保配置文件中ROBOTSTXT_OBEY = False
check        #检测项目中有无语法错误
list         #列出项目中所包含的爬虫名
parse        #scrapy parse url地址 --callback 回调函数  #以此可以验证我们的回调函数是否正确
bench        #scrapy bentch压力测试

【1】全局命令(Global commands)

  • startproject:创建一个新的 Scrapy 项目。
  • genspider:创建一个新的爬虫程序。
  • settings:显示一个 Scrapy 项目的配置信息。
  • runspider:运行一个独立的 Python 文件作为爬虫,不需要创建项目。
  • shell:进入 Scrapy 的交互式调试环境,可以检查选择器规则是否正确。
  • fetch:单独请求一个页面,并获取响应结果。
  • view:下载指定页面并在浏览器中打开,用于检查通过哪些请求获取数据。
  • version:查看当前安装的 Scrapy 版本号。

【2】项目命令(Project-only commands)

  • crawl:运行一个 Scrapy 爬虫,必须在项目目录下执行且确保配置文件中的 ROBOTSTXT_OBEY 设置为 False。
  • check:检查项目中是否存在语法错误。
  • list:列出项目中包含的所有爬虫名称。
  • parse:使用回调函数解析给定的 URL,用于验证回调函数是否正确。
  • bench:用于对 Scrapy 进行压力测试。

【3】官网链接

【三】创建项目

【1】创建步骤

(1)创建项目命令

  • 通过 Scrapy 命令创建项目
scrapy startproject 项目名

scrapy startproject SpiderNewsProjects

(2)进入爬虫项目文件

  • 切换到爬虫项目目录
cd SpiderNewsProjects

(3)创建spider项目

  • 创建自定义的爬虫程序脚本
scrapy genspider 自定爬虫程序文件名 目标网址
  • 示例
scrapy genspider wangyi news.163.com
scrapy genspider huanqiu huanqiu.com
  • 创建成功后会在 spiders文件夹下看到我们创建的自定义的文件名的py文件

【2】目录结构

(1)概览

├── NewsPro 						  # 项目名
│   ├── __init__.py
│   ├── items.py					# 类似于django的 models表模型,一个个模型类
│   ├── middlewares.py		# 中间件
│   ├── pipelines.py 			# 管道---》写持久化
│   ├── settings.py				# 项目配置文件
│   └── spiders						# 里面放了自定义的爬虫,类似于app
│       ├── __init__.py
│       ├── huanqiu.py		# 自定义爬虫文件
│       └── wangyi.py			# 自定义爬虫文件
└── scrapy.cfg						# 项目上线配置

(2)说明

  • scrapy.cfg
    • 项目的主配置信息,用来部署scrapy时使用,爬虫相关的配置信息在settings.py文件中。
  • items.py
    • 设置数据存储模板,用于结构化数据
    • 如:Django的Model
  • pipelines
    • 数据处理行为
    • 如:一般结构化的数据持久化
  • settings.py
    • 配置文件
    • 如:递归的层数、并发数,延迟下载等。强调:配置文件的选项必须大写否则视为无效,正确写法USER_AGENT='xxxx'
  • spiders
    • 爬虫目录
    • 如:创建文件,编写爬虫规则

【四】简单使用

  • wangyi.py
import scrapy

# 自动以当前文件夹命名的类型
class WangyiSpider(scrapy.Spider):
    # 爬虫文件的唯一标识 
    name = "wangyi"
    # 允许访问的域名
    allowed_domains = ["news.163.com"]
    # 起始 的 URL 列表 (重要)
    # 列表内部的 url 都会被框架进行异步请求发送
    start_urls = ["http://news.163.com/"]
		
    # 数据解析主函数:自动调用
    # 调用的次数取决于 start_urls 列表内元素的个数
    def parse(self, response):
        # response : 表示的就是响应对象
        print("response:::", response.text)

【五】启动项目

  • 通过指定的命令启动 Scrapy 项目,而非通过文件启动
# 【1】纯命令行
scrapy crawl baidu
# 【2】py 文件启动
在项目根目录下创建一个启动py文件

from scrapy.cmdline import execute

execute(['scrapy', 'crawl', '自定义爬虫文件名', "--nolog"])

【六】优化启动

【1】降低日期等级

  • 在 settings.py 文件中添加指定配置项
# 指定输出日志的类型:
LOG_LEVEL = 'ERROR'

【2】不遵循ROBOTS协议

ROBOTSTXT_OBEY = False

【3】以启动文件启动项目

  • 每一次终端启动和麻烦,我们可以在项目根目录下新建启动文件
  • bin.py:
from scrapy.cmdline import execute


execute(['scrapy', 'crawl', '自定义爬虫文件名', "--nolog"])

Ⅵ Scrapy框架之数据解析

【一】项目准备

【1】前言

  • 如果终端还在第一个项目的文件夹中,则需要在终端中执行cd ../返回到上级目录,在去新建另一个项目。

【2】创建项目步骤

(1)创建工程

scrapy startproject 项目名称

(2)切换到项目目录

cd 项目名称

(3)创建爬虫文件

scrapy genspider 爬虫文件名 www.xxx.com

(4)配置文件的修改

  • settings.py
# 不遵从robots协议
ROBOTSTXT_OBEY = False

# 指定输出日志的类型:
LOG_LEVEL = 'ERROR'

from fake_useragent import UserAgent

# 指定UA:
USER_AGENT = UserAgent().random

(5)编写爬虫文件:

  • spiders/爬虫文件名.py

【3】启动项目

  • 命令启动
scrapy crawl spider_news
  • 项目根目录下新建启动文件
    • start.py:
from scrapy.cmdline import execute
execute(['scrapy', 'crawl', '爬虫文件名', "--nolog"])

【4】项目执行流程简解

  • 启动爬虫:
    • 开始执行爬虫程序。
  • 创建Request对象:
    • 将start_urls地址包装成request对象,其中包含待爬取的网页链接、回调函数等信息。
  • 交给引擎:
    • 将创建好的request对象交给引擎进行处理。
  • 调度器排队:
    • 引擎将请求交给调度器,调度器按照一定的策略(如先进先出)将请求放入队列中进行排队。
  • 引擎处理:
    • 引擎从调度器中取出请求,并选择合适的下载中间件进行处理。
  • 下载器处理:
    • 下载器根据请求中的链接发起网络请求,下载相应的页面内容,并将下载结果返回给引擎。
  • 下载完成:
    • 下载器将网页内容下载完成后,将下载结果返回给引擎。
  • 引擎传递给爬虫:
    • 引擎将下载结果传递给相应的爬虫解析函数(例如parse函数)进行处理。
  • 爬虫解析:
    • 爬虫解析函数对下载下来的网页内容进行解析,提取出需要的数据,并生成新的Request对象或是Item对象。
  • 回到步骤2:
    • 解析函数可以继续生成新的Request对象,或是处理Item对象
    • 然后回到步骤2,继续执行后续的请求和解析过程。

【二】爬虫文件结构解析

import scrapy

# 爬虫类,继承了scrapy.Spider
class FirstSpider(scrapy.Spider):
    # 爬虫文件的名称,是当前爬虫文件的唯一标识
    name = "first"
    # 允许访问的域名
    allowed_domains = ["www.cnblogs.com/"]
    # 起始的url列表:可以将即将被请求的url,存放在当前列表中。
    # 默认情况,列表中存储的url都会被scrapy框架进行get请求的发送
    start_urls = ["https://www.cnblogs.com/"]

    # 实现数据解析
    # 参数response表示请求对应的响应对象
    # parse方法调用的次数取决于请求的次数
    def parse(self, response):
        # 可以在响应对象中直接使用xpath进行数据解析
        pass

【三】CSS解析器

【1】概览

  • response.css(‘a’)返回的是selector对象,
  • response.css(‘a’).extract()返回的是a标签对象
  • response.css(‘a::text’).extract_first()返回的是第一个a标签中文本的值
  • response.css(‘a::attr(href)’).extract_first()返回的是第一个a标签中href属性的值
  • response.css(‘a[href*=image]::attr(href)’).extract()返回所有a标签中href属性包含image的值
  • response.css(‘a[href*=image] img::attr(src)’).extract()返回所有a标签下image标签的src属性

【2】基本语法

语法 说明
* 选择所有节点
#container 选择id为container的节点
.container 选择所有class包含container的节点
div,p 选择所有 div 元素和所有 p 元素
li a 选取所有li 下所有a节点
ul + p 选取ul后面的第一个p元素
div#container > ul 选取id为container的div的第一个ul子元素
ul ~p 选取与ul相邻的所有p元素
a[title] 选取所有有title属性的a元素
a[href=”http://baidu.com”] 选取所有href属性为http://baidu.com的a元素
a[href*=”baidu”] 选取所有href属性值中包含baidu的a元素
a[href^=”http”] 选取所有href属性值中以http开头的a元素
a[href$=”.jpg”] 选取所有href属性值中以.jpg结尾的a元素
input[type=radio]:checked 选择选中的radio的元素
div:not(#container) 选取所有id为非container 的div属性
li:nth-child(3) 选取第三个li元素
li:nth-child(2n) 选取第偶数个li元素
a::attr(href) 选取a标签的href属性
a::text 选取a标签下的文本

【3】更多语法

  • 选择器是一种模式,用于选择需要添加样式的元素。
  • CSS列指示该属性是在哪个 CSS 版本中定义的。(CSS1、CSS2 还是 CSS3
选择器 例子 例子描述
.class .intro 选择 class=”intro” 的所有元素。
#id #firstname 选择 id=”firstname” 的所有元素。
* * 选择所有元素。
element p 选择所有

元素。

element,element div,p 选择所有 元素和所有

元素。

element element] div p 选择元素内部的所有

元素。

element>element div>p 选择父元素为 元素的所有

元素。

element+element div+p 选择紧接在元素之后的所有

元素。

[attribute] [target] 选择带有 target 属性所有元素。
[attribute=value] [target=_blank] 选择 target=”_blank” 的所有元素。
[attribute~=value] [title~=flower] 选择 title 属性包含单词 “flower” 的所有元素。
[attribute|=value] [lang|=en] 选择 lang 属性值以 “en” 开头的所有元素。
:link a:link 选择所有未被访问的链接。
:visited a:visited 选择所有已被访问的链接。
:active a:active 选择活动链接。
:hover a:hover 选择鼠标指针位于其上的链接。
:focus input:focus 选择获得焦点的 input 元素。
:first-letter p:first-letter 选择每个

元素的首字母。

:first-line p:first-line 选择每个

元素的首行。

:first-child p:first-child 选择属于父元素的第一个子元素的每个

元素。

:before p:before 在每个

元素的内容之前插入内容。

:after p:after 在每个

元素的内容之后插入内容。

:lang(language) p:lang(it) 选择带有以 “it” 开头的 lang 属性值的每个

元素。

element1~element2 p~ul 选择前面有

元素的每个

    元素。
[attribute^=value] a[src^=”https”] 选择其 src 属性值以 “https” 开头的每个 元素。
[attribute$=value] a[src$=”.pdf”] 选择其 src 属性以 “.pdf” 结尾的所有 元素。
[attribute*=value] a[src*=”abc”] 选择其 src 属性中包含 “abc” 子串的每个 元素。
:first-of-type p:first-of-type 选择属于其父元素的首个

元素的每个

元素。

:last-of-type p:last-of-type 选择属于其父元素的最后

元素的每个

元素。

:only-of-type p:only-of-type 选择属于其父元素唯一的

元素的每个

元素。

:only-child p:only-child 选择属于其父元素的唯一子元素的每个

元素。

:nth-child(n) p:nth-child(2) 选择属于其父元素的第二个子元素的每个

元素。

:nth-last-child(n) p:nth-last-child(2) 同上,从最后一个子元素开始计数。
:nth-of-type(n) p:nth-of-type(2) 选择属于其父元素第二个

元素的每个

元素。

:nth-last-of-type(n) p:nth-last-of-type(2) 同上,但是从最后一个子元素开始计数。
:last-child p:last-child 选择属于其父元素最后一个子元素每个

元素。

:root :root 选择文档的根元素。
:empty p:empty 选择没有子元素的每个

元素(包括文本节点)。

:target #news:target 选择当前活动的 #news 元素。
:enabled input:enabled 选择每个启用的 元素。
:disabled input:disabled 选择每个禁用的 元素
:checked input:checked 选择每个被选中的 元素。
:not(selector) :not(p) 选择非

元素的每个元素。

::selection ::selection 选择被用户选取的元素部分。

【四】Xpath解析器

【1】概览

  • Scrapy xpath语法,Xpath是XML Path的简介,基于XML树状结构,可以在整个树中寻找锁定目标节点。由于HTML文档本身就是一个标准的XML页面,因此我们可以使用XPath的语法来定位页面元素。

【2】路径表达式

表达式 描述 实例
nodename 选取nodename节点的所有子节点 //div
/ 从根节点选取 /div
// 选取任意位置的节点,不考虑他们的位置 //div
. 选取当前节点 ./div
.. 选取当前节点的父节点 ..
@ 选取属性 //@calss
  • 示例
语法 说明
artical 选取所有artical元素的子节点
/artical 选取根元素artical
./artical 选取当前元素下的artical
../artical 选取父元素下的artical
artical/a 选取所有属于artical的子元素a元素
//div 选取所有div 子元素,无论div在任何地方
artical//div 选取所有属于artical的div 元素,无论div元素在artical的任何位置
//@class 选取所有class属性
a/@href 选取a标签的href属性
a/text() 选取a标签下的文本
string(.) 解析出当前节点下所有文字
string(..) 解析出父节点下所有文字

【3】谓语

  • 谓语被嵌在方括号内,用来查找某个特定的节点或包含某个制定的值的节点
语法 说明
/artical/div[1] 选取所有属于artical 子元素的第一个div元素
/artical/div[last()] 选取所有属于artical子元素的最后一个div元素
/artical/div[last()-1] 选取所有属于artical子元素的倒数第2个div元素
/artical/div[position()❤️] 选取所有属于artical子元素的前2个div元素
//div[@class] 选取所有拥有属性为class的div节点
//div[@class=”main”] 选取所有div下class属性为main的div节点
//div[price>3.5] 选取所有div下元素值price大于3.5的div节点

【4】通配符

  • Xpath通过通配符来选取未知的XML元素
表达式 结果
//* 选取所有元素
//div/* 选取所有属于div元素的所有子节点
//div[@*] 选取所有带属性的元素

【5】 取多个路径

  • 使用 | 运算符可以选取多个路径
表达式 结果
//div | //table 选取文档中所有的div和table节点
//div/a | //div/p 选取所有div元素的a和p 元素
artical/div/pl | //span 选取所有div下的pl和文档中所有span

【6】轴

  • 轴可以定义相对于当前节点的节点集
轴名称 表达式 描述
ancestor ./ancestor:

标签:novel,滑块,img,self,验证码,Scrapy,article,div,scrapy
From: https://www.cnblogs.com/zyb123/p/18316818

相关文章

  • SkiaSharp画的验证码在Linux下无法正常显示
    SkiaSharp是Google的Skia图形库的.NET封装版,可用于跨移动、服务器和桌面平台绘制2D图形。SkiaSharp可与OpenGL一起用于硬件加速渲染。SkiaSharp最初由Mono开发,但现在由Microsoft维护,并根据MITLicense提供。使用SkiaSharp生成验证码图片示例代码usingSkiaSharp......
  • Scrapy:存储/抓取当前的start_url?
    背景(可以跳过):我当前正在运行两个不同的scrapy爬虫。第一个检索有关产品x的信息,第二个检索有关产品x的其他信息,这些信息是在第一个机器人抓取的url上找到的.我的管道将每个产品的信息连接到多个文本文件中,其中每个产品的信息占用一行数据,并作为不同的文本文件......
  • Spring Boot实现分布式验证码登录方案
     ​ 博客主页:   南来_北往......
  • Kaptcha - Java图片验证码
    1.什么是Kaptcha验证码?Kaptcha是一个强大的开源Java验证码生成库,由Google开发。它能够生成高度可配置的图片验证码,主要用于防止自动化程序滥用web应用,提高应用的安全性。2.Kaptcha的主要特性Kaptcha具有以下几个主要特性:高度可配置:可以自定义字体、颜色、大小......
  • 第二节:一锁二判三更新、短信验证码完善方案、自动关单问题
    一.        二.        三.         !作       者:Yaopengfei(姚鹏飞)博客地址:http://www.cnblogs.com/yaopengfei/声     明1:如有错误,欢迎讨论,请勿谩骂^_^。声     明2:原创博客请在转载......
  • 计算机毕业设计Python+Tensorflow小说推荐系统 K-means聚类推荐算法 深度学习 Kears
    2、基于物品协同过滤推荐算法2.1、基于⽤户的协同过滤算法(UserCF)该算法利⽤⽤户之间的相似性来推荐⽤户感兴趣的信息,个⼈通过合作的机制给予信息相当程度的回应(如评分)并记录下来以达到过滤的⽬的进⽽帮助别⼈筛选信息,回应不⼀定局限于特别感兴趣的,特别不感兴趣信息的纪录也相......
  • SpringBoot增加验证码
    一、加入验证码依赖包com.github.whvcseeasy-captcha1.6.2二、实现验证码控制层@GetMapping("/common/kaptcha")publicvoiddefaultKaptcha(HttpServletRequesthttpServletRequest,HttpServletResponsehttpServletResponse)throwsException{httpServletRespo......
  • Python web自动化爬虫-selenium/处理验证码/Xpath
    #coding:utf-8importtimeimportrandomfromtimeimportsleepfromcsvimportwriterfromseleniumimportwebdriverfromselenium.webdriver.common.byimportByfromchaojiyingimportChaojiying_Clientfromselenium.webdriverimportActionChainsdriver......
  • 使用Spring Boot实现图形验证码:从零开始的详细教程
    使用SpringBoot实现图形验证码:从零开始的详细教程在现代Web应用中,图形验证码是一种常见的防止机器人和恶意攻击的手段。今天,我们将深入探讨如何在SpringBoot项目中实现图形验证码。通过这个教程,你将学会如何生成和验证图形验证码,并将其集成到你的SpringBoot应用中。一、项目......
  • 自动填充验证码,懒人福音,对视觉障碍的朋友太友善了
    自动填充验证码,懒人福音,对视觉障碍的朋友太友善了一、安装插件Tampermonkey油猴(篡改侯)脚本插件https://www.tampermonkey.net/这个怎么安装就不详细介绍了二、安装验证码解析脚本https://greasyfork.org/zh-CN/scripts/418942-万能验证码自动输入-升级版点击进去直接点......