Python爬取网页保存为PDF

2022-04-26 17:39:27 浏览数 (1)

1.前言

我在今天还能更文,是不是很单身狗,可我也想尝尝这爱情的苦。越是在孤独的时候越是要战胜它,所以今天去买了一份慕课专栏,用买买买来解决孤独。

作为一个拥有几个、几十个、还是几百个粉丝的群主,怎么能忘了在苦海挣扎的你们呢?

这个专栏在网上已经是售出了7000 份,在这个小众群体中,这个销量已经是很高了,是47个专栏中最高的,可见写的确实很不错。

一线城市公司面试都会喜欢问一些源码的内容,尽管在工作上用的很少,不妨碍它存在,尝尝遭遇“面试造火箭,工作拧螺丝”的情况。但是我们要知道,即便是拧螺丝也是火箭的螺丝。

面试问的比较深入的问题,并不是为了难为你,而是看看你是否对一门语言有深层次的把握。

好比你熟悉了古今中外的历史,你会发现,这个世界的规律从来没变过。

废话这么多,那么说说今天的礼物吧。就是上面的这份专栏,我已经把内容转存成PDF。但是授之于鱼不如授之于渔,今天的分享一份Python代码,爬取网页html内容,保存到PDF后自(da)己(jia)看。

2.需求

爬取慕课网《面试官系统精讲Java源码及大厂真题》专栏的内容,以PDF形式保存到本地。

3.分析

  1. 这是付费内容,所以肯定会判断当前请求是否合法,所以爬虫中必须带着cookice的内容,让服务器知道这是你,否则会拒绝你的请求。
  2. 使用wkhtmltopdf 工具,需要到官网下载安装本地后可以用。
  3. 工具是将HTML页面转成PDF,第一个图是网页的内容,左边的目录是灵活的,但是下载到PDF中就没有效果,还不好看,所以直接把目录拿掉,达到效果是第二个。
  1. 代码中 html_template 就是拼装的模板,删除了不需要的内容,所以你需要知道一点前端的内容。
  2. 剩下的就是爬虫常用的几个库 requests ,BeautifulSoup ,json
  3. 源码贴在下面了仅供参考使用。没有使用 try except,生产中需要不住异常。
代码语言:javascript复制
import os
import requests
from bs4 import BeautifulSoup
import json
import pdfkit

