美文网首页
01_python爬取简书文章,输出为pdf(还是个坑)

01_python爬取简书文章,输出为pdf(还是个坑)

作者: 乐大爷L | 来源:发表于2018-06-08 08:53 被阅读36次

写在前面

由于在简书上写的文章是mardown格式的,直接复制下来比较乱,怎么采用爬虫的方式将文章获取下来呢?

分析

1、要获取的文章地址:
  • url:https://www.jianshu.com
  • 用户:/u/39cef8a56bf9
  • 分类:获取我的分类,并存入list或字典,如:/nb/23293583
  • 文章地址:获取一个分类下的所有文章地址,如:/p/3cb9bf01825c
    获取文章内容:标题 作者 字数 文章正文(正文可以根据不同的标签设定不同的字体或格式)
2、要用到的库:
  • requests:发送get请求,获取页面内容
  • Beautifulsoap:解析html
  • pdfkit:将html转换为pdf
  • 由于pdfkit是工具wkhtmltopdf的封装,所以需要现在本机安装wkhtmltopdf,并将bin目录添加到环境变量path中
  • wkhtmltopdf下载地址:https://wkhtmltopdf.org/downloads.html
3、想要输出的pdf格式:
  • 以简书中的分类命名pdf文件
  • 以每篇文章的标题为pdf文件中的文章标题

技术准备

1、requests发送请求
  • 添加header信息,不然会报403。headers中添加浏览器信息就可以啦,如果还是报403,证明你的user-agent信息不对,换一个
2、beautifulsoap解析html
3、pdfkit将html转换为pdf

实现步骤

1、
2、
3、
4、
改进:
1、处理文章页面的html,删除article之后的所有节点,然后保存html

第一版

实现点:每个文集生成了一个pdf文件,但是每篇文章中包含了页面中的推荐文章之类的,信息点不集中。
改进点:对html进行处理后,采用from_file进行转换。将每个url处理后的html保存为文件,再将文件名列表传给from_file转换为pdf文件。

import re

import pdfkit
from selenium import webdriver
from bs4 import BeautifulSoup

driver = webdriver.PhantomJS()
base_url = 'https://www.jianshu.com'
user = '/u/39cef8a56bf9'

# 获取页面html信息
def get_html(driver, url):
    driver.get(url)
    html = driver.page_source
    return html

# 将html实例化为Beautiful Soup对象
def html_to_bsobj(html):
    bsobj = BeautifulSoup(html)
    bsobj.encode('utf-8')
    return bsobj

# 解析首页html,获取文集的链接信息
def get_essays(bsobj):
    essays = bsobj.find_all('a', attrs={'class': 'name'}, href=re.compile("^/nb/"))
    # print(essays)
    essay_dict = {}
    for essay in essays:
        essay_link = essay['href']
        essay_name = essay.text
        essay_dict[essay_name.strip()] = essay_link
    return essay_dict


def get_articles(bsobj):
    articles = bsobj.find_all('a', attrs={'class': 'title'}, href=re.compile("^/p/"))
    article_urls = []
    for article in articles:
        article_link = article['href']
        article_urls.append(base_url+article_link)
    return article_urls


def save_pdf(article_urls, filename):
    # options = {
    #     'page-size': 'Letter',
    #     'encoding': "UTF-8",
    #     'custom-header': [
    #         ('Accept-Encoding', 'gzip')
    #     ]
    # }
    pdfkit.from_url(article_urls, output_path=filename+'.pdf')


if __name__ =='__main__':
    index_page = get_html(driver, base_url+user)
    index_bsobj = html_to_bsobj(index_page)
    # print(get_essays(index_bsobj))

    for essay_name, essay_link in get_essays(index_bsobj).items():
        print(essay_link)
        essay_page = get_html(driver, base_url+essay_link)
        essay_bsobj = html_to_bsobj(essay_page)
        article_urls = get_articles(essay_bsobj)
        save_pdf(article_urls, essay_name)

改进版:先这样吧

"""
Created by catleer on 2018-06-06.
"""
__author__ = 'catleer'

import codecs
import re, time

import pdfkit
from selenium import webdriver
from bs4 import BeautifulSoup

html_template = """
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
</head>
<body>
{content}
</body>
</html>
"""

driver = webdriver.PhantomJS()
base_url = 'https://www.jianshu.com'
user = '/u/39cef8a56bf9'


# 将html实例化为Beautiful Soup对象
def html_to_bsobj(driver, url):
    driver.get(url)
    time.sleep(10)
    html = driver.page_source
    bsobj = BeautifulSoup(html)
    bsobj.encode('utf-8')
    return bsobj

# 解析首页html,获取文集的链接信息
def get_essays(bsobj):
    essays = bsobj.find_all('a', attrs={'class': 'name'}, href=re.compile("^/nb/"))
    # print(essays)
    essay_dict = {}
    for essay in essays:
        essay_link = essay['href']
        essay_name = essay.text
        essay_dict[essay_name.strip()] = essay_link
    return essay_dict

# 获得文章的链接信息
def get_articles(bsobj):
    articles = bsobj.find_all('a', attrs={'class': 'title'}, href=re.compile("^/p/"))
    article_urls = []
    for article in articles:
        article_link = article['href']
        article_urls.append(base_url+article_link)
    print("排序前", article_urls)
    article_urls.reverse()
    return article_urls


# 解析文章的html页面,将文章正文存入html中,并对图片进行处理
def parse_article_html(article_page):
    body = article_page.find_all(class_='article')[0]
    body = str(body)

    # 图片将相对路径处理为绝对路径
    pattern = "(<img .*?data-original-src=\")(.*?)(\")"

    def func(m):
        if not m.group(2).startswith("http"):
            rtn = "".join([m.group(1), 'https:', m.group(2), m.group(3)])
            return rtn
        else:
            return "".join([m.group(1), m.group(2), m.group(3)])

    html = re.compile(pattern).sub(func, str(body))
    html = html_template.format(content=html)
    return html


def save_pdf():
    options = {
        'page-size': 'Letter',
        'margin-top': '0.75in',
        'margin-right': '0.75in',
        'margin-bottom': '0.75in',
        'margin-left': '0.75in',
        'encoding': "UTF-8",
        'custom-header': [
            ('Accept-Encoding', 'gzip')
        ],
        'cookie': [
            ('cookie-name1', 'cookie-value1'),
            ('cookie-name2', 'cookie-value2'),
        ],
        'outline-depth': 10,
    }


    index_bsobj = html_to_bsobj(driver, base_url + user)
    essays = get_essays(index_bsobj)
    print(essays)

    for essay_name, essay_link in essays.items():
        essay_bsobj = html_to_bsobj(driver, base_url + essay_link)
        article_urls = get_articles(essay_bsobj)
        # print(article_urls)
        htmls = []
        for index, article_url in enumerate(article_urls):
            article_page = html_to_bsobj(driver, article_url)
            time.sleep(10)
            # print(article_page)
            html = parse_article_html(article_page)
            f_name = '.'.join([essay_name + str(index), 'html'])
            with codecs.open(f_name, 'w+', 'utf-8') as f:
                f.write(html)
            htmls.append(f_name)
            break
        pdfkit.from_file(htmls, essay_name+'.pdf', options=options)


if __name__ == '__main__':
    save_pdf()




相关文章

网友评论

      本文标题:01_python爬取简书文章,输出为pdf(还是个坑)

      本文链接:https://www.haomeiwen.com/subject/nhdtsftx.html