Python爬取今日头条街拍美图

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

4 _( p  o: l0 M. b3 o$ X& |前言3 |  r, Z$ M- l6 d0 \

; n7 R4 j8 W' H9 D# `今日我们在 今日头条 网站上爬取 街拍美图1 V, H$ s, k4 R
今日头条 的数据都是用 Ajax 技术加载渲染完成,打开 今日头条 页面源码,连一根鸡毛都没有。
5 @  G: I; e4 M
5 d% {% ]0 a2 m# K7 B% H
Python爬取今日头条街拍美图-2.jpg

8 v) @- \' ?7 ^' x8 D2 l/ p( D7 _9 }2 `$ {/ E7 z9 r5 s
Python爬取今日头条街拍美图-3.jpg
' E+ [$ b$ C! t- N( K6 C: Q
假如今天生活欺骗了你,不要悲伤,不要哭泣,因为明天生活还会继续欺骗你。5 s% Y2 I3 [8 r4 Z  j8 S

; K+ s; ]: q( h; L' @/ I, Q3 N% ]; F& Y1 e+ R( P( R4 n$ L1 W
在我们爬虫界,按照 ‘可见即可爬’ 的原则, 所谓的 Ajax 就是 ’换一个页面‘ 爬取我们想要爬取的资源。: U$ M8 L9 e, @) v% b
换的那个页面,有时是 XHR 文件,有时是 HTML 文件。
5 k' a$ G5 w  @; {目标站点分析
( x" _# L" L/ X2 J# \F12审查页面元素。; e9 ]! ~0 Q1 |" X

$ G7 k: p9 }7 ~; t) v
Python爬取今日头条街拍美图-4.jpg

& ]3 {2 D' w: @1 k2 L5 J( x2 f
$ |* K. v5 u2 u- B8 u" G. t# s* ^
我们需要的资源全部在这个 URL 下。
9 p3 C4 X7 x# O! o9 R8 t获取 JSON 数据- m2 l7 w* m) a5 U
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()) y- O! ~$ j$ Z# a1 v2 H
转换映射对象或两个元素的元组,其可以包含的序列 str 或 bytes 对象。如若是字符串,则结果是由 ‘&’ 分隔的 key=value 的系列队。
解析 Json 数据0 J& ~3 g# F$ l6 d+ P
8 G8 L# b3 d; `4 j1 |
def getImage(json):% U5 O8 m6 a) S( d
- ]/ @6 ?. m' S5 ~5 |' `1 e
data = json.get('data')
2 f, p: o  }4 e& Q' T
, B2 T! d7 I, N3 U; X' ^ for item in data:
/ _6 c* V9 X' A: B3 G1 v! @, y+ J
title = item.get('title')
0 i1 L8 N7 M0 L' W; @, i8 v0 N9 D! \# p$ M5 q* G& _5 R; L
image_list = item.get('image_list')
2 S3 @9 p0 b: |1 {+ I5 \
7 t& M7 t% x# L( o% W  z if image_list:
7 l  Y; B. @: y, H' `( y' u( o8 N' j7 m. s5 U$ f. V
for item in image_list:
9 N4 E- U; H7 _) k  u
: P( M2 e* U4 m5 G. W( z+ T yield{
0 ]0 r) L0 T/ w! t/ O% `: x$ e
: W; Q& L$ {9 W; r 'title': title,
3 A& r9 @9 P$ P- H  s
  a% r$ n/ ]! s6 k 'image': item.get('url')
: t/ S( [1 i+ O' C  `; D1 e( s( K/ i; m' Y, Y; ^; e
}
6 a: c. S% e7 w" `. E保存图片6 r, o  x9 x! P. V8 R
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() 函数的一段话:
3 B6 I8 j0 t0 U8 k( M6 O  f
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.
大概意思是:
; {  [. [" w& b% p
到目前为止,hexdigest() 和 digest() 函数能满足你把一串字符串的组合物变成一段摘要的需要。
官方文档:
: q2 L; c! c( U6 L" _, v0 A
https://docs.python.org/2/library/hashlib.html
保存到 MongDB/ `& S: A% T5 w4 E" ^
def saveToMongo(item): if db[MONGO_TABLE].insert(item): print('储存到MONGODB成功', item) return False主函数和进程池
4 F' t( V! w% K1 B: ?; idef 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 了。8 V' x4 I7 @) S  u
总结- X6 @1 U9 O2 G& ]
主要关注如何下载和解析 Json数据。
$ m6 x) k+ V2 b) c# a) v公众号内输出 ‘崔佬视频’获取崔庆才大佬的《Python3WebSpider》全套视频。, f: z8 N4 ?, G
全码1 j! v& A  z" E+ Y) ^6 s
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() #主进程阻塞等待子进程的退出5 m: c& q% P2 D/ m: L
Python爬取今日头条街拍美图-5.jpg
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

11

金钱

0

收听

0

听众
性别

新手上路

金钱
11 元