一个信息采集器(小爬虫)的实例和优化

爬虫第一步,网络信息采集 自己爬虫经验总结 项目地址网络信息采集在编写爬虫之前可能需要先了解和搜集网站信息robots.txt Robots协议(也称为爬虫协议、机器人协议等)的全称是“网络爬虫排除标准”(Robots Exclusion Protocol),网站通过Robots协议告诉搜索引擎哪些页面可以抓取,哪些页面不能抓取。一般的网站都会有这个文件。可以大致了解这个网站存在哪些限制 下面是知乎的robots.tx 阅读详情

【题记】最近在“猪八戒网”上看到一个任务,采集“袖扣网”的所有商品的编号、价格和图片, 图片保存在以商品编号为名称的文件夹下,编号、价格信息写入excel中保存。


目标网站数据量: 商品列表页面559个(截止2011-12-22),每页商品20个,每个商品平均4个图片。总共需要网络下载量(559(商品列表页面--parent)+559*20(具体商品页面--leaf)+559*20*4=56459次);

测试下载一个商品页面平均需要14s,单线程情况下预计完成任务52小时,自己使用了100个线程,完成任务耗时8小时。


下面先贴出源代码:供大家来批判,同时提供好的改进优化意见。


DataCollector001.java

//=============================================

package org.study.app.crawler;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.Vector;
import java.util.concurrent.CountDownLatch;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;

import org.apache.log4j.Logger;
import org.study.util.excel.ExcelUtil;
import org.study.util.net.URLGetter;

/**
 * 采集袖口网的所有:编号、批发价格已经所有袖口图片。
 * 
 * @author Walker Jong
 * @version 1.0, 2011-12-22
 */
public class DataCollector001 extends Thread {
    public static final int THREAD_NUM = 100;
    private static final String leafToken = "'http://www.xiukouwang.com/product";
    private static final String parentToken = "http://www.xiukouwang.com/gallery--b%2C_ANY__t%2C_ANY_-10--";
    private static final String[] infoKeys = new String[] { "编 号:</span>",
            "class=\"price1\">", "http://www.biilii.com/pic/products/" };
    private static final String endToken = "<";
    private static final String otherToken = "grid.html";
    private static final String defaultDir = "F:/data";

    private static final List<URL> toDo = new Vector<URL>(800);
    private static final Set<URL> finished = new HashSet<URL>(1000);
    private static List<Object[]> infos = new ArrayList<Object[]>(13000);

    private static final Logger logger = Logger
            .getLogger(DataCollector001.class);

    private static final CountDownLatch cdl = new CountDownLatch(THREAD_NUM);

