Python爬取今日头条街拍美图

[复制链接]
查看9898 | 回复0 | 2021-10-14 03:23:16 | 显示全部楼层 |阅读模式
Python爬取今日头条街拍美图-1.jpg
0 @; K  Y) P/ Y4 j  c2 @
前言( j; c  J: p0 a; G9 G+ S
* A# J+ {) l% a- c9 \9 T
今日我们在 今日头条 网站上爬取 街拍美图
" H( I9 S. _$ I: Q! [$ Q3 M2 I今日头条 的数据都是用 Ajax 技术加载渲染完成,打开 今日头条 页面源码,连一根鸡毛都没有。
7 ?1 N) W, p- o; i" @/ Y5 }  F2 |# ], ~! s
Python爬取今日头条街拍美图-2.jpg

, F  p, b' Q5 S+ B2 U2 z0 {# P6 p) u+ \# s
Python爬取今日头条街拍美图-3.jpg
2 [, p; S' F2 b. V
假如今天生活欺骗了你,不要悲伤,不要哭泣,因为明天生活还会继续欺骗你。
0 W7 `' Y" H) R" D/ Q0 U/ U  z" m& C' J" j: g

# ?! g1 I1 a2 d3 o8 O在我们爬虫界,按照 ‘可见即可爬’ 的原则, 所谓的 Ajax 就是 ’换一个页面‘ 爬取我们想要爬取的资源。
' w, Y3 L. u  f$ ^: D: d/ v  m换的那个页面,有时是 XHR 文件,有时是 HTML 文件。
4 n; t* p+ q8 r% f8 c目标站点分析
0 e0 f8 g( C& Z0 j8 p' ?F12审查页面元素。) c- ^: X1 x, {7 L1 o  u

1 m* S2 r. K3 F* L# B& i: ^& |6 M
Python爬取今日头条街拍美图-4.jpg

+ R/ I" k7 ]0 O2 w* h- [% `, i( ~$ Y$ D4 v

8 d" p/ ~0 d( u我们需要的资源全部在这个 URL 下。
1 U# Q; g" o6 |+ s/ x1 f+ F获取 JSON 数据
3 d2 G; s1 q& f4 M$ C" |8 o1 S) W& ?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 ""urllib.parse.urlencode()' S% H! O9 g) n9 X
转换映射对象或两个元素的元组,其可以包含的序列 str 或 bytes 对象。如若是字符串,则结果是由 ‘&’ 分隔的 key=value 的系列队。
解析 Json 数据
. X3 K9 C6 I+ p* T- R1 M4 ]$ t  _
- \  C' Y  Q3 V6 }& ]3 ndef getImage(json):6 A; L& F9 N; w. P% ]2 Y
8 P3 E; u; @& [+ w1 k- w2 _
data = json.get('data')
" I' o5 `2 }+ k
/ W' G3 _0 S* J6 B' q for item in data:' @9 G. P4 Z" v" s  S

+ f# d* n6 Y1 \, p8 p title = item.get('title')
8 S4 P. h" @! v  r) t( H& \9 A; O8 s6 P9 X3 \
image_list = item.get('image_list')- q! w3 i$ n  Z) v

) s. y; T, u2 R9 a' @% `& k2 x if image_list:5 w5 t6 S5 a; u$ |

& e7 S& y: H& F4 a% l' r& V for item in image_list:& G/ c2 [8 ?2 s! Z

; D( z, U% Q! `$ i3 j7 y7 A3 _! a yield{3 o5 p5 D' ~$ J" {  U

; M1 S8 H- |/ Z1 q 'title': title,
  W  q# E& }) B( B1 h
: I+ c. I6 y" L. c/ j 'image': item.get('url')
9 P& _0 E2 b" q9 f' ?; a. f1 h' h- Z# P* Z" v+ F. ?3 r: I" x; Q
}# A$ A4 B. j; Y! V1 k% Z1 P3 n
保存图片
4 `! \6 U4 d4 d0 d) Ydef 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() 函数的一段话:+ X. K$ ?% n2 O- N% ]! J
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.
大概意思是:
; T- E5 A: k$ @/ J
到目前为止,hexdigest() 和 digest() 函数能满足你把一串字符串的组合物变成一段摘要的需要。
官方文档:
( k- v# ^$ k2 q( Q4 A' T
https://docs.python.org/2/library/hashlib.html
保存到 MongDB
/ D3 q6 i# I, v6 l& U  Bdef saveToMongo(item): if db[MONGO_TABLE].insert(item): print('储存到MONGODB成功', item) return False主函数和进程池
$ \3 d6 ~$ v( v) \; K- s0 [def 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 了。
/ z8 U: c9 y5 H, g" F1 b总结5 k5 S3 x% n& \4 m8 c
主要关注如何下载和解析 Json数据。5 B/ W) _& Q6 q8 l5 ?6 e7 A
公众号内输出 ‘崔佬视频’获取崔庆才大佬的《Python3WebSpider》全套视频。. h: E/ y/ W( w0 y* S2 O7 w! u  c
全码$ `, p& v6 V- R/ g+ ^9 i
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  V( z8 Z" `) G7 ^
Python爬取今日头条街拍美图-5.jpg
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

11

金钱

0

收听

0

听众
性别

新手上路

金钱
11 元