15-分析Ajax请求并抓取今日头条街拍美图
流程框架:
抓取索引页内容:利用requests请求目标站点,得到索引网页HTML代码,返回结果。
抓取详情页内容:解析返回结果,得到详情页的链接,并进一步抓取详情页的信息。
下载图片与保存数据库:将图片下载到本地,并把页面信息及图片URL保存至MongoDB。
开启循环及多线程:对多页内容遍历,开启多线程提高抓取速度。
jiepai_picture.py
'''有些网页直接请求得到的HTML代码,并没有包括在浏览器中直接看到的内容,因为一些信息通过Ajax加载、通过JS渲染生成的,此时要分析网页请求。
本次用到的工具:
网络库:requests、解析库:beautifulsoup和正则表达式、存储数据库:mongoDB、pymongo库。
目标站点分析:
'''
from urllib.parse import urlencode
import requests
from requests.exceptions import RequestException
import json
from bs4 import BeautifulSoup
import re import pymongo
import sys
sys.path.append('D://ASoft/Python/PycharmProjects/pachong/15-分析Ajax请求并抓取今日头条街拍美图') #将自己写的config.py的路径加入到系统路径中以便导入。
from config import *
client = pymongo.MongoClient(MONGO_URL,connect=False) #生成一个Mongo客户端,多进程时候connect=False,每个进程启动时才连接
db = client[MONGO_DB] #定义一个DB import os
from hashlib import md5
from multiprocessing import Pool #引入进程池开启多进程
from json.decoder import JSONDecodeError '''抓取索引页内容'''
def get_page_index(offset,keyword): #使offset和keyword变成可变参数传递进来
#得到网页请求的参数,参数见图1,注意:抓取的是“图集”标题页的内容
data = {
'offset': offset,
'format': 'json',
'keyword': keyword,
'autoload': 'true',
'count': '20',
'cur_tab': '3',
'from': 'gallery' #此属性要加上,否则可能会不会返回标签“图集”的url
# 'pd':''
}
#将字典对象转换为url的请求参数,是urlib库提供的一种编码方法
url = 'https://www.toutiao.com/search_content/?' + urlencode(data) #链接见图2
try:
#利用requests请求这个url
response = requests.get(url)
if response.status_code == 200:
return response.text
else:
return None
except RequestException:
print('请求索引页出错')
return None '''解析索引页信息'''
def parse_page_index(html):
try:
data = json.loads(html) #生成一个json对象。
if data and 'data' in data.keys():
for item in data.get('data'):
yield item.get('article_url') #生成器
except JSONDecodeError:
pass '''得到详情页详细信息'''
def get_page_detail(url):
headers = {
# 'User-Agent': 'Mozilla/4.0(compatible;MSIE 5.5;Windows NT)' #这个user-agent可以,有的user-agent可能会导致爬取到的源码不全。
# 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.67 Safari/537.36'
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko'
}
try:
#利用requests请求这个url,注意此处直接传入url来请求网页内容由于反爬机制可能会得不到网页内容,所以要requests.get方法要加入headers参数。
response = requests.get(url=url,headers=headers)
if response.status_code == 200:
return response.text
else:
return None
except RequestException:
print('请求详情页出错')
return None '''解析详情页信息:根据想要得到的信息,在爬取到的网页源码中搜索想要的信息,找到信息的标签位置,然后利用选择器或正则表达式解析。'''
def parse_page_detail(html,url):
soup = BeautifulSoup(html,'lxml') #由于图片链接信息在原始的网页源代码中可以找到,见图3,所以用Beautiful库解析,以lxml方式解析html
try:
title = soup.select('title')[0].get_text() #得到图片的名称
except IndexError:
print('title获取失败',url)
# images_pattern = re.compile('var gallery = (.*?);', re.S) # 利用正则表达式解析图片链接地址
images_pattern = re.compile('JSON.parse("(.*?)"),', re.S)
# print(html)
result = re.search(images_pattern,html)
if not result:
images_pattern = re.compile('JSON.parse("(.*?)"),', re.S)
result = re.search(images_pattern,html)
if result:
data = json.loads(result.group(1)) #得到包含url的字典
if data and 'sub_images' in data.keys():
sub_images = data.get('sub_images') #得到一个列表,分析得知,列表中包含很多个集合,每个集合中包含一个键为url值为图片链接的键值对。
images = [item.get('url') for item in sub_images] #包含网页街拍中一个组图中每张图片的链接
#下载图片
for image in images:
download_image(image)
#返回图片包含图片名称和链接的字典
return {
'title':title,
'url':url,
'images':images
} #定义一个存储到MONGODB的方法
def save_to_mongo(result):
if db[MONGO_TABLE].insert(result): #如果存储成功
print('存储到MongoDB成功',result)
return True
return False #将图片存储下来
def download_image(url):
print('正在下载',url)
try:
response = requests.get(url)
print('---------')
if response.status_code == 200:
save_image(response.content) #response.content:返回二进制。response.text:返回正常网页源码结果。
return None
except RequestException:
print('请求图片出错',url)
return None #存储为图片
def save_image(content):
#文件路径包括三部分:路径、文件名、后缀。os.getcwd():当前项目的路径。md5(content).hexdigest():防止文件重复,如果图片内容相同则文件名相同。
file_path = '{0}/{1}.{2}'.format(os.getcwd(),md5(content).hexdigest(),'jpg')
if not os.path.exists(file_path):
with open(file_path,'wb') as f:
f.write(content)
f.close() def main(offset):
#得到索引页信息
html_index = get_page_index(offset,KEYWORD)
for url in parse_page_index(html_index): #url是每个详情页的url
# 得到详细页信息
html_detail = get_page_detail(url)
if html_detail:
result = parse_page_detail(html_detail,url) #得到解析后的title,url,images_url
if result:
save_to_mongo(result) #将得到的信息存储到数据库 if __name__ == '__main__':
# main()
#抓取其他索引页
groups = [x * 20 for x in range(GROUP_START,GROUP_END + 1)]
pool = Pool() #声明一个进程池
pool.map(main,groups) config.py
'''把得到的信息存储到MONGODB中。配置信息放到配置文件中。'''
MONGO_URL = 'localhost'
MONGO_DB = 'toutiao'
MONGO_TABLE = 'toutiao' GROUP_START = 1
GROUP_END = 20 KEYWORD = '街拍'
程序执行可能有一些问题,尚待更正。
15-分析Ajax请求并抓取今日头条街拍美图的更多相关文章
- 分析Ajax请求并抓取今日头条街拍美图
项目说明 本项目以今日头条为例,通过分析Ajax请求来抓取网页数据. 有些网页请求得到的HTML代码里面并没有我们在浏览器中看到的内容.这是因为这些信息是通过Ajax加载并且通过JavaScript渲 ...
- 2.分析Ajax请求并抓取今日头条街拍美图
import requests from urllib.parse import urlencode # 引入异常类 from requests.exceptions import RequestEx ...
- 分析 ajax 请求并抓取今日头条街拍美图
首先分析街拍图集的网页请求头部: 在 preview 选项卡我们可以找到 json 文件,分析 data 选项,找到我们要找到的图集地址 article_url: 选中其中一张图片,分析 json 请 ...
- python爬虫知识点总结(十)分析Ajax请求并抓取今日头条街拍美图
一.流程框架
- Python爬虫系列-分析Ajax请求并抓取今日头条街拍图片
1.抓取索引页内容 利用requests请求目标站点,得到索引网页HTML代码,返回结果. 2.抓取详情页内容 解析返回结果,得到详情页的链接,并进一步抓取详情页的信息. 3.下载图片与保存数据库 将 ...
- 【Python爬虫案例学习】分析Ajax请求并抓取今日头条街拍图片
1.抓取索引页内容 利用requests请求目标站点,得到索引网页HTML代码,返回结果. from urllib.parse import urlencode from requests.excep ...
- python爬虫之分析Ajax请求抓取抓取今日头条街拍美图(七)
python爬虫之分析Ajax请求抓取抓取今日头条街拍美图 一.分析网站 1.进入浏览器,搜索今日头条,在搜索栏搜索街拍,然后选择图集这一栏. 2.按F12打开开发者工具,刷新网页,这时网页回弹到综合 ...
- Python Spider 抓取今日头条街拍美图
""" 抓取今日头条街拍美图 """ import os import time import requests from hashlib ...
- 爬虫(八):分析Ajax请求抓取今日头条街拍美图
(1):分析网页 分析ajax的请求网址,和需要的参数.通过不断向下拉动滚动条,发现请求的参数中offset一直在变化,所以每次请求通过offset来控制新的ajax请求. (2)上代码 a.通过aj ...
随机推荐
- Selenium Webdriver 中的 executeScript 使用方法
1.使用executeScript 返回一个WebElement . 下例中我们将一个浏览器中的JavaScript 对象返回到客户端(C#,JAVA,Python等). IWebElement el ...
- 介绍一个比较了各种浏览器对于HTML5 等标准支持程度的网站
可以选择浏览器种类,版本,比较的功能 网站地址:https://caniuse.com/#comparison
- LeetCode算法题-Plus One(Java实现)
这是悦乐书的第156次更新,第158篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第15题(顺位题号是66).给定一个非空数字数组来表示一个非负整数,并给其加1.该数组已 ...
- Java JDK与JRE
JDK与JRE JDK(Java Development Kit):Java开发工具包.包含JRE中的所有内容,以及用于开发小应用程序和应用程序的编译器和调试器等工具. JRE(Java Runtim ...
- 自定义Chrome浏览器
一.全局 自用备份,窗体透明化.要添加对应网站的窗体class到对应的位置 /*主页背景*/ /*https://images.cnblogs.com/cnblogs_com/AardWolf/135 ...
- 【夯实Ruby基础】Ruby快速入门
本文地址: http://www.cnblogs.com/aiweixiao/p/6664301.html 文档提纲 扫描关注微信公众号 1.Ruby安装 1.1)[安装Ruby] Linux/Uni ...
- nodejs websocket
<script src="https://cdn.socket.io/socket.io-1.4.5.js"></script> <script ty ...
- React项目中那些奇怪的写法
1.在一个React组件里看到一个奇怪的写法: const {matchs} = this.props.matchs; 原来,是解构赋值,虽然听说过,但是看起来有点奇怪 下面做个实验: <scr ...
- 新手PHP连接MySQL数据库出问题(Warning: mysqli_connect(): (HY000/1045): Access denied for user 'root'@'localhost' (using password: YES))
我用的环境是wampServer集成的软件包 在php连接MySQL数据库的时候老是出现这个问题Warning: mysqli_connect(): (HY000/1045): Access deni ...
- 【转】APK反编译
学习和开发Android应用有一段时间了,今天写一篇博客总结一下Android的apk文件反编译.我们知道,Android应用开发完成之后,我们最终都会将应用打包成一个apk文件,然后让用户通过手机或 ...