    /**
     * 处理父节点页面,负责处理页面信息和提取其他的父页面和叶子节点。
     * 
     * @param parent
     */
    public static void processParent(URL parent) {
        synchronized (finished) {
            if (finished.contains(parent)) {
                logger.debug("url [" + parent + "] has processed.");
                return;
            } else {
                logger.info("process parent url [" + parent + "]");
            }
        }

        final List<URL> leafs = new ArrayList<URL>();
        final Set<String> parents = new HashSet<String>();
        BufferedReader br = null;
        try {
            br = new BufferedReader(new InputStreamReader(parent.openStream(),
                    "UTF-8"));
            String str = null, urlStr = null;
            int index = -1, nextIndex = -1;
            boolean leafEnd = false, urlEnd = false;
            while ((str = br.readLine()) != null) {
                for (index = 0; index < str.length();) {
                    if (!leafEnd) {
                        // 提取叶子页面信息
                        index = str.indexOf(leafToken, index);
                        if (index != -1) {
                            nextIndex = str.indexOf("'",
                                    index + leafToken.length());
                            urlStr = str.substring(index + 1, nextIndex);
                            leafs.add(new URL(urlStr));
                            logger.info("add leaf url[" + urlStr + "]");
                            index = nextIndex + 1;
                        } else {
                            if (leafs.size() > 0) {
                                index = str.indexOf("pagernum", index);
                                if (index != -1) {
                                    leafEnd = true;
                                } else {
                                    break;
                                }
                            } else {
                                break;
                            }
                        }
                    } else {
                        // 提取父页面信息
                        index = str.indexOf(parentToken, index);
                        if (index != -1) {
                            nextIndex = str.indexOf("\"",
                                    index + parentToken.length());
                            urlStr = str.substring(index, nextIndex);
                            if (urlStr.endsWith(otherToken)
                                    && !parents.contains(urlStr)) {
                                parents.add(urlStr);
                                logger.info("add parent url[" + urlStr + "]");
                            }
                            index = nextIndex + 1;
                        } else {
                            if (parents.size() > 0
                                    && str.indexOf("pagenum") != -1) {
                                urlEnd = true;
                            }
                            break;
                        }
                    }
                }// end of for
                if (urlEnd) {
                    break;
                }
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (br != null) {
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        // 标记该页面已经处理
        synchronized (finished) {
            finished.add(parent);
        }
        logger.info("leafs.size=" + leafs.size() + ", parents.size="+ parents.size());

        // 处理父页面
        for (String pStr : parents) {
            try {
                URL url = new URL(pStr);
                synchronized (toDo) {
                    toDo.add(url);
                }
            } catch (MalformedURLException e1) {
                logger.error(e1);
            }
        }

        // 处理叶子页面
        for (URL url : leafs) {
            processLeaf(url);
        }
    }

    /**
     * 采集叶子节点里的数据。
     */
    public static void processLeaf(URL leaf) {
        logger.info("process leaf url [" + leaf + "]");
        List<URL> picUrls = new ArrayList<URL>();
        String str = null, id = null, price = null, picUrl = null;
        BufferedReader br = null;
        try {
            br = new BufferedReader(new InputStreamReader(leaf.openStream(),
                    "UTF-8"));
            int index = -1, nextIndex = -1;
            boolean picExist = false, picEnd = false;
            while ((str = br.readLine()) != null) {
                for (index = 0; index < str.length();) {
                    if (id == null) {
                        index = str.indexOf(infoKeys[0]);
                        if (index != -1) {
                            index += infoKeys[0].length();
                            nextIndex = str.indexOf(endToken, index);
                            id = str.substring(index, nextIndex);
                            index = nextIndex + 1;
                        } else {
                            break;
                        }
                    }
                    if (price == null) {
                        index = str.indexOf(infoKeys[1], index);
                        if (index != -1) {
                            index += infoKeys[1].length();
                            nextIndex = str.indexOf(">", index);
                            if (nextIndex != -1) {
                                index = nextIndex + 1;
                            }
                            nextIndex = str.indexOf(endToken, index);
                            price = str.substring(index, nextIndex);
                            index = nextIndex + 1;
                        } else {
                            break;
                        }
                    }
                    if (picUrl == null) { // 提取图片信息
                        index = str.indexOf(infoKeys[2], index);
                        if (index != -1) {
                            nextIndex = str.indexOf("\"",
                                    index + infoKeys[2].length());
                            picUrl = str.substring(index, nextIndex);
                            picUrls.add(new URL(picUrl));
                            logger.info("picture url [" + picUrl + "]");
                            picUrl = null;
                            picExist = true;
                            index = nextIndex + 1;
                        } else {
                            if (picExist
                                    && str.indexOf("img src=", nextIndex + 1) != -1) {
                                picEnd = true;
                            }
                            break;
                        }
                    }
                }// end of for
                if (picEnd) {
                    Object[] objects = new Object[2];
                    objects[0] = id;
                    objects[1] = price;
                    synchronized (infos) {
                        infos.add(objects);
                    }
                    logger.info("id = " + id + ", price=" + price);
                    break;
                }
            }

        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (br != null) {
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        // 下载图片信息
        char postName = 'a';
        for (URL url : picUrls) {
            URLGetter.download(url, new File(defaultDir + "/" + id, id
                    + postName + ".jpg"));
            postName++;
        }
    }

    public static void saveDataToExcel() {
        File file = new File("data/袖扣编号价格表.xls");
        String sheetName = "袖扣编号价格表";
        String[] titleNames = new String[] { "编号", "价格" };
        try {
            ExcelUtil.write(file, sheetName, titleNames, infos);
        } catch (IOException e) {
            logger.error(e);
        }
    }

    public void run() {
        int counter = 3;
        while (true) {
            URL url = null;
            synchronized (toDo) {
                int size = toDo.size();
                if (size > 0) {
                    url = toDo.remove(size - 1);
                } else {
                    counter--;
                    if (counter <= 0) {
                        cdl.countDown();
                        break;
                    }

                    try {
                        toDo.wait(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
            if (url != null) {
                processParent(url);
            }
        }
    }

    public static void main(String[] args) {
        String parent = "http://www.xiukouwang.com/gallery--b%2C_ANY__t%2C_ANY_-10--1--grid.html";
        try {
            processParent(new URL(parent));
        } catch (MalformedURLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        DataCollector001 c = null;
        for (int i = 0; i < THREAD_NUM; i++) {
            c = new DataCollector001();
            c.start();
        }

        // 等待所有子线程完成后,写入数据
        try {
            cdl.await();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        saveDataToExcel();
    }
}





URLGetter.java

//==========================================

package org.study.util.net;

import java.io.*;
import java.net.*;
import org.apache.log4j.Logger;

public class URLGetter 
{
	private static final Logger logger = Logger.getLogger(URLGetter.class);
	
	private static final int BUFFER_SIZE = 2048;
	private static long defaultFileNo = 1;
	private static final String defaultPostName = "txt";

	/**
	 * 下载指定的url文件,保存成为给定的文件名。
	 * 
	 * @URL url 需要下载的url地址。
	 * @File file 指定下载文件的名称,也可以包含路径。
	 * @boolean override 指定当文件已经存在时,是否重写。
	 */
	public static void download(URL url, File file, boolean override)
	{
		if(file == null)
		{
			file = getFile(url);
		}

		File parent = file.getParentFile();
		if(parent != null && !parent.exists()){
			parent.mkdirs();
		}

		if(file.exists())
		{
			logger.info("file["+file+"] has existed.");
			if(!override)
			{
                return;
			}
			else
			{
				logger.info("overwrite the file["+file+"]");			
			}
		}
		
		BufferedInputStream bis = null;
		BufferedOutputStream bos = null;
		try {
			bis = new BufferedInputStream(url.openStream());
			bos = new BufferedOutputStream(new FileOutputStream(file));
			byte[] buffer = new byte[BUFFER_SIZE];
			int len = -1;
			while((len = bis.read(buffer)) != -1){
				bos.write(buffer, 0, len);
			}
			logger.info("finished download url["+url+"], file="+file);
		} catch (IOException e) {
			logger.error(e);
		}finally{
			if(bis != null){
				try {
					bis.close();
				} catch (IOException e) {
					logger.error(e);
				}
			}
			if(bos != null){
				try {
					bos.close();
				} catch (IOException e) {
					logger.error(e);
				}
			}
		}
	}
	
	/**
	 * 下载指定的url文件,保存成为给定的文件名。
	 * 遇到重名文件不重写。
	 * 
	 * @URL url 需要下载的url地址。
	 * @File file 指定下载文件的名称,也可以包含路径。
	 * @boolean override 指定当文件已经存在时,是否重写。
	 */
	public static void download(URL url, File file)
	{
		download(url, file, false);
	}

	/**
	 * 下载指定的url文件,文件名以url给定的path为准,若path中缺少文件名默认“数字.txt”;
	 * 遇到重名文件不重写。
	 * 
	 * @URL url 需要下载的url地址。
	 * @File file 指定下载文件的名称,也可以包含路径。
	 * @boolean override 指定当文件已经存在时,是否重写。
	 */
	public static void download(URL url)
	{
		download(url, getFile(url), false);
	}

	public static synchronized File getFile(URL url)
	{
		String path = url.getPath();
		logger.debug("path="+path+" isNull="+(path==null));
		if(path == null)
		{
			path = defaultFileNo+"."+defaultPostName;
		}
		else if(path.equals("") || path.endsWith("/"))
		{
            path = path+defaultFileNo+"."+defaultPostName;
		}			
		return new File(path);
	}

	public static void main(String[] args) 
	{
		try {
			URL url = new URL("http://www.baidu.com/");
			URLGetter.download(url, null, false);
		} catch (MalformedURLException e1) {
			logger.error(e1);
			return;
		}  
	}
}



ExcelUtil.java

//===========================================

package org.study.util.excel;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.List;

import org.apache.log4j.Logger;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;

public class ExcelUtil {
	private static final Logger logger = Logger.getLogger(ExcelUtil.class);
	
	public static void write(String[] titleNames, List<Object[]> data) throws IOException{
		write("data.xls", "", titleNames, data);
	}
	
	public static void write(String fileName, String sheetName,
			String[] titleNames, List<Object[]> data) throws IOException{
		write(new File(fileName), sheetName, titleNames, data);
	}
	public static void write(File file, String sheetName, String[] titleNames, List<Object[]> data) throws IOException{
		if(file == null){
			return;
		}
		File dir = file.getParentFile();
		if(dir != null){
			dir.mkdirs();
		}
		
		Workbook wb = new HSSFWorkbook();
		Sheet s = wb.createSheet(sheetName);
		for(int i=0; i<titleNames.length; i++){
			s.setColumnWidth(i, 5000);
		}		
		CreationHelper createHelper = wb.getCreationHelper();
		
		// create 2 fonts objects
		Font tf = wb.createFont();
		Font cf = wb.createFont();
		// Set title font and cell font 
		tf.setFontHeightInPoints((short)16);
		tf.setColor(IndexedColors.BLUE.getIndex());
		cf.setFontHeightInPoints((short) 12);
		cf.setColor(IndexedColors.BLACK.getIndex());
		cf.setBoldweight(Font.BOLDWEIGHT_NORMAL);
		
		
		// create title style and cell style
		CellStyle cs = wb.createCellStyle();
		CellStyle ts = wb.createCellStyle();
		DataFormat df = wb.createDataFormat();
		// Set the other cell style and formatting
		ts.setDataFormat(df.getFormat("text"));
		ts.setFont(tf);
		cs.setDataFormat(df.getFormat("text"));
		cs.setFont(cf);
		
		Row r = null;
		Cell c = null;
		//set title for all columns
		r = s.createRow(0);
		for(int i=0; i<titleNames.length; i++){
			c = r.createCell(i);
			c.setCellStyle(ts);
			c.setCellValue(createHelper.createRichTextString(titleNames[i]));
		}
		
		logger.debug("data size="+data.size());
		//create rows and cell, then fill data
		for(int i=1; i<=data.size(); i++){
			Object[] objects = (Object[])data.get(i-1);
			r = s.createRow(i);
			for(int j=0; j<objects.length; j++){
				c = r.createCell(j);
				c.setCellStyle(cs);
				c.setCellValue(createHelper.createRichTextString(objects[j].toString()));
			}
		}
		
		// save 
		OutputStream os = new FileOutputStream(file);
		wb.write(os);
		os.close();
	}
}



用到的jar包,包括commons-loggoing.jar, log4j.jar, poi.jar,都是apache的东西。 commons-logging、log4j都是用来记录日志的,poi是用来保存excel用到的组件。

下载地址:

commons-logging: http://commons.apache.org/logging/

log4j.jar:  http://logging.apache.org/log4j/

poi.jar: http://poi.apache.org/


自己觉得待改进的地方:

1、多线程的调度和任务分配、意见同步互斥。

2、已经下载链接的去重问题。

3、代码的设计模式,更加清晰易懂,可重用性。

希望有研究的人,给些意见和建议。


注:本文仅供学习研究使用,并无攻击和冒犯“袖扣网”之意,给贵网站带来不便,敬请谅解。


 

        
绿道 / 骑行道公开目录页爬虫实战:requests + BeautifulSoup + SQLite 构建路线数据采集系统 我长期专注 Python 爬虫工程化实战,主理专栏 👉 《Python爬虫实战》:从采集策略到反爬对抗,从数据清洗到分布式调度,持续输出可复用的方法论与可落地案例。内容主打一个“能跑、能用、能扩展”,让数据价值真正做到——抓得到、洗得净、用得上。 阅读详情

相关推荐

KALI虚拟机挂代理教程

需要你本地挂了代理,然后通过虚拟机连接本机代理端口,不说废话了,直接说怎么做了。 1.查看选项设置中自己的小飞机的本地端口是多少:(默认是1080) 2.本机win+r打开cmd,输入ipconfig查看本地ip,我的本地ip是192.168.0.107: 2.打开kali虚拟机,编辑ProxyChains配置文件: vi /etc/proxychains.conf 3.在文件末尾的ProxyList中添加物理机本地ip和1080端口作为代理地址: 4.保存并退出即可: esc :wq 回车 5.

qq_34853514的博客 3万+

EasyPOI导入验证功能

EasyPoi导入验证功能 来自: http://www.leftso.com/blog/326.html https://www.cnblogs.com/bigbigxiao/p/11897871.html 1.加入EasyPOI 的Jar包支持 多说两句,我刚开始测试的时候一直报ValidationException异常,然后加上 hibernate-validator就可以了 <!-- easypoi的支持 --> <dependency>

weixin_45624150的博客 6991

Human3.6M 数据集介绍及下载

360 万张 3D 人体姿势和对应图像11 名专业演员(6 男 5 女)7 个场景(讨论、吸烟、拍照以及打电话等等)

XavierJ的博客 3万+

easypoi 导出 备注异常的字体颜色为红色

结合以上核心代码可以实现如下最后一列备注为红色 只供参考。

aq_money的博客 1718

SLUB DEBUG 检测slab 内存泄漏

文章介绍如何定位linux 内核中slab 内存泄漏。

一叶知秋的博客 1491

在LangChain中使用DashVector进行高效向量检索

DashVector为需要处理高维向量数据的开发者提供了一种便捷且高效的解决方案。通过将其集成到LangChain生态系统中,您可以轻松实现复杂的语义搜索和数据分析功能。DashVector官方文档LangChain GitHub仓库有关DashVector的详细notebook示例。

sjufgwgfhoia的博客 455

POI设置单元格字体颜色等样式(踩坑记录)

最近项目使用POI按模板导出Excel,需要设置单元格的字体为红色,但只设置一部分或者某一个. 这里遇到一个容易踩坑的点,所以记录一下,希望能让更多的人少走弯路. 这里关键点有两步,也是容易踩坑的点: 1.克隆Style:新建的redCellStyle要从现有的cell拷贝cellStyle:redCellStyle.cloneStyleFrom(cell.getCellStyle()); 2.克隆Font:新建的redFont要从现有的cellStyle拷贝font:这个POI没有封装,只能手动拷贝。。。

天罡gg的专栏 1万+

「大模型学习」(14)Long Context之线性插值、NTK-aware、Yarn、LongRoPE

大语言模型长上下文扩展中的位置插值技术 摘要:为解决大语言模型(LLMs)在推理阶段扩展上下文窗口时的位置编码限制,研究人员开发了一系列位置插值技术。这些方法主要针对旋转位置编码(RoPE)机制,通过不同策略调整位置索引以适应超出训练长度的上下文。典型方法包括:基础位置插值(PI)均匀缩放位置索引;NTK-aware插值对不同频率维度差异化处理;NTK-by-parts插值根据波长分段调整;Yarn插值结合温度调节;以及LongRoPE采用非均匀插值策略。这些技术在不修改模型结构的前提下,通过调整位置编码的

qq_43044037的博客 1645

springmvc导出excel并弹出下载框

最近做grid列表相关数据导出到excel功能,根据自己选择的列导出成excel 并且下载到本地。废话不说 直接上关键代码: 需要引入相关的包: compile 'org.apache.poi:poi-ooxml:3.9'compile 'org.apache.poi:poi:3.9'compile 'org.apache.poi:poi-scratchpad:3.9'

学亮编程手记 1699

ICCV 2025 | 哈工大、清华等提出首个双曲学习框架:HLFormer,革新局部相关视频检索

离原点越远,代表的语义越具体(部分)。现有方法大多在传统的欧几里得空间中对视频和文本进行建模,但这往往会导致对视频内在层次结构的错误表示,从而影响检索的准确性。通过UMAP对学习到的帧嵌入进行可视化(如下图),可以观察到,来自同一时刻的视频帧在嵌入空间中聚集在一起,清晰地展示了模型对时序关系的捕捉能力。下图的双曲空间可视化进一步证实了模型的层次建模能力:离原点越近的点,代表的语义层级越高、粒度越粗糙,反之亦然。:既然文本查询描述的是视频的一部分,那么在几何表示上,文本的嵌入向量应该从属于视频的嵌入向量。

我爱计算机视觉 1083

MFC C++ 中实现跨平台(WindowsLinux)的远程桌面控制

**输入捕获**:在显示窗口中捕获鼠标/键盘事件(重写 `OnLButtonDown`、`OnMouseMove`、`OnKeyDown` 等),将事件坐标/键值通过网络发送到服务端。- **显示窗口**:使用 `CStatic` 或自定义 `CWnd` 派生类显示远程桌面图像(通过 `StretchDIBits` 绘制解压后的像素数据)。// 转换为相对坐标。- **Wayland 支持**:需使用 `libweston` 或 `xdg-desktop-portal`,较复杂,建议优先支持 X11。

寒寒豆豆软件公司的博客 155

POI 颜色Color

1. 颜色概述颜色Color是单元格的基本样式,单元格默认颜色为黑色 - 单元格边框颜色 - 单元格填充色 - 单元格字体颜色2. 预定自颜色POI中预定义了56种颜色,索引从0x8 - 0x40, 索引0x40定义一种默认颜色 - 黑色org.apache.poi.ss.usermodel.IndexedColors org.apache.poi.hssf.util.HSSFColor$

李平安 1万+

《YOLOv8-seg改进》专栏指导书册 &手把手创新教程

学姐带你学习YOLOv8,从入门到创新,轻轻松松搞定科研;1)手把手教你如何训练YOLOv8-seg;2)模型创新,提升分割性能;3)独家自研模块助力分割;

会AI的学姐 3813

2020-09-09

自学HTML的第二天 表单元素 css3层叠样式表 行内样式直接写在行里style=" " (修改麻烦不建议使用) 内部样式。在里面写。用选择器选用 外部样式。在单独的css文件夹写。然后用link引用

y3330138322的博客 432

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

easyPoi导出excel工具类和设置excel导出样式(边框,背景色,字体)

**使用方式** 1.使用时把样式工具类ExcelStyleUtil当做参数传递进去即可 ExportParams exportParams = new ExportParams(&amp;amp;quot;标题名称&amp;amp;quot;, &amp;amp;quot;sheet名称&amp;amp;quot;, ExcelType.XSSF); exportParams.

zhouqu3790的博客 4万+

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

Python爬虫小说采集程序

开发工具:python3.4 操作系统:win8 主要功能:去指定小说网页爬小说目录,按章节保存到本地,并将爬过的网页保存到本地配置文件。 被爬网站:http://www.22pq.com/ 小说名称:武道宗师 代码出处:本人亲自码的 import urllib.request import http.cookiejar import socket import time

cmdos的专栏 1626

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

python爬虫案例:获取商品信息并进行数据分析

众所周知,随着人们生活水平的提高,零食在人们生活中扮演的角色越来越重要。一些像“良平铺子”“三只松鼠”“百草味”这样的零食网店迅速进入人们的视野,并在零食市场中占了比重非常大的份额。   我个人也是一位零食爱好者,因此萌生出某些疑问,是否能寻得一个平衡,既让商家谋取最高利润,也能使顾客最划算,互惠互利。本文将通过对不同的零食店铺和商品的价格、销量等方面进行分析,引导商家合理地制定商品价格和运费,引导人们正确而合理地购买零食。 分析思路 利用python爬虫爬取淘宝商品信息,本文的爬取对象为“零食” 分.

xiongxiaoxuan的博客 4504

一个可以爬取小说的小爬虫 - 来自业余编程人的第一篇编程分享

内容提要 最近闲来无事,网上找了本小说,翻来覆去的终于找到一个还不错的小说,然而所下载的小说质量实在不讨喜,错误重复随处可见,网站广告也夹杂其中,遂产生了自己爬小说的念头。还好小说的网站都比较简单,基本没有什么反爬措施。期间遇到一个神奇的网站,小说内容是用JS格式化加载的。后来想了一个办法,遇到加载未完成,重新请求即可。 废话少说,我们来看代码。代码使用Python写的。 麻雀虽小,五脏俱全 整个...

unknown_world_now的博客 4324

【定制开发】【M9】Python爬虫 - 【1688】公开信息采集案例

一、背景: 一个做展会的小伙伴儿找到我,希望能帮他采集某一类目的1688厂家信息,然后邀请他们参加展会。 二、设计思路如下: 采用 Python3 语言编码 , 工具 PyCharm; 模仿真实用户登录1688,使用Selenium + Google Chrome + chromedriver.exe; 备注1:Google Chrome + chromedriver.exe版本对应参考链接:https://blog.csdn.net/lildkdkdkjf/article/details/1068

记录项目交付的日常 1389

Beats轻量级日志采集工具

Beats 平台集合了多种单一用途数据采集器。这些采集器安装后可用作轻量型代理,从成百上千或成千上万台机器向 Logstash 或 Elasticsearch 发送数据。常用的Beats有Filebeat(收集文件)、Metricbeat(收集服务、系统的指标数据)、Packetbeat(收集网络包)等。这里主要介绍Filebeat插件。 一、架构图 二、安装Filebeat 官网地址: htt...

******* ▄︻┻┳═一 ******* 3166

(二十二)日志采集框架Flume的介绍与案例

前言 在一个完整的大数据处理系统中,除了hdfs+mapreduce+hive组成分析系统的核心之外,还需要数据采集、结果数据导出、任务调度等不可或缺的辅助系统,而这些辅助工具在hadoop生态体系中都有便捷的开源框架 如图所示: 1.Flume介绍 1.1 概述 Flume是一个分布式、可靠、和高可用的海量日志采集、聚合和传输的系统。 Flume可以采集文件,socket数据包等各种形式源数据,又可以将采集到的数据输出到HDFS、hbase、hive、kafka等众多外部存储系统中

Ares_song的博客 868

分布式实现网络爬虫

笔者尝试由原本的一个普通的爬虫程序,修改成分布式爬虫,期间遇到一些问题,在此作此博客,分享收获。 爬虫的思路: 目标网页 网页解析 目标提取 对目标进行下载 实现普通的爬虫根据这个思路,利用正则即可完成 将其改为分布式爬虫的思路是:将解析、访问网页的部分用 函数进行编写,之后逐次调用,调用的过程中就可以用到了分布式,多线程啦!! import requests import re import...

weixin_42326545的博客 741

python通过条码(商品名)查询商品信息(完整版)

前言 录入商品数据太痛苦了,但是又不能不录,所以这时候需要写一个python脚本来完成,仅供参考。 开始 可能会给一个exec表格给你,或者一个文件夹条码图片给你.....要你根据条码(商品名)找到对应的图片,保存起来。 项目代码地址 1.通过百度爬取商品图片(免费接口) # 通过配合商品名通过百度找图片 def getBaiDu(shop_id, search_title): baidu_url ="http://image.baidu.com/search/flip?tn=ba

echo_Ae的博客 4433

@RequestBody, @ResponseBody 注解详解

引言: 接上一篇文章讲述处理@RequestMapping的方法参数绑定之后,详细介绍下@RequestBody、@ResponseBody的具体用法和使用时机;同时对曾经看的一篇文章中讲述的某些部分进行澄清 (文章地址:http://www.byywee.com/page/M0/S702/702424.html)。 简介: @RequestBody 作用:

行者无疆 18万+

HttpClient 使用proxy 设置了connectionTimeout, socketTimeout 还是无限等待

package org.happy.downloader; import java.io.IOException; import java.util.Date; import org.apache.http.HttpHost; import org.apache.http.client.config.CookieSpecs; import org.apache.http.client.conf

行者无疆 9206
上一篇: GBK、GB18030、GB2312 区别
下一篇: Spring 3 MVC深入研究
walkerJong
博客等级 码龄15年 263粉丝 68原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值