分析Ajax请求并抓取今日头条街拍美图
Posted 大神笨蛋
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了分析Ajax请求并抓取今日头条街拍美图相关的知识,希望对你有一定的参考价值。
通常我们从网页上爬取内容时,都是html代码,内容都已经写好了,直接从页面获取想要的信息即可,但是有的网页是通过ajax获取的数据,将ajax获取的数据通过json格式接受,然后展示在页面上的,也就是说,当我们打开一个页面时,首先请求的是他的html,然后HTML里面通过ajax获取后端数据,将数据以json格式展示在页面上。而近日头条就是这样。下面我们来看看。
我们打开链接:https://www.toutiao.com/search/?keyword=%E8%A1%97%E6%8B%8D,我们发现下面图片的链接和我们粘贴复制过来的地址不一样,说明最终请求的数据通过了ajax请求,数据格式发生了改变。我们查看网页源码,发现页面中没有关于我们在头条中看到的信息。
我们使用开发者选项F12,查看网页元素,发现请求头header中url与我们上面的连接不一样,增加了很多信息
我们查看请求的参数,发现有很多参数,这就是通过ajax真正访问的数据连接,我们需要的就是将https://www.toutiao.com/search_content/? + 加上下面的各种参数,就能查看到真正的数据源,
下面是请求网页源数据的代码:
#请求网页具体信息的函数 def get_page_index(offset,keyword): data={ \'offset\': offset, \'format\': \'json\', \'keyword\': keyword, \'autoload\': \'true\', \'count\': \'20\', \'cur_tab\':3, \'from\': \'search_tab\' } url=\'https://www.toutiao.com/search_content/?\'+urlencode(data) try: response = requests.get(url) if response.status_code == 200: return response.text return None except RequestException: return None
接下来应该解析网页中的数据:我们通过上面的请求方式获得的就是通过ajax请求返回的json数据,这些数据中我们需要每一条头条的链接,下面是解析函数:
def parse_page_index(html): data = json.loads(html)#将获取的ajax请求转换为json类型的数据 if data and \'data\' in data.keys(): for item in data.get(\'data\'): yield item.get(\'article_url\')#从json数据中获取名为artile_url的数据
接下来我们需要根据上面获得url请求每一条头条的内容:
def get_page_datail(url): headers = { \'User-Agent\': \'Mozilla/5.0(Macintosh;Intel Mac OS X 10_11_4)APPleWebKit/537.36(KHTML,like Gecko)Chrome/52.0.2743.116 Safari/537.36\' } try: response = requests.get(url,headers=headers) if response.status_code == 200: return response.text return None except RequestException: print(\'出现错误\') return None 注意:这里我们添加了请求头,添加请求头的原因是有的网页防止python爬取数据,我们可以通过伪代理或者添加header的方式来避免。
我们打开头条中的一条新闻,查看网页源代码,发现同样的我们看不到这条消息的数据,这些数据都包含在ajax请求返回的json数据中,我们需要从这些数据中提取
我们需要从网页中解析,下面是代码:
def pase_page_detail(html,url): soup=BeautifulSoup(html,\'lxml\')#使用beautifulsoup解析库来解析网页 title = soup.select(\'title\')[0].get_text()#直接可以通过标签名来获取头条的名称 print(title) images_pattern = re.compile(\'BASE_DATA.galleryInfo.*?gallery: JSON.parse\\("(.*?)"\\),\',re.S)#这里我们使用正则表达式获取我们想要图片的信息 result = re.search(images_pattern,html) if not result is None:#有的网页中不含有符合正则表达式的内容,我们直接将之过滤 data=json.loads(result.group(1).replace(\'\\\\\',\'\'))#将\\\\转义替换为空字符,同时将图片的信息转为json格式 if data and \'sub_images\'in data.keys():#判断数据不为空并且里面含有图片的信息 sub_images=data.get(\'sub_images\')#从json数据中获取名为sub_images的内容 images=[item.get(\'url\') for item in sub_images]#有的新闻中含有多张图片,我们将图片的链接存在数组中 for image in images: get_save_image(image)#请求图片的链接 return{ \'title\':title, \'url\':url, \'image\':images }#将我们得到的数据以数组格式返回,需要标题,url,还有图片链接
接下来我们需要将这些数据存放到MongoDB数据库,首先定义几个静态变量,新建一个config.py的python文件
MONGO_URL=\'localhost\'#数据库的ip就是localhost MONGO_DB=\'toutiao\'#存放的数据库名称 MONGO_TABLE=\'toutiao\'#存放的表名称
在写代码的python文件中定义数据库:
client = pymongo.MongoClient(MONGO_URL,connect=False)
db = client[MONGO_DB]
下面是存放到MongoDB的函数:
def save_to_mongo(result): if db[MONGO_TABLE].insert(result): print(\'存储到数据库成功\',result) return True return False
我们还有将图片保存在本地的函数,这里我直接上全部代码:
import json import os import re from hashlib import md5 from multiprocessing import Pool from urllib.parse import urlencode import pymongo from config import * client = pymongo.MongoClient(MONGO_URL,connect=False) db = client[MONGO_DB] from bs4 import BeautifulSoup from requests.exceptions import RequestException import requests #请求网页具体信息的函数 def get_page_index(offset,keyword): data={ \'offset\': offset, \'format\': \'json\', \'keyword\': keyword, \'autoload\': \'true\', \'count\': \'20\', \'cur_tab\':3, \'from\': \'search_tab\' } url=\'https://www.toutiao.com/search_content/?\'+urlencode(data) try: response = requests.get(url) if response.status_code == 200: return response.text return None except RequestException: return None def parse_page_index(html): data = json.loads(html)#将获取的ajax请求转换为json类型的数据 if data and \'data\' in data.keys(): for item in data.get(\'data\'): yield item.get(\'article_url\')#从json数据中获取名为artile_url的数据 def get_page_datail(url): headers = { \'User-Agent\': \'Mozilla/5.0(Macintosh;Intel Mac OS X 10_11_4)APPleWebKit/537.36(KHTML,like Gecko)Chrome/52.0.2743.116 Safari/537.36\' } try: response = requests.get(url,headers=headers) if response.status_code == 200: return response.text return None except RequestException: print(\'出现错误\') return None def pase_page_detail(html,url): soup=BeautifulSoup(html,\'lxml\')#使用beautifulsoup解析库来解析网页 title = soup.select(\'title\')[0].get_text()#直接可以通过标签名来获取头条的名称 print(title) images_pattern = re.compile(\'BASE_DATA.galleryInfo.*?gallery: JSON.parse\\("(.*?)"\\),\',re.S)#这里我们使用正则表达式获取我们想要图片的信息 result = re.search(images_pattern,html) if not result is None:#有的网页中不含有符合正则表达式的内容,我们直接将之过滤 data=json.loads(result.group(1).replace(\'\\\\\',\'\'))#将\\\\转义替换为空字符,同时将图片的信息转为json格式 if data and \'sub_images\'in data.keys():#判断数据不为空并且里面含有图片的信息 sub_images=data.get(\'sub_images\')#从json数据中获取名为sub_images的内容 images=[item.get(\'url\') for item in sub_images]#有的新闻中含有多张图片,我们将图片的链接存在数组中 for image in images: get_save_image(image)#请求图片的链接 return{ \'title\':title, \'url\':url, \'image\':images }#将我们得到的数据以数组格式返回,需要标题,url,还有图片链接 def save_to_mongo(result): if db[MONGO_TABLE].insert(result): print(\'存储到数据库成功\',result) return True return False def get_save_image(url): headers = { \'User-Agent\': \'Mozilla/5.0(Macintosh;Intel Mac OS X 10_11_4)APPleWebKit/537.36(KHTML,like Gecko)Chrome/52.0.2743.116 Safari/537.36\' } try: response = requests.get(url, headers=headers) if response.status_code == 200: save_image(response.content) return None except RequestException: print(\'请求图片界面错误\') return None def save_image(content): file_path=\'{0}/{1}.{2}\'.format(os.getcwd(),md5(content).hexdigest(),\'jpg\') if not os._exists(file_path): with open(file_path,\'wb\')as f: f.write(content) f.close() def main(offset): html=get_page_index(offset,\'街拍\') for url in parse_page_index(html): if url: html1=get_page_datail(url) if html: result=pase_page_detail(html1,url) if not result is None: save_to_mongo(result) if __name__ == \'__main__\': groups = [x*2 for x in range(GROUP_START,GROUP_END+1)] pool = Pool() pool.map(main,groups)
下面就是在MongoDB中的信息:
以上是关于分析Ajax请求并抓取今日头条街拍美图的主要内容,如果未能解决你的问题,请参考以下文章