文章目录

  • 1.网站检查:
  • 2.项目实施:
  • 2.1 Scrapy项目创建:
  • 2.2 项目准备:
  • 2.3 项目流程:



Pyppeteer的安装:

pip install pyppeteer


清华源安装:

pip3 install -i https://pypi.tuna.tsinghua.edu.cn/simple pyppeteer


Pyppeteer可以直接饶过网站加密,从加载完的浏览器中直接抓取


本次爬取的网站:

Scrape Center spa6


python爬取带密码网页 python爬取加密网页_Pyppeteer

1.网站检查:

F12 检查页面 ——> 点击network,切换页面,发现加载出部分数据,点击第一条数据查看headers
Request URL:
https://spa6.scrape.center/api/movie?limit=10&offset=10&token=MjEzMmE3MTIxOTdjNzEzNWQyMzc5OWVmN2U1MjYxNGYxZmRkNWM0ZSwxNjU1ODYwOTEwpython爬取带密码网页 python爬取加密网页_ide_02
这一串为加密字符:token=MjEzMmE3MTIxOTdjNzEzNWQyMzc5OWVmN2U1MjYxNGYxZmRkNWM0ZSwxNjU1ODYwOTEw

由此可知,网站数据是由api调用,并进行了加密,若没学习过Javascript逆向,则可以使用Pyppeteer调用;

2.项目实施:

2.1 Scrapy项目创建:

创建Scrapy项目:

  1. 在终端中找到需要创建项目的目录;
  2. scrapy startproject spa6 spa6为项目名,scrapy startproject为固定语法;
  3. 进入到spa6文件夹中,cd spa6
  4. scrapy genspider example example.com 后面两随便写即可

2.2 项目准备:

在Scrapy项目创建过程中,我写的第一个example是app1,所以在文件夹spider中就可以看见一个app1.py文件,点开它

python爬取带密码网页 python爬取加密网页_python爬取带密码网页_03


这就是项目的主文件,需要进行爬取的操作均在这里实现;

app1.py导入Pyppeteer库,from gerapy_pyppeteer import PyppeteerRequest

import scrapy
from gerapy_pyppeteer import PyppeteerRequest

class App1Spider(scrapy.Spider):
    name = 'app1'
    # allowed_domains = ['df']
    # start_urls = ['http://df/']

    def start_requests(self):
        url = "https://spa6.scrape.center/page/2"
        # 使用Pyppeteer 等待class = m-b-sm元素出现
        yield PyppeteerRequest(url, callback=self.show, wait_for='.m-b-sm')

    def show(self, response):
        print(response.text)

关键代码:

yield PyppeteerRequest(url, callback=self.show, wait_for='.m-b-sm')

参数一:用于传递url;
参数二:指定传递数据的函数;这里指定的是show函数;
参数三:等待一个元素加载出来,这里等待的是class类 .m-b-sm

此时还需要做另一些准备,将Pyppeteer与Scrapy对接
项目关键:
setting.py文件夹中
更改 DOWNLOADER_MIDDLEWARES
实现Pyppeteer的对接middlewares,使用Pyppeteer中的下载器

DOWNLOADER_MIDDLEWARES = {
    # 'spa6.middlewares.Spa6DownloaderMiddleware': 543,
    'gerapy_pyppeteer.downloadermiddlewares.PyppeteerMiddleware': 543,
}
# 指定不加载的数据类型,image图片,font字体文件
GERAPY_PYPPETEER_IGNORE_RESOURCE_TYPES = ['image', 'font']

末尾加入

# 对接pyppeteer
CONCURRENT_REQUESTS = 3
GERAPY_PYPPETEER_HEADLESS = False
# 反屏蔽
GERAPY_PYPPETEER_PRETEND = True
# 设置超时时间
GERAPY_PYPPETEER_DOWNLOAD_TIMEOUT = 30
# 设置窗口大小
GERAPY_PYPPETEER_WIDTH = 1400
GERAPY_PYPPETEER_HEIGHT = 700

Scrapy的运行

需要在终端中输入 scrapy crawl 项目名,项目名就是app1.py文件中的name参数,我这里就是app1;

接下来介绍,一种更加方便的方法,就不用每次都在终端中输入直接运行就可以了

创建一个启动文件,run.py

