import os.path import random import time from multiprocessing import Pool import requests from lxml import etree headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36' } def get_img_src(page): ''' 抓取页面的图片的src :return: ''' for i in range(1, page+1): url = f'https://www.pkdoutu.com/photo/list/?page={i}' print(f'抓取{url}页数据') res = requests.get(url, headers=headers) res.encoding = res.apparent_encoding tree = etree.HTML(res.text) # 抓取图片 img_list = tree.xpath('//img[@referrerpolicy="no-referrer"]/@data-original') yield img_list def download_img(url): ''' 下载图片 :return: ''' time.sleep(random.uniform(0, 1)) img_res = requests.get(url, headers=headers) img_name = url.split('_')[-1] # 通过图片url进行拆分,拿到图片名称和后缀 path = 'img' # 判断路径是否存在,不存在则创建 if not os.path.exists(path): os.mkdir(path) # 写入到文件中 with open(os.path.join(path, img_name), 'wb') as f: f.write(img_res.content) if __name__ == '__main__': pool = Pool() # 通过生成器get_img_src返回图片列表 for url_list in get_img_src(2): for url in url_list: # 循环加入进程池 pool.apply_async(download_img, args=(url, )) pool.close() pool.join() print('over')
时间: 2024-04-25 10:27:17 浏览: 152
这是一个 Python 程序,主要用于从指定网站上抓取图片并下载到本地。程序使用了 multiprocessing 库中的进程池来实现多进程下载,加快了下载速度。其中,get_img_src 函数用于抓取指定页数的图片链接,download_img 函数用于下载指定链接的图片并保存到本地。主函数中使用了进程池来异步下载所有图片。
程序的具体实现步骤如下:
1. 导入所需的库,包括 os.path、random、time、multiprocessing 和 requests。
2. 定义抓取图片链接的函数 get_img_src,通过循环抓取指定页数的页面,并使用 lxml 库解析页面内容,抓取图片链接并返回。
3. 定义下载图片的函数 download_img,通过 requests 库下载指定链接的图片,并将图片保存到本地。
4. 在主函数中使用进程池来异步下载所有图片,具体实现如下:
a. 创建进程池 pool。
b. 通过生成器 get_img_src 返回图片链接列表,循环遍历每个链接。
c. 将 download_img 函数加入进程池,并传入图片链接作为参数。
d. 关闭进程池,并等待所有进程完成。
e. 打印下载完成提示信息。
该程序适用于需要大量下载图片的场景,可以通过调整进程池的大小和抓取的页数来适应不同的需求。
相关问题
优化这段代码:import requests import pandas as pd from bs4 import BeautifulSoup from lxml import etree import time import pymysql from sqlalchemy import create_engine from urllib.parse import urlencode # 编码 URL 字符串 start_time = time.time() #计算程序运行时间 def get_one_page(i): try: headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36' } paras = {'reportTime': '2023-03-23', #可以改报告日期,比如2018-6-30获得的就是该季度的信息 'pageNum': i #页码 } url = 'http://s.askci.com/stock/a/?' + urlencode(paras) response = requests.get(url,headers = headers) if response.status_code == 200: return response.text return None except RequestException: print('爬取失败') def parse_one_page(html): soup = BeautifulSoup(html,'lxml') content = soup.select('#myTable04')[0] #[0]将返回的list改为bs4类型 tbl = pd.read_html(content.prettify(),header = 0)[0] # prettify()优化代码,[0]从pd.read_html返回的list中提取出DataFrame tbl.rename(columns = {'序号':'serial_number', '股票代码':'stock_code', '股票简称':'stock_abbre', '公司名称':'company_name', '省份':'province', '城市':'city', '主营业务收入(201712)':'main_bussiness_income', '净利润(201712)':'net_profit', '员工人数':'employees', '上市日期':'listing_date', '招股书':'zhaogushu', '公司财报':'financial_report', '行业分类':'industry_classification', '产品类型':'industry_type', '主营业务':'main_business'},inplace = True) return tbl def generate_mysql(): conn = pymysql.connect( host='localhost', user='root', password='******', port=3306, charset = 'utf8', db = 'wade') cursor = conn.cursor() sql = 'CREATE TABLE IF NOT EXISTS listed_company (serial_number INT(20) NOT NULL,stock_code INT(20) ,stock_abbre VARCHAR(20) ,company_name VARCHAR(20) ,province VARCHAR(20) ,city VARCHAR(20) ,main_bussiness_income VARCHAR(20) ,net_profit VARCHAR(20) ,employees INT(20) ,listing_date DATETIME(0) ,zhaogushu VARCHAR(20) ,financial_report VARCHAR(20) , industry_classification VARCHAR(20) ,industry_type VARCHAR(100) ,main_business VARCHAR(200) ,PRIMARY KEY (serial_number))' cursor.execute(sql) conn.close() def write_to_sql(tbl, db = 'wade'): engine = create_engine('mysql+pymysql://root:******@localhost:3306/{0}?charset=utf8'.format(db)) try: tbl.to_sql('listed_company2',con = engine,if_exists='append',index=False) # append表示在原有表基础上增加,但该表要有表头 except Exception as e: print(e) def main(page): generate_mysql() for i in range(1,page): html = get_one_page(i) tbl = parse_one_page(html) write_to_sql(tbl) # # 单进程 if __name__ == '__main__': main(178) endtime = time.time()-start_time print('程序运行了%.2f秒' %endtime) # 多进程 from multiprocessing import Pool if __name__ == '__main__': pool = Pool(4) pool.map(main, [i for i in range(1,178)]) #共有178页 emdtime = time.time()-start_time print('程序运行了%.2f秒' %(time.time()-start_time))
这段代码已经很简洁了,但是可以通过以下方式进行优化:
1. 导入模块时可以将相同的模块放在一起,如将requests和pandas放在一起,将BeautifulSoup和lxml放在一起。
2. 导入模块时可以只导入需要的部分,如只导入urlencode函数。
3. 可以将函数或代码段封装成函数或类,使代码结构更清晰。
阅读全文