Aug. 22nd 笔记 - 针对掘金官网的爬虫
这是我参与「第四届青训营 」笔记创作活动的的第5天
需求
我们小组的任务是仿掘金官网,必然的,涉及到内容问题。我们的策略是爬取一部分内容。由于我们都没有数据库基础,故先需爬取基础信息:文章标题,作者,主题,摘要,预览图等;然后依次放入网页之中。再选取一部分文章爬取文章内部内容。
一个传统的方法
最简单的,也是我最早想到的,就是传统的读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
}
})
}
""")