html_template = """
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
        <link rel="stylesheet"
          href="http://static.mukewang.com/static/css/??base.css,common/common-less.css?t=2.5,column/zhuanlanChapter-less.css?t=2.5,course/inc/course_tipoff-less.css?t=2.5?v=201911221436"
          type="text/css"/>
<link href="http://moco.imooc.com/captcha/style/captcha.min.css" rel="stylesheet">
<link rel="stylesheet" href="http://www.imooc.com/static/moco/v1.0/dist/css/moco.min.css?t=201911221436" type="text/css" />
<link rel="stylesheet" href="http://www.imooc.com/static/lib/swiper/swiper-3.4.2.min.css?t=201911221436">
</head>
<body style="background:white;background-color:white">

<div class="main-con fixed">
 <div class="right-content" style="padding-left:0px;">
<div class="container clearfix" style="display: block;">
<div class="center_con js-center_con l">

{content}

</div>
</div>
</div>
</div>
</body>
</html>
"""

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36',
    'Cookie': 'sajssdk_2015_cross_new_user=1; Hm_lvt_f0cfcccd7b1393990c78efdeebff3968=1589958823; IMCDNS=0; imooc_isnew=1; imooc_isnew_ct=1589958822; imooc_uuid=79ba42d1-dba0-4c15-bcb4-59791dc988a9; last_login_username=liudrain@163.com; adv_#globalTopBanner_2911=1589958872594; PSEID=18bab2b6e29e505149c9bfed416f7aa4; loginstate=1; apsid=AwNjIwNzRjYjg4YmZkYzVmZWM1YWIzYTlhOTM4MTgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMzE5NjgyOQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABsaXVkcmFpbkAxNjMuY29tAAAAAAAAAAAAAAAAAAAAADBhZjliMmRkYmUyZjJiM2FhNmExNmY3Mjc5YWMwNDI4LNnEXizZxF4=Zj; sensorsdata2015jssdkcross={"distinct_id":"3196829","first_id":"17230ee4b1167c-07bcf017e968db-376b4502-2073600-17230ee4b1298f","props":{"$latest_traffic_source_type":"引荐流量","$latest_search_keyword":"未取到值","$latest_referrer":"https://unitradeprod.alipay.com/acq/cashierReturn.htm?sign=K1iSL1GPeGbSvmIcCfvJFOlQnC344vkFZfgRwLbnwkpv%252FwlaJRev1UgxnMKwijyz5F%252FGw26TwRM%253D&outTradeNo=2005201517348565407335&pid=20888216223418"},"$device_id":"17230ee4b1167c-07bcf017e968db-376b4502-2073600-17230ee4b1298f"}; addQunTip47=true; Hm_lpvt_f0cfcccd7b1393990c78efdeebff3968=1589959225; cvde=5ec4d8a670b63-39',
    'Host': 'www.imooc.com'
}
# 通过url获取到html保存到本地
def parse_url_to_html(url, name):
    response = requests.get(url, headers=headers, timeout=30)
    soup = BeautifulSoup(response.content, "html.parser")
    body = soup.find_all(class_="article-con")[0]
    html = str(body)
    html = html_template.format(content=html)
    html = html.replace("//img", "http://img")
    html = html.replace("/static/img", "http://www.imooc.com/static/img")
    html = html.replace("data-original", "src")
    # html = html.replace('''alt="图片描述"''', '''alt="图片描述" style="height:60%"''')
    with open("imooc/"   name, 'w', encoding="utf-8") as f:
        f.write(str(html))
    return name
# html 转成pdf
def html_to_pdf(htmlname, pdfname):
    options = {
        'page-size': 'Letter',
        'margin-top': '0',
        'margin-right': '0',
        'margin-bottom': '0',
        'margin-left': '0',
        'encoding': "UTF-8",
        'no-outline': None,
        'custom-header': [
            ('Accept-Encoding', 'gzip')
        ],
        'outline-depth': 10,
    }
    config = pdfkit.configuration(wkhtmltopdf='d:\Program Files\wkhtmltopdf\bin\wkhtmltopdf.exe')
    pdfkit.from_file("imooc/"   htmlname, "imooc/"   pdfname, configuration=config)
    # pdfkit.from_url(url, "imooc/686.pdf", configuration=config)
def get_menu_url(url):
    response = requests.get(url, headers=headers)
    jsonobject = json.loads(response.text)
    list = jsonobject['data']['list']
    for i in list:
        urllist = i['list']
        for n in urllist:
            title = str(n['title'])
            title = title.replace("?", "")
            title = title.replace("?", "")
            title = title.replace("*", "")
            print(title)
            # restful 链接 47是课程的id article 后面是文章的id
            url = "http://www.imooc.com/read/47/article/"   (n['url'][-3:])
            name = parse_url_to_html(url, title   ".html")
            html_to_pdf(name, title   ".pdf")
            os.remove("imooc/"   name)
            
if __name__ == '__main__':
    # url = "http://www.imooc.com/read/43/article/686"
    # 获取慕课网上的专栏的目录的list,其实需要知道课程id即可
    url = "http://www.imooc.com/read/cataloglist?column_id=47"
    get_menu_url(url)

4.总结

你可以用生活中来验证所学的内容,生活处处可以python。

总体来讲,作为一个工具,python是个不错的万能胶。这样看起来,是不是比网页上爽多了,还可以分享呢。

上面的相关资料我已经分享在群里,谢谢大家的支持。

最后祝大家520快乐,能早日脱单。

0 人点赞