python爬取带密码网页 python爬取加密网页_Pyppeteer_04


run.py文件代码,要启动Scrapy项目直接运行run.py即可

from scrapy.cmdline import execute
execute(['scrapy', 'crawl', 'app1'])

2.3 项目流程:

一下代码是在app1.py主文件中的show()函数内
导入lxml库中的etree,from lxml import etree 该代码检查是否可以获得数据,由于是异步执行,所以获取数据的顺序不一定一致;

def show(self, response):
    source = response.text
	demo = etree.HTML(source).xpath('//h2[@class="m-b-	sm"]/text()')
	print(demo)

即可测试能否爬取到数据

项目翻页有两种方法实现,方法一是直接通过更改网页链接进行翻页;
方法二是通过Pyppeteer的鼠标控制进行翻页;

方法一:使用for循环翻页

import scrapy
from gerapy_pyppeteer import PyppeteerRequest
from lxml import etree

class App1Spider(scrapy.Spider):
    name = 'app1'
    # allowed_domains = ['df']
    # start_urls = ['http://df/']

    def start_requests(self):
        # 翻页
        for i in range(1, 4):
            url = "https://spa6.scrape.center/page/{}".format(i)
            yield PyppeteerRequest(url, callback=self.show, wait_for='.m-b-sm')
        # 使用Pyppeteer 等待class = m-b-sm元素出现


    def show(self, response):
        source = response.text
        # 获取页面中10个div[@class="el-card__body"]
        demo = etree.HTML(source).xpath('//div[@class="el-card__body"]')
        for i in demo:
            # 获取标题
            title = i.xpath('div[1]/div[2]/a/h2/text()')[0]
            category = i.xpath('div[1]/div[2]/div[1]//text()')
            # category是一个列表,所以使用map函数解析列表,并执行操作;str.strip消除空格;再用|拼接
            category = '|'.join(map(str.strip, category))
            print(title)
            print(category)

方法二:使用点击控制翻页
需要载入一个异步包 asyncio
在类外创建一个异步函数

import asyncio

async def hello(page):
    await page.click('.btn-next')
def start_requests(self):
        # 翻页
        url = "https://spa6.scrape.center/page/1"
        yield PyppeteerRequest(url, callback=self.show, wait_for='.m-b-sm', actions=hello)

翻页:yield PyppeteerRequest(url, callback=self.show, wait_for='.m-b-sm', actions=hello) actions = hello为调用hello函数

翻页的思路是:设定一个类参数page,用于记录翻页情况,没翻一次减去一次page,便于指定爬取页数

import scrapy
from gerapy_pyppeteer import PyppeteerRequest
from lxml import etree
import asyncio

async def hello(page):
    await page.click('.btn-next')

class App1Spider(scrapy.Spider):
    name = 'app1'
    # allowed_domains = ['df']
    # start_urls = ['http://df/']
    page = 10

    def start_requests(self):
        # 翻页
        url = "https://spa6.scrape.center/page/1"
        yield PyppeteerRequest(url, callback=self.show, wait_for='.m-b-sm')

    def show(self, response):
        print(response.url)
        source = response.text
        # 获取页面中10个div[@class="el-card__body"]
        demo = etree.HTML(source).xpath('//div[@class="el-card__body"]')
        for i in demo:
            # 获取标题
            title = i.xpath('div[1]/div[2]/a/h2/text()')[0]
            category = i.xpath('div[1]/div[2]/div[1]//text()')
            # category是一个列表,所以使用map函数解析列表,并执行操作;str.strip消除空格;再用|拼接
            category = '|'.join(map(str.strip, category))
            print(title, category)
        App1Spider.page = App1Spider.page - 1
        if App1Spider.page > 0:
            yield PyppeteerRequest(response.url, callback=self.show, wait_for='.m-b-sm', actions=hello, dont_filter=True)

yield PyppeteerRequest(response.url, callback=self.show, wait_for=‘.m-b-sm’, actions=hello, dont_filter=True),
该处加入了 dont_filter参数
Scrapy中是默认开启过滤,默认dont_filter = False
我们第一次传入url时已经使用过了response.url,当我们进行函数回调时,系统会把重复的url删除,这样就不能进行回调了,所以要把回调机制关闭