Python爬取今日头条街拍美图

[复制链接]
查看9887 | 回复0 | 2021-10-14 03:23:16 | 显示全部楼层 |阅读模式
Python爬取今日头条街拍美图-1.jpg

5 U' X5 U- Y# \9 k0 X前言
$ c* g! m/ N3 b- D+ [
& s: o! S9 c. P. }8 U9 q今日我们在 今日头条 网站上爬取 街拍美图1 t! O9 Y; R8 S- q8 c4 B5 `
今日头条 的数据都是用 Ajax 技术加载渲染完成,打开 今日头条 页面源码,连一根鸡毛都没有。
3 P% T) v6 ^7 s. q. f/ c4 G* D8 {# Q, I* [- m( D3 B& [+ H, \* s
Python爬取今日头条街拍美图-2.jpg

# C+ t! B+ N8 P5 e: w2 ~8 X
6 U' O) S7 f$ Y. W' x
Python爬取今日头条街拍美图-3.jpg

* K% Z$ g7 q2 ^* J, D/ l3 V1 m假如今天生活欺骗了你,不要悲伤,不要哭泣,因为明天生活还会继续欺骗你。
0 g/ z/ K4 M2 Q0 f' b. q  `) C- R2 o( x8 H/ {5 g
6 k2 F9 ^1 n) r8 |# p+ D
在我们爬虫界,按照 ‘可见即可爬’ 的原则, 所谓的 Ajax 就是 ’换一个页面‘ 爬取我们想要爬取的资源。8 I, p; V7 l; K
换的那个页面,有时是 XHR 文件,有时是 HTML 文件。
* T( k6 H( A! ]/ T  ]9 X. s( z目标站点分析& j  b$ c) \( {4 A: i
F12审查页面元素。
1 u% G2 ~3 y. H3 H
7 N) o1 y, e2 W5 B7 G* ~
Python爬取今日头条街拍美图-4.jpg

: ?8 u9 s, R& U, {; t" K3 S1 E$ Z+ I! ^) F6 |$ c) \, N
8 {% d# p! {; H4 k, o
我们需要的资源全部在这个 URL 下。; Q6 r" P5 G" D4 P
获取 JSON 数据
; T' l$ |0 `  x2 x, X6 E: Z+ X1 Odef getPage(offset): params = { 'offset': offset, 'format': 'json', 'keyword': '街拍', 'autoload': 'true', 'count': '20', 'cur_tab': '3', 'from': 'gallery', } url = 'https://www.toutiao.com/search_content/?' + urlencode(params) try: r = requests.get(url) if r.status_code == 200: return r.json() except requests.ConnectionError: return ""urllib.parse.urlencode()
& n9 v5 i5 W+ s! x* E5 I$ M& |! T
转换映射对象或两个元素的元组,其可以包含的序列 str 或 bytes 对象。如若是字符串,则结果是由 ‘&’ 分隔的 key=value 的系列队。
解析 Json 数据
0 D0 P8 u2 t2 L5 d% F- P8 B) [7 B; Y7 X( U  l. G4 i
def getImage(json):5 a' u$ C) \, \- z& m9 m
8 i& M% [& T- Y7 O
data = json.get('data'); F  E5 n4 e0 _

7 p; t" m& w& Z+ Q" G! H for item in data:
9 k) ^$ f0 u/ w+ G# G: M2 p) A$ l# F# n/ L* ?+ d/ X5 S
title = item.get('title')
4 F% e# V! v: f/ L
) J  \8 d  s9 {5 B, Z% Z image_list = item.get('image_list')$ ?* M' q& B% @7 B% ]

7 e- h/ m7 [( w0 j1 h9 h% I/ J if image_list:" u& U5 w4 e7 k( z3 A; x
" K' |7 i9 T) `; e3 p4 X
for item in image_list:
/ k% U9 C4 b2 ]# Z8 E
- i( d! O* A" {3 l- ~. U0 d yield{5 A0 j, M' `6 x: J9 {. u

  J8 X$ {% Q9 ]' L6 Y 'title': title,7 k) G" C6 }2 ^' u; D

- D3 F' r) m5 ^% U: t" a. s1 ^ 'image': item.get('url')
! ^. {: D2 b; ]3 R& o/ x  J4 Q: n: k& C" U( \3 L
}
5 C; s! k- y/ K" P保存图片
+ T( B) H2 n% f2 ?, e* bdef saveImage(item): img_path = 'img' + os.path.sep + item.get('title') if not os.path.exists(img_path): os.makedirs(img_path) local_image_url = item.get('image') new_image_url = local_image_url.replace('list', 'large') r = requests.get('http:' + new_image_url) if r.status_code == 200: file_path = img_path + os.path.sep +'{0}.{1}'.format(md5(r.content).hexdigest(), 'jpg') if not os.path.exists(file_path): with open(file_path, 'wb') as f: f.write(r.content)在官方文档中描述 hexdigest() 函数的一段话:
; p1 J& o9 b* `* @( v! |* Y
At any point you can ask it for the digest of the concatenation of the strings fed to it so far using the digest() or hexdigest() methods.
大概意思是:7 m4 X8 V- |2 n5 b( A* ^0 v
到目前为止,hexdigest() 和 digest() 函数能满足你把一串字符串的组合物变成一段摘要的需要。
官方文档:; k8 D2 H1 E+ _5 `( c
https://docs.python.org/2/library/hashlib.html
保存到 MongDB
4 v* j3 D! l5 a+ l) Z+ `def saveToMongo(item): if db[MONGO_TABLE].insert(item): print('储存到MONGODB成功', item) return False主函数和进程池
& ~. @/ b/ ]. b. g9 T1 k( Rdef main(offset): json = getPage(offset) for item in getImage(json): saveImage(item) saveToMongo(item)if __name__ == '__main__': pool = Pool() groups = [x * 20 for x in range(2)] #爬取五页 pool.map(main, groups) pool.close() #关闭进程池(pool),使其不在接受新的任务 pool.join() #主进程阻塞等待子进程的退出对 pool 对象调用 join() 方法会让主进程等待所有子进程自行完毕,调用 join() 之前必须先调用 close() ,让其不再接受新的 Process 了。$ U2 u+ J( d9 b( W- \
总结% V& H4 w( Z7 W2 z8 L; P- o% @$ ?
主要关注如何下载和解析 Json数据。2 S+ M/ J) Y( q
公众号内输出 ‘崔佬视频’获取崔庆才大佬的《Python3WebSpider》全套视频。
1 u- a. U6 Z3 r. i! e/ Q全码9 r+ c" U, k! b! W9 W# M/ z3 ?; T, }& w
import requestsfrom urllib.parse import urlencodeimport osfrom hashlib import md5import pymongofrom multiprocessing.pool import PoolMONGO_URL = 'localhost'MONGO_DB = 'toutiao'MONGO_TABLE = 'toutiao' #数据集合Collectionclient = pymongo.MongoClient(MONGO_URL) # MongoClient 对象,并且指定连接的 URL 地址db = client[MONGO_DB] #要创建的数据库名def getPage(offset): params = { 'offset': offset, 'format': 'json', 'keyword': '街拍', 'autoload': 'true', 'count': '20', 'cur_tab': '3', 'from': 'gallery', } url = 'https://www.toutiao.com/search_content/?' + urlencode(params) try: r = requests.get(url) if r.status_code == 200: return r.json() except requests.ConnectionError: return ""def getImage(json): data = json.get('data') for item in data: title = item.get('title') image_list = item.get('image_list') if image_list: for item in image_list: yield{ 'title': title, 'image': item.get('url') }def saveImage(item): img_path = 'img' + os.path.sep + item.get('title') if not os.path.exists(img_path): os.makedirs(img_path) local_image_url = item.get('image') new_image_url = local_image_url.replace('list', 'large') r = requests.get('http:' + new_image_url) if r.status_code == 200: file_path = img_path + os.path.sep +'{0}.{1}'.format(md5(r.content).hexdigest(), 'jpg') if not os.path.exists(file_path): with open(file_path, 'wb') as f: f.write(r.content)def saveToMongo(item): if db[MONGO_TABLE].insert(item): print('储存到MONGODB成功', item) return Falsedef main(offset): json = getPage(offset) for item in getImage(json): saveImage(item) saveToMongo(item)if __name__ == '__main__': pool = Pool() groups = [x * 20 for x in range(2)] #爬取五页 pool.map(main, groups) pool.close() #关闭进程池(pool),使其不在接受新的任务 pool.join() #主进程阻塞等待子进程的退出* S+ Z# D) J; K
Python爬取今日头条街拍美图-5.jpg
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

11

金钱

0

收听

0

听众
性别

新手上路

金钱
11 元