11

写爬虫抓取页面是不是还需要等待页面有数据了才能抓取,那么页面渲染的这段时间(虽然不长但架不住多啊)是不是可以省去呢

基础不太了解的可以参考我这篇简单使用的文章

使用puppeteer抓取接口拦截ajax数据

这里有小伙伴就要说了我都知道接口了直接去请求不就完了吗,python,node,axios,原生的ajax那个不行啊

哈哈,那要是接口参数中有随机数呢,有随机时间点呢,有随机时间戳和uuid再混起来呢

分分钟怀疑人生

来看小说站的接口参数

咱们准备抓取的信息

图中标记的自上往下分别是:

  1. 书籍id
  2. 要抓取的信息
  3. 接口
  4. 接口地址

clipboard.png

接口数据

clipboard.png

怀疑人生的时候到了,来看请求参数

  1. 首先是 post 请求
  2. 再来分析Form Data数据
  3. bookID和user_id都没啥事
  4. timestamp这个参数是有一定间隔时间的时间戳
  5. 头大的是这个, sign, 黑人问号脸(这是个啥)

clipboard.png

翻腾了好久找了一个js文件发现了sign的由来

  1. 还是个md5加密的
  2. 那么问题来了
  3. 这个r,通过这个接口可以知道它就是bookid了
  4. 小问题是这个有固定间隔时间的timestamp怎么获取,喜欢等待的小伙伴可以试试等等看,具体我也不知道,不过应该在10分钟以上了
  5. 大问题是这个bookKey是个啥啊,找遍了也没找到,我能怎么办,我也很绝望啊,没办法只能放大招了

clipboard.png
clipboard.png

官网的api可以看到这么几个,直接上代码(详细说明在注释里)

clipboard.png
clipboard.png

代码关键的地方截图

clipboard.png

结果截图

clipboard.png

转载请附上本文章地址

const puppeteer = require('puppeteer');
const mongodb = require('mongodb')
// mongoDB
const mongo_url = 'mongodb://127.0.0.1:27017/book'
const mongoClient = mongodb.MongoClient
// 休眠函数
function sleep(second) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(' enough sleep~');
        }, second);
    })
}
// 站点地址url
var url = `http://t.shuqi.com/route.php?pagename=route.php#!/ct/cover/bid/6070553`

class Parse {
  constructor() {
    this.page = null
    this.browser = null
    this.bookMessage = {}
  }
  async init() {
    // 构造浏览器对象
    // 显示浏览器
    this.browser = await puppeteer.launch({
      'headless': false,
    });
    // 创建页面
    this.page = await this.browser.newPage();
    // 模拟浏览器信息
    const UA = "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.119 Safari/537.36";
    await Promise.all([
        this.page.setUserAgent(UA),
        // 允许执行js脚本
        this.page.setJavaScriptEnabled(true),
        // 页面视口大小
        this.page.setViewport({width: 1100, height: 1080}),
    ]);
    await this.getBook()
  }
  async getBook() {
    // 打开页面
    await this.page.goto(url);
    let page = await this.page
    // 等待页面请求完成
    page.on('requestfinished', request => {
      // 查看所有请求地址
      // console.log(request.url)
      // ajax
      if (request.resourceType == "xhr") {
        // 匹配所需数据的请求地址
        if(request.url.indexOf('http://walden1.shuqireader.com/webapi/book/info') != -1) {
          (async () => {
            try {
              // 获取数据并转为json格式
              let res = await request.response();
              let result = await res.json();
              let res_data = result.data     
              // 接口数据中找到需要的数据      
              this.bookMessage = {                        
                'book_name': res_data.bookName,              
                'book_summary': res_data.desc,              
                'author_name': res_data.authorName,              
              }
              let data = await this.bookMessage
              mongoClient.connect(mongo_url, (err, db) => {                
                db.collection('shuqi_test').insert(data,(err, result) => {
                    if(err) {
                      console.log('连接失败')
                    }
                    // 关闭浏览器            
                    this.browser.close()                    
                    // 关闭数据库连接
                    db.close()
                  }
                )
              })
            } catch(err) {
              console.log(err)
            }
          })()
        }
      }
    });
  }
}

let parse = new Parse()
parse.init()

Taste
254 声望7 粉丝

能做并不意味着应该做