import json import os from urllib.parse import urlencode #将字符串以URL格式编码 import pymongo import requests from bs4 import BeautifulSoup from requests.exceptions import ConnectionError import re from multiprocessing import Pool from hashlib import md5 from json.decoder import JSONDecodeError from config import * #multiprocessing包是Python中的多进程管理包 #urlencode()函数原理就是首先把中文字符转换为十六进制,然后在每个字符前面加一个标识符%。 #urldecode()函数与urlencode()函数原理相反,用于解码已编码的 URL 字符串,其原理就是把十六进制字符串转换为中文字符 """ 连接数据库 client = pymongo.MongoClient(MONGO_URL) db = client[MONGO_DB] #或者 db = client.example """ client = pymongo.MongoClient(MONGO_URL, connect=False) #connect=False db = client[MONGO_DB] """ 1、抓取索引页,构造Ajax请求 (提取当前页面所有的Article_url,查看) 2、抓取详情页 根据Ajax返回的json,解析文章列表 3、下载图片 保存到数据库 4、开启循环 多线程 改变offset """ def get_page_index(offset, keyword): #构造索引页 #post 请求参数, """ offset: 0 开始位置 format: json keyword: 街拍 搜索的关键字 autoload: true count: 20 当前页数目 cur_tab: 1 当前页 """ data = { 'autoload': 'true', 'count': 20, 'cur_tab': 1, 'format': 'json', 'keyword': keyword, 'offset': offset, } #w网页请求连接:Request URL: https://www.toutiao.com/search_content/?offset=0&format=json&keyword=%E8%A1%97%E6%8B%8D&autoload=true&count=20&cur_tab=1&from=search_tab params = urlencode(data) #输出结果:autoload=true&count=20&cur_tab=3&format=json&keyword=keyword&offset=offset base = 'http://www.toutiao.com/search_content/' url = base + '?' + params #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 ConnectionError: print('Error occurred') return None """ response返回: content中间存的是字节码,而text中存的是Beautifulsoup根据猜测的编码方式将content内容编码成字符串 """ def download_image(url): #下载图片 print('正在下载:', url) try: response = requests.get(url) if response.status_code == 200: save_image(response.content) return None except ConnectionError: return None def save_image(content): #b保存图片 file_path = '{0}/{1}.{2}'.format(os.getcwd(), md5(content).hexdigest(), 'jpg') #路径 文件名 后缀 md5(content).hexdigest()为防止下载重复 #os.getcwd() 方法用于返回当前工作目录。 #生成16进制的md5 hashlib.md5.digest() 加密后的结果用二进制表示,如果你要看内容可以使用print hashlib.md5(str).digest() #MD5(content) print(file_path) if not os.path.exists(file_path):#如果路径不存在 就存储 with open(file_path, 'wb') as f: #二进制 f.write(content) f.close() def parse_page_index(text): #获取网页 try: data = json.loads(text) """ data.keys(): dict_keys(['count', 'action_label', 'return_count', 'has_more', 'page_id', 'request_id', 'cur_tab', 'tab', 'offset', 'action_label_web', 'show_tabs', 'data', 'message', 'action_label_pgc']) """ if data and 'data' in data.keys(): #判断data中有data属性 和data是否为空 for item in data.get('data'): #遍历 每一条数据的article_url 提取 yield item.get('article_url') except JSONDecodeError: pass def get_page_detail(url): #获取网页细节 try: response = requests.get(url) if response.status_code == 200: return response.text return None except ConnectionError: print('Error occurred') return None def parse_page_detail(html, url): #解析网页 soup = BeautifulSoup(html, 'lxml') result = soup.select('title') title = result[0].get_text() if result else '' images_pattern = re.compile('gallery: JSON.parse\("(.*)"\)', re.S) result = re.search(images_pattern, html) if result: data = json.loads(result.group(1).replace('\\', ''))#转换成json对象 if data and 'sub_images' in data.keys(): sub_images = data.get('sub_images')#含有字典的列表 images = [item.get('url') for item in sub_images] for image in images: download_image(image) return { 'title': title, 'url': url, 'images': images } def save_to_mongo(result): #保存到数据库 if db[MONGO_TABLE].insert(result): print('Successfully Saved to Mongo', result) return True return False def main(offset): text = get_page_index(offset, KEYWORD) urls = parse_page_index(text) for url in urls: print(url) html = get_page_detail(url) #组图html result = parse_page_detail(html, url) if result: save_to_mongo(result) if __name__ == '__main__': pool = Pool() #声明进程池 groups = ([x * 20 for x in range(GROUP_START, GROUP_END + 1)]) #更改offset值 实现多页爬取 print(groups) pool.map(main, groups) pool.close() pool.join()
多线程 爬今日touti图片
最新推荐文章于 2024-10-01 20:02:09 发布