标签:ssi title ade tps innerhtml var proc pen asc
Ajax简介:
var xmlhttp; if (windows.XMLHttpRequest) { // code for IE7+, Firefox, Chrome, Opera, Safari xmlhttp =new XMLHttpRequest(); } else {// code for IE6, IE5 xmlhttp =new ActiveXObject("Microsoft.XMLHTTP"); } xmlhttp.open("POST","/ajax/",true); xmlhttp.send();
JavaScript 对 Ajax 最底层的实现,实际上就是新建了 XMLHttpRequest 对象,然后调用 onreadystatechange 属性设置了监听,然后调用 open()和 send ()方法向某个链接(也就是服务器)送了请求。用 Python 实现请求发送之后,可以得到响应结果,但这里请求的发送变成 JavaScript 来完成。由于设置了监听,所以当服务器返回响应时, onreadystatechange 对应的方法便会被触发,然后在这个方法里面解析响应内容即可。
解析内容
得到响应之后,onreadystatechange 属性对应的方法便会被触发,此时利用 xmlhttp 的 responseText 属性便可取到响应内容。类似于 Python 中利用 requests 向服务器发起请求,然后得到响应的过程。那么返回内容可能是 HTML,可能是 JSON,接下来只需要在方法中用 JavaScript 进一步处理即可。如:如果是 JSON 的话,可以进行解析和转化
一、Ajax分析方法
二、Ajax 结果提取
这个内容是 JSON 格式,浏览器开发者工具自动做了解析以方便我们查看。最关键的两部分信息就是 cardlistlnfo 和 cards:cardlistlnfo包含一个比较重要的信息 total,其实是微博的总数量,可以根据这个数字来估算分页数;cards 是一个列表,它包含 10 个元素。
from urllib.parse import urlencode import requests base_url = ‘https://m.weibo.cn/api/container/getlndex?‘ headers = { ‘Host‘: ‘m.weibo.cn‘, ‘Referer‘: ‘https://m.weibo.cn/u/2830678474‘, ‘User-Agent‘: ‘Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36‘, ‘X-Requested-With‘: ‘XMLHttpRequest‘, } def get_page(page): params = { ‘type‘: ‘uid‘, ‘value‘: ‘2830678474‘, ‘containerid‘: ‘1076032830678474‘, ‘page‘: page } url = base_url + urlencode(params) try: response = requests.get(url, headers=headers) if response.status_code == 200: return response.json() except requests.ConnectionError as e: print( ‘Error‘ , e.args) 也可:
from pyquery import PyQuery as pq import requests def getPage(page): url = ‘https://m.weibo.cn/api/container/getIndex?‘#在怎么来?分析Ajax请求 hd = {"User-Agent": ‘Mozilla‘} # 模仿浏览器 params = {‘type‘: ‘uid‘, ‘value‘: ‘2830678474‘, ‘containerid‘: ‘1076032830678474‘, ‘page‘: page} # 作为参数增加到url中去 try: response = requests.get(url, headers=headers, params=params) response.raise_for_status() return response.json() # 解析为JSON返回 --snip--
首先,定义 base_url 来表示请求的 URL 的前半部分。然后,构造参数字典,其中 type、value、containerid 是固定参数, page 是可变参数。调用 urlencode()方法将参数转化为 -- URL的 GET 请求参数,类似于 type=uid&value=2830678474&containerid=1076032830678474&page=2 这样的形式。base_url 与参数拼合形成一个新的 URL。判断响应的状态码,如果是 200 ,则直接调用 json()方法将内容解析为JSON 返回,否则不返回任何信息。如果出现异常,则捕获并输出其异常信息。
from pyquery import PyQuery as pq def parse_page(json): if json: items = json.get(‘data‘).get(‘cards‘) for item in items: item = item.get(‘mblog‘) if item == None: #注意:如果不添加返回None,可能因为有部分无返回值导致报错 continue weibo = {} weibo[‘id‘] = item.get(‘id‘) weibo[‘text‘] = pq(item.get(‘text‘)).text() weibo[‘attitudes‘] = item.get(‘attitudes_count‘) weibo[‘comments‘] = item.get(‘comments_count‘) weibo[‘reposts‘] = item.get(‘reposts_count‘) yield weibo
借助 pyquery 将正文中的 HTML签去掉。
遍历 page,将提取到的结果输出:
if __name__ == ‘__main__‘: for page in range(1,11): json = get_page(page) results = parse_page(json) for result in results: print(result)
from pymongo import MongoClient client = MongoClient() db = client[‘weibo‘] collection =db[‘weibo‘] def save_to_mongo(result): if collection.insert(result): print(‘Save to mongo‘)
三、分析 Ajax爬取今日头条街拍美图
import requests from urllib.parse import urlencode def get_page(offset): params = { ‘offset‘: offset, ‘format‘: ‘json‘, ‘keyword‘: ‘街拍‘, ‘autoload‘: ‘true‘, ‘count‘: ‘20‘, ‘cur_tab‘: ‘1‘, ‘from‘: ‘search_tab‘ } base_url = ‘https://www.toutiao.com/search_content/?‘ url = base_url + urlencode(params) try: resp = requests.get(url) if codes.ok == resp.status_code: return resp.json() except requests.ConnectionError: return None
这里用 urlencode()方法构造请求的 GET 参数,然后用 requests 请求这个链接,如果返回状 态码为 200(ok),则调用 response 的 json()方法将结果转为 JSON 格式,然后返回。
再实现一个解析方法:提取每条数据的 image_list 字段中的每一张图片链接,将图片链接和图片所属的标题一并返回,此时可以构造一个生成器。实现代码:
def get_images(json): if json.get(‘data‘): data = json.get(‘data‘) for item in data: if item.get(‘cell_type‘) is not None: continue title = item.get(‘title‘) images = item.get(‘image_list‘)for image in images: yield { ‘image‘: ‘https:‘ + image.get(‘url‘), ‘title‘: title }
接下来,实现一个保存图片的方法 save_image(),其中 item 是前面 get_images()方法返回的字典。首先根据 item 的 title 来创建文件夹,然后请求图片链接,获取图片的二进制数据,以二进制的形式写入文件。图片的名称可以使用其内容的 MD5 值,这样可以去除重复。代码:
import os from hashlib import md5 def save_image(item): img_path = ‘img‘ + os.path.sep + item.get(‘title‘) if not os.path.exists(img_path): os.makedirs(img_path) try: resp = requests.get(item.get(‘image‘)) if codes.ok == resp.status_code: file_path = img_path + os.path.sep + ‘{file_name}.{file_suffix}‘.format( file_name=md5(resp.content).hexdigest(), file_suffix=‘jpg‘) if not os.path.exists(file_path): with open(file_path, ‘wb‘) as f: f.write(resp.content) print(‘Downloaded image path is %s‘ % file_path) else: print(‘Already Downloaded‘, file_path) except requests.ConnectionError: print(‘Failed to Save Image,item %s‘ % item)
最后,只需要构造一个时fset 数组,遍历 offset ,提取图片链接,并将其下载:
from multiprocessing.pool import Pool def main(offset): json = get_page(offset) for item in get_images(json): print(item) save_image(item) GROUP_START = 0 GROUP_END = 7 if __name__ == ‘__main__‘: pool = Pool() groups = ([x * 20 for x in range(GROUP_START, GROUP_END + 1)]) pool.map(main, groups) pool.close() pool.join()
定义分页的起始页数和终止页数,分别为 GROUP_START和 GROUP_END ,利用了多线程的线程池,调用其 map()方法实现多线程下载。
标签:ssi title ade tps innerhtml var proc pen asc
原文地址:https://www.cnblogs.com/Mack-Yang/p/10167570.html