爬取今日头条历史图集将信息保存到MongDB,并且下载图片到本地
Posted scorpionspace
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了爬取今日头条历史图集将信息保存到MongDB,并且下载图片到本地相关的知识,希望对你有一定的参考价值。
写在前面:学习<崔庆才_Python3爬虫入门到精通课程视频>动手写的小项目。
(一) 分析页面
访问今日头条页面(https://www.toutiao.com/)在输入框中输入要搜索的关键字,搜索出的页面点击图集。要爬取的就是这里的所有图集。
查看页面的URL可以发现这是一个POST请求,然后我们就检查页面找到POST请求包,进行分析。
这个就是POST请求服务器返回的response
这是一个JSON格式的数据,复制下来放在解析器中查看。(使用jsonView)
可以看到data字段中的aritical_url与要请求的页面url相同,那么只要抓取到这个json数据通过处理就可以获取当前搜索页面的所有要访问的url。
在搜索页面滑动鼠标时,浏览器向服务器发送了多个request请求,用来加载之后的图集。所通过修改offset值就可以获取之后的图集信息。
(二)过程分析
首先要有一个初始的url作为入口,通过这个url来获取更多的url。这个url就是第一页搜索页的url,可以使用requests库模拟post请求,将参数添加到请求体,并且通过修改请求体中的offset值来获取下一个要爬取的页面。
def get_response(url,offset): header = {‘User-Agent‘: ‘Mozilla/5.0 (X11;Ubuntu;Linux x86_64; rv:52.0) Gecko/20100101 Firefox/52.0‘} data = { ‘offset‘:offset, ‘format‘:‘json‘, ‘keyword‘:‘历史‘, ‘autoload‘:‘true‘, ‘count‘:‘20‘, ‘cur_tab‘:‘3‘, ‘from‘:‘gallery‘, } response = requests.get(url,headers=header,params=data) response.encoding = ‘utf-8‘ try: if response.status_code == 200: html = response.text return html return None except RequestException: print(‘请求页面出错!‘) return None url = ‘https://www.toutiao.com/search_content/‘ for offset in range(0,121,20): html = get_response(url,str(offset))
然后通过response返回的json数据找出之后要爬取的每个图集的url。
def get_data(dic): if ‘data‘ in dic.keys(): for item in dic[‘data‘]: yield item[‘article_url‘]
通过分析每个图集页面发现,每个图集页面的图片是一个轮播图,但是在一个Ajax请求中有所有图面的url。
选择使用正则将所有的url提取出来。并以字典形式返回。
def handle_detail_html(html,url): from bs4 import BeautifulSoup import re from urllib.parse import urljoin soup = BeautifulSoup(html,‘lxml‘) title_text = soup.find(‘title‘).get_text() pattern = re.compile(‘gallery: JSON.parse((.*?)),‘) result = re.findall(pattern, html) pattern = re.compile("(w{19,23})", re.S) result_end = re.findall(pattern, result[0]) img_url = [] url_header_1 = ‘http://p3.pstatp.com/origin/pgc-image/‘ url_header_2 = ‘http://p3.pstatp.com/origin/‘ for each_url in set(result_end): url_1 = Accessable_download(urljoin(url_header_1,each_url)) url_2 = Accessable_download(urljoin(url_header_2,each_url)) if url_1: img_url.append(urljoin(url_header_1,each_url)) elif url_2: img_url.append(urljoin(url_header_2,each_url)) data_dic = { ‘url‘:url, ‘title‘:title_text, ‘img_list‘:img_url } return data_dic
最后就是连接数据库将信息保存到数据库中,并且将图片下载到本地。
下面是所有代码。
# coding=utf-8 ‘‘‘ 解析Ajax请求抓取今日头条图集并将信息存储到mongoDB并且下载图片到本地 ‘‘‘ import requests from requests.exceptions import RequestException # 返回搜索页的json数据 def get_response(url,offset): header = {‘User-Agent‘: ‘Mozilla/5.0 (X11;Ubuntu;Linux x86_64; rv:52.0) Gecko/20100101 Firefox/52.0‘} data = { ‘offset‘:offset, ‘format‘:‘json‘, ‘keyword‘:‘历史‘, ‘autoload‘:‘true‘, ‘count‘:‘20‘, ‘cur_tab‘:‘3‘, ‘from‘:‘gallery‘, } response = requests.get(url,headers=header,params=data) response.encoding = ‘utf-8‘ try: if response.status_code == 200: html = response.text return html return None except RequestException: print(‘请求页面出错!‘) return None # 将json数据转为python数据。 def loads_python(data): import os,json dic_data = json.loads(data) return dic_data # 将json中的每个图集的url找出来,将函数作为迭代器每次输出一个url。 def get_data(dic): if ‘data‘ in dic.keys(): for item in dic[‘data‘]: yield item[‘article_url‘] # 获取每个图集页面的html信息 def get_each_html(url): header = {‘User-Agent‘: ‘Mozilla/5.0 (X11;Ubuntu;Linux x86_64; rv:52.0) Gecko/20100101 Firefox/52.0‘} try: html = requests.get(url,headers=header) html.encoding = ‘utf-8‘ if html.status_code == 200: return html.text return None except RequestException: print(‘图集页面请求错误!‘) return None # 测试图片的url是否可以访问,如果可以就下在图片并保存在本地,然后返回可以访问的图片url。 def Accessable_download(url): import os from hashlib import md5 from urllib.request import urlretrieve print(‘正在尝试:‘,url) filepath = ‘{0}/{1}/{2}.{3}‘.format(os.getcwd(),‘今日头条可爱图集‘,md5(url.encode(‘utf-8‘)).hexdigest(),‘.jpg‘) if not os.path.exists(os.path.join(os.getcwd(),‘今日头条可爱图集‘)): os.mkdir(os.path.join(os.getcwd(),‘今日头条可爱图集‘)) header = {‘User-Agent‘: ‘Mozilla/5.0 (X11;Ubuntu;Linux x86_64; rv:52.0) Gecko/20100101 Firefox/52.0‘} try: response = requests.get(url,headers=header) if response.status_code == 200: urlretrieve(url,filepath) print(‘已下载完成:‘,url) return True return False except: return False # 提取每个图集页面的信息,标题,图片的url,返回字典格式的信息。 def handle_detail_html(html,url): from bs4 import BeautifulSoup import re from urllib.parse import urljoin soup = BeautifulSoup(html,‘lxml‘) title_text = soup.find(‘title‘).get_text() pattern = re.compile(‘gallery: JSON.parse((.*?)),‘) result = re.findall(pattern, html) pattern = re.compile("(w{19,23})", re.S) result_end = re.findall(pattern, result[0]) img_url = [] url_header_1 = ‘http://p3.pstatp.com/origin/pgc-image/‘ url_header_2 = ‘http://p3.pstatp.com/origin/‘ for each_url in set(result_end): url_1 = Accessable_download(urljoin(url_header_1,each_url)) url_2 = Accessable_download(urljoin(url_header_2,each_url)) if url_1: img_url.append(urljoin(url_header_1,each_url)) elif url_2: img_url.append(urljoin(url_header_2,each_url)) data_dic = { ‘url‘:url, ‘title‘:title_text, ‘img_list‘:img_url } return data_dic # 连接数据库,将爬取的信息存储到数据库 def mongo_db_conn(data): from pymongo import MongoClient try: conn = MongoClient(‘localhost‘,27017) db = conn.maoyan collection = db.img_data collection.insert_one(data) except: print(‘数据未写入‘) conn.close() # 主函数 def main(url): i = 0 for offset in range(0,121,20): html = get_response(url,str(offset)) dic_data = loads_python(html) for each_url in get_data(dic_data): i += 1 print(i, each_url) each_html = get_each_html(each_url) result = handle_detail_html(each_html,each_url) mongo_db_conn(result) print(i,result) if __name__ == ‘__main__‘: # 初始url url = ‘https://www.toutiao.com/search_content/‘ main(url)
以上是关于爬取今日头条历史图集将信息保存到MongDB,并且下载图片到本地的主要内容,如果未能解决你的问题,请参考以下文章