下面的分析相当于一个框架,搞懂之后,对于类似的文字爬取,我们也可以实现。就算不能使用Ajax方法,我们也能够使用相同思想去爬取我们想要的数据。
豆瓣电影排行榜分析
首先我们打开网页的审查元素,选中Network==》XHR==》电影相关信息网页文件
筛选并比较以下数据(三个文件数据)
请求地址
1Request URL:https://movie.douban.com/j/search_subjects?type=movie&tag=%E7%83%AD%E9%97%A8&sort=recommend&page_limit=20&page_start=0 2 3Request URL:https://movie.douban.com/j/search_subjects?type=movie&tag=%E7%83%AD%E9%97%A8&sort=recommend&page_limit=20&page_start=20 4 5Request URL:https://movie.douban.com/j/search_subjects?type=movie&tag=%E7%83%AD%E9%97%A8&sort=recommend&page_limit=20&page_start=40
查询参数
1type:movie 2tag:热门 3sort:recommend 4page_limit:20 5page_start:0 6 7type:movie 8tag:热门 9sort:recommend 10page_limit:20 11page_start:20 12 13type:movie 14tag:热门 15sort:recommend 16page_limit:20 17page_start:40
请求报头
1Host:movie.douban.com 2Referer:https://movie.douban.com/explore 3User-Agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36 4X-Requested-With:XMLHttpRequest
通过比较请求地址和查询参数,得出
1请求地址 = baseurl+type+tag+sort+page_limit+page_start 2 3baseurl:https://movie.douban.com/j/search_subjects? 4type:固定为movie 5tag:关键字,需要将utf-8转换为urlencode 6sort:固定为recommend 7page_limit:表示一页显示的电影数量,固定20 8page_start:表示电影页数,从0开始,20为公差的递增函数
由此我们获取到了我们需要的数据,可以将爬虫分为三步
- 获取网页json格式代码
- 从代码中获取电影名和电影海报图片链接
- 将获得的图片命名为电影名
流程
准备工作
在函数外部定义伪装的请求报头
1headers={ 2 'Host': 'movie.douban.com', 3 'Referer': 'https://movie.douban.com/explore', 4 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36', 5 'X-Requested-With': 'XMLHttpRequest' 6}
获取json格式代码
1def get_page(page): 2 #请求参数 3 params={ 4 'type': 'movie', 5 'tag': '奥特曼', 6 'sort': 'recommend', 7 'page_limit': '20', 8 'page_start': page, 9 } 10 #基本网页链接 11 base_url = 'https://movie.douban.com/j/search_subjects?' 12 #将基本网页链接与请求参数结合在一起 13 url = base_url + urlencode(params) 14 try: 15 #获取网页代码 16 resp = requests.get(url, headers=headers) 17 print(url) 18 #返回json数据格式代码 19 if 200 == resp.status_code: 20 print(resp.json()) 21 return resp.json() 22 except requests.ConnectionError: 23 return None
筛选数据
通过观察电影列表代码文件的preview,进行数据筛选

1def get_image(json): 2 if(json.get('subjects')): 3 data=json.get('subjects') 4 for item in data: 5 title=item.get('title') 6 imageurl=item.get('cover') 7 #返回"信息"字典 8 yield { 9 'title':title, 10 'images':imageurl, 11 }
存储图片文件
1def save_page(item): 2 #文件夹名称 3 file_name = '奥特曼电影大全' 4 if not os.path.exists(file_name): 5 os.makedirs(file_name) 6 7 #获取图片链接 8 response=requests.get(item.get('images')) 9 #储存图片文件 10 if response.status_code==200: 11 file_path = file_name + os.path.sep + item.get('title') + '.jpg' 12 with open(file_path, 'wb') as f: 13 f.write(response.content)
多线程处理
1def main(page): 2 json = get_page(page) 3 for item in get_image(json): 4 print(item) 5 save_page(item) 6 7if __name__ == '__main__': 8 pool = Pool() 9 pool.map(main, [i for i in range(0, 200, 20)]) 10 pool.close() 11 pool.join()

总代码
1import requests 2from urllib.parse import urlencode 3import os 4from multiprocessing.pool import Pool 5 6headers={ 7 'Host': 'movie.douban.com', 8 'Referer': 'https://movie.douban.com/explore', 9 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36', 10 'X-Requested-With': 'XMLHttpRequest' 11} 12 13def get_page(page): 14 #请求参数 15 params={ 16 'type': 'movie', 17 'tag': '奥特曼', 18 'sort': 'recommend', 19 'page_limit': '20', 20 'page_start': page, 21 } 22 #基本网页链接 23 base_url = 'https://movie.douban.com/j/search_subjects?' 24 #将基本网页链接与请求参数结合在一起 25 url = base_url + urlencode(params) 26 try: 27 #获取网页代码 28 resp = requests.get(url, headers=headers) 29 print(url) 30 #返回json数据格式代码 31 if 200 == resp.status_code: 32 print(resp.json()) 33 return resp.json() 34 except requests.ConnectionError: 35 return None 36 37def get_image(json): 38 if(json.get('subjects')): 39 data=json.get('subjects') 40 for item in data: 41 title=item.get('title') 42 imageurl=item.get('cover') 43 #返回"信息"字典 44 yield { 45 'title':title, 46 'images':imageurl, 47 } 48 49def save_page(item): 50 #文件夹名称 51 file_name = '奥特曼电影大全' 52 if not os.path.exists(file_name): 53 os.makedirs(file_name) 54 55 #获取图片链接 56 response=requests.get(item.get('images')) 57 #储存图片文件 58 if response.status_code==200: 59 file_path = file_name + os.path.sep + item.get('title') + '.jpg' 60 with open(file_path, 'wb') as f: 61 f.write(response.content) 62 63def main(page): 64 json = get_page(page) 65 for item in get_image(json): 66 print(item) 67 save_page(item) 68 69if __name__ == '__main__': 70 pool = Pool() 71 pool.map(main, [i for i in range(0, 200, 20)]) 72 pool.close() 73 pool.join()
本来是准备使用https://movie.douban.com/tag/#/ 不过在后面,刷新网页时,总是出现服务器问题。不过下面的代码还是可以用。
1import requests 2from urllib.parse import urlencode 3import os 4from hashlib import md5 5from multiprocessing.pool import Pool 6 7headers={ 8 'Host': 'movie.douban.com', 9 'Referer': 'https://movie.douban.com/tag/', 10 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36', 11} 12 13def get_page(page): 14 params={ 15 'sort':'U', 16 'range':'0,10', 17 'tags':'奥特曼', 18 'start': page, 19 } 20 base_url = 'https://movie.douban.com/j/new_search_subjects?' 21 url = base_url + urlencode(params) 22 try: 23 resp = requests.get(url, headers=headers) 24 print(url) 25 if 200 == resp.status_code: 26 print(resp.json()) 27 return resp.json() 28 except requests.ConnectionError: 29 return None 30 31def get_image(json): 32 if(json.get('data')): 33 data=json.get('data') 34 for item in data: 35 title=item.get('title') 36 imageurl=item.get('cover') 37 yield { 38 'title':title, 39 'images':imageurl, 40 } 41 42def save_page(item): 43 file_name='奥特曼大全'+os.path.sep+item.get('title') 44 if not os.path.exists(file_name): 45 os.makedirs(file_name) 46 try: 47 response=requests.get(item.get('images')) 48 if response.status_code==200: 49 file_path = '{0}/{1}.{2}'.format(file_name, md5(response.content).hexdigest(), 'jpg') 50 if not os.path.exists(file_path): 51 with open(file_path, 'wb') as f: 52 f.write(response.content) 53 else: 54 print('Already Downloaded', file_path) 55 except requests.ConnectionError: 56 print('Failed to Save Image') 57 58def main(page): 59 json = get_page(page) 60 for item in get_image(json): 61 print(item) 62 save_page(item) 63 64if __name__ == '__main__': 65 pool = Pool() 66 pool.map(main, [i for i in range(0, 200, 20)]) 67 pool.close() 68 pool.join()