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

Python爬虫自动爬取拉钩教育课程文章并保存成PDF

程序员文章站 2022-03-04 09:13:32
背景:前段时间写了一篇Python爬虫爬取拉钩教育视频的博客,有朋友留言说改写下爬取文章,今天有空改了改…爬取视频版:https://blog.csdn.net/Mr_Renxiansheng/article/details/106313236由于在尝试的过程中爬取过猛…账号被封了,所以这里贴的图片会有些差异,请担待正文......

背景:

前段时间写了一篇Python爬虫爬取拉钩教育视频的博客,有朋友留言说改写下爬取文章,今天有空改了改…
爬取视频版:https://blog.csdn.net/Mr_Renxiansheng/article/details/106313236

运用到的技术点总结

1、线程
2、队列
3、requests库
4、json
5、pdfkit
注意:由于需要保存成PDF,我这里用了pdfkit,使用前得先安装[http://wkhtmltopdf http://wkhtmltopdf.org/downloads.html](https://wkhtmltopdf%20%20http://wkhtmltopdf.org/downloads.html) windows选择 选择 7z Archive 下载解压即可

正文

基本流程同爬取视频一样。
pdfkit 有一个方法是from_string 通过这个方法可以将string转换成pdf,所以我们这里只需要找到课程文章的HTML并转成str,最后丢到pdfkit转换就可以了,具体实现如下:
打开文章页面,通过查看源码可以发现,课程文章并不在源码中,所以我们这里需要通过抓包的形式来获取。 直接F12,刷新后抓包
Python爬虫自动爬取拉钩教育课程文章并保存成PDF
通过分析可以发现这个响应里面有文章的html,查看请求url
https://gate.lagou.com/v1/neirong/kaiwu/getCourseLessonDetail?lessonId=xxx
最后的数字是课程的id,为了一次性爬取所有课程文章,那么就需要知道所有课程文章的id,继续分析请求…
Python爬虫自动爬取拉钩教育课程文章并保存成PDF
找到课程文章id了,通过https://gate.lagou.com/v1/neirong/kaiwu/getCourseLessonDetail?lessonId=(id)就可以拼接成正确的url了,最后通过这个url获取课程文章的html

到了这里基本上思路都已经通了,简单总结下:
1、找到所有课程文章的id,用来拼接正确的url
2、通过抓包分析找到课程文章html的请求url,解析得到html
3、将html转换成pdf

好了上具体代码:


import threading
from queue import Queue
import requests
import json
import time
import pdfkit




class LaGou_spider():
    def __init__(self):
        self.url = 'https://gate.lagou.com/v1/neirong/kaiwu/getCourseLessons?courseId=17'
        self.headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36',
            'Cookie': '请使用自己的Cookie',
            'Referer': 'https://kaiwu.lagou.com/course/courseInfo.htm?courseId=17',
            'Origin': 'https://kaiwu.lagou.com',
            'Sec-fetch-dest': 'empty',
            'Sec-fetch-mode': 'cors',
            'Sec-fetch-site': 'same-site',
            'x-l-req-header': '{deviceType:1}'}
        self.textUrl='https://gate.lagou.com/v1/neirong/kaiwu/getCourseLessonDetail?lessonId='  #发现课程文章html的请求url前面都是一样的最后的id不同而已
        self.queue = Queue()  # 初始化一个队列
        self.error_queue = Queue()

    def parse_one(self):
        """

        :return:获取文章html的url
        """
        # id_list=[]
        html = requests.get(url=self.url, headers=self.headers).text
        dit_message = json.loads(html)
        message_list = dit_message['content']['courseSectionList']
        # print(message_list)
        for message in message_list:
            for i in message['courseLessons']:
                true_url=self.textUrl+str(i['id'])
                self.queue.put(true_url)#文章的请求url


        return self.queue

    def get_html(self,true_url):
        """

        :return:返回一个Str 类型的html
        """
        html=requests.get(url=true_url,timeout=10,headers=self.headers).text
        dit_message = json.loads(html)
        str_html=str(dit_message['content']['textContent'])
        article_name=dit_message['content']['theme']
        self.htmltopdf(str_html,article_name)

    def htmltopdf(self,str_html,article_name):
        path_wk = r'D:\wkhtmltox-0.12.6-1.mxe-cross-win64\wkhtmltox\bin\wkhtmltopdf.exe'
        config = pdfkit.configuration(wkhtmltopdf=path_wk)
        options = {
            'page-size': 'Letter',
            'encoding': 'UTF-8',
            'custom-header': [('Accept-Encoding', 'gzip')]
        }
        pdfkit.from_string(str_html,"{}.pdf".format(article_name),configuration=config,options=options)



    def thread_method(self, method, value):  # 创建线程方法
        thread = threading.Thread(target=method, args=value)
        return thread

    def main(self):

        thread_list = []
        true_url= self.parse_one()
        while not  true_url.empty():
            for i in range(10):  # 创建线程并启动
                if not true_url.empty():
                    m3u8 = true_url.get()
                    print(m3u8)
                    thread = self.thread_method(self.get_html, (m3u8,))
                    thread.start()
                    print(thread.getName() + '启动成功,{}'.format(m3u8))
                    thread_list.append(thread)
                else:
                    break
            while len(thread_list)!=0:
                for k in thread_list:
                    k.join()  # 回收线程
                    print('{}线程回收完毕'.format(k))
                    thread_list.remove(k)



run = LaGou_spider()
run.main()


注意:

请控制下爬取的速度,太快可能会导致账号被封…大饼在调试程序的过程中曾被封过,过了一段时间后才恢复…

本文地址:https://blog.csdn.net/Mr_Renxiansheng/article/details/107230524