Aug. 22nd 笔记 - 针对掘金官网的爬虫| 青训营笔记

Aug. 22nd 笔记 - 针对掘金官网的爬虫

这是我参与「第四届青训营 」笔记创作活动的的第5天

参考:blog.csdn.net/weixin_3616…

需求

我们小组的任务是仿掘金官网,必然的,涉及到内容问题。我们的策略是爬取一部分内容。由于我们都没有数据库基础,故先需爬取基础信息:文章标题,作者,主题,摘要,预览图等;然后依次放入网页之中。再选取一部分文章爬取文章内部内容。

一个传统的方法

最简单的,也是我最早想到的,就是传统的读DOM树爬取相关信息。但一方面掘金官网是动态网页,不那么好确定所需元素在DOM树中的位置,且由于反扒机制的存在,直接读取可能并不现实,且存在被封IP的可能。一个最懒人的解决方案便是直接储存HTML再爬取。

import requests
from lxml import etree
import csv
#import time
from urllib.parse import unquote

file = open('juejin_online.csv','a+')
writer = csv.writer(file)
writer.writerow(['user_name','date','theme','title','link'])
headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3776.400 QQBrowser/10.6.4212.400'
    }
for i in range(10):
    url = "http://juejin.cn"
    html=requests.get(url=url,headers=headers).text
    print(html)
    doc = etree.HTML(html)
    lis = doc.xpath("/html/body/div/div/div/div/main/div/div/div/div/div/div/div/li")
    # all information are stored in the path above
    for li in lis:
        try:
            user_name = li.xpath('./div/div/a/@href')[0].split("/")[-1]
        except:
            continue
        else:
            date  = li.xpath('./div/div/div/text()')[0]
            theme = li.xpath('./div/div/div[2]/a/@href')
            theme_list = []
            for url_tag in theme:
                tag = url_tag.split("/")[-1]
                if "%" in tag:
                    tag = unquote(tag, encoding="utf-8")
                theme_list += [tag]
            theme = theme_list
            title = li.xpath('./div/div[2]/div/div/a/text()')[0]
            link = li.xpath('./div/div[2]/div/div/a/@href')[0]
            abstract = li.xpath('./div/div[2]/div/div[2]/a/div/text()')[0]
            try:
                pic = li.xpath('./div/div[2]/img/@src')[0]
            except:
                pic = "None"
            row = [user_name,date,theme,title,abstract,pic,link]
            writer.writerow(row)
            time.sleep(1)
file.close()

一个聪明的方法 -- 使用 puppeteer

使用 puppeteer的最大优势当然是对 js 加密实行降维打击,完全无视 js 加密手段,对于一些需要登录的应用,也可以模拟点击然后保存 cookie。而很多时候前端的加密是爬虫最难攻克的一部分。

pyppeteer.launch

可以传入一个字典来配置几个options

browser = await pyppeteer.launch({
    'headless': False, # 关闭无头模式
    'devtools': True, # 打开 chromium 的 devtools
    'executablePath': '你下载的Chromium.app/Contents/MacOS/Chromiu',
    'args': [ 
        '--disable-extensions',
        '--hide-scrollbars',
        '--disable-bundled-ppapi-flash',
        '--mute-audio',
        '--no-sandbox',
        '--disable-setuid-sandbox',
        '--disable-gpu',
    ],
    'dumpio': True,  
})

注入 js 脚本

可以通过page.evaluate形式。我们会看到这一步非常关键,因为 puppeteer会设置 window.navigator.webdriver为 true,告诉网站我是一个 webdriver 驱动的浏览器。有些网站会通过这个来判断对方是不是爬虫程序。

await page.evaluate("""
    () =>{
        Object.defineProperties(navigator,{
            webdriver:{
            get: () => false
            }
        })
    }
""")