Python爬取今日头条街拍美图

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

* Y, P2 {! i: V: V% m' A, \前言
- d$ h% A: Y% K- }
4 B; ]& ^* P9 L2 r$ z+ h4 A7 [今日我们在 今日头条 网站上爬取 街拍美图  _8 ]7 [1 v9 u+ K$ z  f7 O% P
今日头条 的数据都是用 Ajax 技术加载渲染完成,打开 今日头条 页面源码,连一根鸡毛都没有。
1 I/ t3 T2 }4 |  }, k6 M$ o2 b4 m" v
Python爬取今日头条街拍美图-2.jpg

7 X* I  e) J2 N. a" P  I% G& B( \2 ?' u3 X8 t( D) N+ x+ @
Python爬取今日头条街拍美图-3.jpg
/ n8 ~. p1 Y9 e
假如今天生活欺骗了你,不要悲伤,不要哭泣,因为明天生活还会继续欺骗你。
" i7 a3 z  f2 k3 |) q" m! S7 C1 m7 a: Z; h7 m% `2 z8 b7 t
3 }' z  Y, h( Y, f. v% [! h1 `
在我们爬虫界,按照 ‘可见即可爬’ 的原则, 所谓的 Ajax 就是 ’换一个页面‘ 爬取我们想要爬取的资源。; ~/ C/ V: W  f" p+ V* f2 m
换的那个页面,有时是 XHR 文件,有时是 HTML 文件。2 j# g# m* m- r/ r* l9 S% M6 J
目标站点分析
+ }% `9 f# c" t6 |% LF12审查页面元素。8 s7 ~8 v$ I; {! N5 \+ \
- h/ s- ?; Q) Z: [2 V
Python爬取今日头条街拍美图-4.jpg

- D1 h, ~4 D. o9 K; D0 {+ y" z8 n# t2 C1 \& `7 ?0 O
2 U! Y2 ]6 L- a; J
我们需要的资源全部在这个 URL 下。& @+ ^7 b" v; ~
获取 JSON 数据
3 K$ y) Z0 t8 u& @6 K+ A2 ^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()$ T. Z8 j' N# Q$ [
转换映射对象或两个元素的元组,其可以包含的序列 str 或 bytes 对象。如若是字符串,则结果是由 ‘&’ 分隔的 key=value 的系列队。
解析 Json 数据* [/ h/ x  Y5 K8 ]4 @) J6 u; e$ r

2 o: t2 ?1 s4 fdef getImage(json):( a1 O1 N5 v! Z/ J' u7 C

+ Q1 ~$ M7 }; d data = json.get('data')/ _# L, r6 E1 W# ^& O/ x1 |5 v. O

3 W/ r- P) @2 S- w6 ` for item in data:0 H+ l' O. }8 D7 E
6 u! e7 W% d5 W/ `8 p9 o0 Q
title = item.get('title')
: z5 v* L. S- H. [) s8 i
4 T$ b3 R5 q5 H* e. F+ F; {2 |* L image_list = item.get('image_list')
+ o. y( b, B  O; ]+ {7 h* `7 u: J- A# ]% s" J
if image_list:
0 w' C: S! k$ q0 M) C( |* V$ E' P1 \1 \# w  M7 o- H8 C
for item in image_list:
$ ^7 X/ X2 v( x0 Z: w4 ~; D$ b2 B- J/ F  q- g7 k$ ?7 h
yield{; ~- n0 D% }5 h' S3 R) `
( R3 l* U; s. o2 k  `/ [' _- o3 ?
'title': title,
4 U2 M8 q+ A$ a  G8 l* U# @% |% F3 H
'image': item.get('url')
! o2 h0 N# N5 C" `6 Q- u- Z. _0 o7 t0 F' z& o
}
  j4 L3 @$ T$ C: y2 d/ A" V- h. c5 {保存图片
' E5 |: S9 S, s- H( d9 ^% |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)在官方文档中描述 hexdigest() 函数的一段话:
2 y" g/ \0 r1 R. ?4 h: n$ h3 w
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.
大概意思是:
$ `; a0 ]8 Z1 R
到目前为止,hexdigest() 和 digest() 函数能满足你把一串字符串的组合物变成一段摘要的需要。
官方文档:2 v& [6 H- C  M! B6 p
https://docs.python.org/2/library/hashlib.html
保存到 MongDB3 u" C+ Z, w9 @# x! g# M9 U: Y
def saveToMongo(item): if db[MONGO_TABLE].insert(item): print('储存到MONGODB成功', item) return False主函数和进程池  {! o5 v, F7 v) O( ^
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 了。  p1 `+ O/ F$ d& l* c2 x6 i
总结# Z+ ?8 I! H% _* L5 F8 x
主要关注如何下载和解析 Json数据。
" O/ O* U/ N& m4 _- C' Q公众号内输出 ‘崔佬视频’获取崔庆才大佬的《Python3WebSpider》全套视频。
  q0 }3 j6 I: g; \全码
* y& S/ X/ u+ Timport 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() #主进程阻塞等待子进程的退出5 K  m" Y# z# j5 F! S
Python爬取今日头条街拍美图-5.jpg
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

11

金钱

0

收听

0

听众
性别

新手上路

金钱
11 元