下面是我的代码框架(请先看代码需要改进的地方)

需要改进的是

1、采用双缓冲队列,即两个队列,可以理解为一个队列用于生产者的数据写入,一个用于消费者的数据读取,当消费者队列没有数据从生产者队列获取,减少锁的竞争。
2、使用selenium(webdriver)连接池(在另一个中会有)。
3、代码过于繁琐与冗余,可以进行精简(这个可能没时间了)。

架构及代码详细说明(后面附上我的完整代码)

1、model中包括一个模型,该模型表示我要爬取的京东的信息。比如一本书包括书的识别码,名字,价格,出版社等信息。
2、runmain中包含两个包,一个是运行包(有main函数,消费者-生产者模型),一个是需要调用包(作用是对字符串进行拼接以获取全部的要提取信息的url)。
3、thread包中是消费者-生产者模型,product和consumer。具体请看代码。
4、downloader中包括下载的所有类,需要有selenium基础。
5、analysis中包括所有解析的类,需要有selenium基础。
6、bloomFilterpack这是一个过滤器。
7、database数据库的有关操作,需要有mongodb基础,redis基础。

架构思路

1、首先获取京东官网的所有要爬取的数据(分类信息)。如下图所示,箭头所指方向即为要获取的分类信息。获取该部分所有的数据并存入redis数据库,具体看下方代码及注释。

解释:下图中蓝色的代码刚开始不显示,只有鼠标移动到上图右边红框上才会显示该部分代码。

package runmain;/**1. 创建时间:2019年1月18日 下午6:43:113. 4. 项目名称:integration_zhong5. 6. @author 王锋洲7. 8. @version 1.09. 10. @since JDK 1.811. 12.        文件名称:run_project.java13. 14.        类说明:主类,调用方法将所有分类信息插入到数据库并进行后续操作。15.*/
public class RunProject {public static void main(String[] args) {Jedis jedis = new Jedis("192.168.50.194");jedis.flushAll();InitRedis init = new InitRedis();init.Init();//获取首页内容GetContent content=new GetContent();//调用方法,代码如下content.getcontenttext();System.out.println("title success");}
}
public void getcontenttext(){try {/*调用GetContent()方法,该方法以GetDownload_html方法返回值作为参数*/ana_content.GetContent(down.GetDownload_html(base.GetToVisit()));} catch (InterruptedException e) {e.printStackTrace();}}
public class AnalysisContent
{List<String> list = new ArrayList<String>();Jedis jedis=new Jedis();RedisBase jedis_content=new RedisBase();public void GetContent(String result){//这里可以用正则解析,具体可以自己编写//用Jsoup解析代码Document doc=Jsoup.parse(result);Elements links = doc.select("div[class=JS_popCtn cate_pop]").select("div[class=cate_part clearfix]").select("div[class=cate_part_col1]").select("dd[class=cate_detail_con]").select("a[href]");for(Element link:links){String content="";content=link.attr("title");if(content.isEmpty()){content=link.text();if((content.isEmpty())){continue;}}if(content.length()>5){continue;}this.list.add(content);}//添加到redis数据库jedis_content.AddToVisitTitle(list);}
}
public class DownloadHtml {private String downloadresult;public void StartDownload(String download_url) throws InterruptedException {System.setProperty("webdriver.chrome.driver", "G:\\Tools\\chromedriver.exe");// 相当于一个静态变量 ,存在内存里面!ChromeOptions option = new ChromeOptions();option.setBinary("D:/Google/Chrome/Application/chrome.exe");option.setHeadless(true);WebDriver driver = new ChromeDriver(option);driver.manage().window().maximize();driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);//// 全局等待元素TimeUnit.SECONDS 线程
//          JavascriptExecutor js = (JavascriptExecutor) driver;driver.get(download_url);
//          js.executeScript("window.scrollTo(0,document.body.scrollHeight)");Thread.sleep(3000);Actions action=new Actions(driver);/*模拟鼠标移动到该元素上*/action.moveToElement(driver.findElement(By.xpath("//div[@id='J_cate']/ul/li/a"))).perform();try {Thread.sleep(3000);downloadresult=driver.getPageSource();} catch (Exception e) {e.printStackTrace();}finally{driver.quit();System.out.println("已关闭3");}}//该方法调用StartDownload()函数public String GetDownload_html(String download_url) throws InterruptedException {this.StartDownload(download_url);return this.downloadresult;}
}

redis数据库执行结果如下图

2、经过第一步的实现,将所有类别都加入了Redis数据库。使用生产者-消费者模型对数据进行精细处理。
解释1:当生产者的待处理队列不为空时,进行生产者睡眠,这时消费开始处理队列反之,当待处理队列为空时,生产者运行,存储数据到待处理队列 。
解释2:使用Future处理,防止中断,或者使用try–catch–finally进行代替。
(1)生产者从redis数据库中获取一个分类信息,使用selenium自动测试模拟输入商品类别并模拟点击“搜索按钮”以获取当前url,再对该url进行拼接并存入到redis待处理队列中。具体看代码注释。

//生产者
public void produce() {lock.lock();try {//待处理队列非空,则睡眠while (!base.ToVisitEmpty()) {System.out.println("生产者" + Thread.currentThread().getName() + " waiting");condition.await();}// while (!base.ToVisitEmptyTitle()) {// 获取数据ExecutorService executor = Executors.newSingleThreadExecutor();//FutureTask处理,预防中断代码的执行。这个代码不是很好。FutureTask<String> future = new FutureTask<String>(new Callable<String>() {// 使用Callable接口作为构造参数@Overridepublic String call() throws IOException {//获取一个分类信息String title = base.GetToVisitedTitle();//添加到已访问的分类数据队列base.AddVisitedTitle(title);// 字符串拼接pingjie.geturl(title);Long length1 = jedis.llen("toVisitTitle");Long length2 = jedis.llen("toVisit");System.out.println("toVisitTitle当前长度:" + length1);System.out.println("toVisit当前长度:" + length2);return "执行成功";}});executor.execute(future);try {String result = future.get(3000, TimeUnit.MILLISECONDS); // 取得结果,同时设置超时执行时间为5秒。同样可以用future.get(),不设置执行超时时间取得结果System.out.println(result);} catch (InterruptedException e) {System.out.println("produceInterruptedException:error");} catch (ExecutionException e) {System.out.println("produceExecutionException:error");} catch (TimeoutException e) {System.out.println("produceTimeoutException:error");} finally {executor.shutdown();}// }condition.signalAll();System.out.println("消费者" + Thread.currentThread().getName() + " Runnable");} catch (InterruptedException e) {e.printStackTrace();} finally {lock.unlock();}}
package runmain;import java.util.LinkedList;
import java.util.concurrent.TimeUnit;import javax.servlet.ServletContext;
import javax.servlet.http.HttpSession;import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;import analysis.AnalysisUrl;
import analysis.AnalysisPage;
import database.redis.RedisBase;
import downloader.DownloadTitleHtml;/*** 创建时间:2019年1月19日 上午10:05:25  * 项目名称:integration_zhong  * @author 王锋洲* @version 1.0* @since JDK 1.8 * 文件名称:String_pingjie.java  * 类说明:  拼接url,调用的类库有 AnalysisUrl,AnalysisPage,RedisBase,DownloadTitleHtml*/
public class StringGetAllUrl
{AnalysisPage ana_page=new AnalysisPage();//下载页面DownloadTitleHtml down_html=new DownloadTitleHtml();//rdis数据库操作RedisBase base = new RedisBase();//解析页面AnalysisUrl anaurl=new AnalysisUrl();//传递要处理的分类数据,进行拼接操作public void geturl(String title){System.out.println("解析当前url");String currenturl=anaurl.AnalysisCurrentUrl(title);System.out.println("currenturl"+currenturl);//生产者中对url进行截取与拼接,以产生不同的页码对应的不同urlString[] str1 = currenturl.split("&");String url1 = str1[0] + "&" + str1[1]+"&page=";System.out.println("解析当前页面页数");int n=ana_page.GetPage(down_html.GetTitleHtml(title));//该拼接方式不完善,会漏抓数据,请改进或者使用selenium一页一页的模拟点击for(int i=1;i<=n*2;i++){String url2=url1+i;//加入到redis数据库中base.AddToVisit(url2);//System.out.println("插入成功");i++;}}
}

//获取当前url并返回,该方法在上面被调用
public String AnalysisCurrentUrl(String title){String current_url ="";System.setProperty("webdriver.chrome.driver", "G:\\Tools\\chromedriver.exe");// 相当于一个静态变量 ,存在内存里面!ChromeOptions option = new ChromeOptions();option.setBinary("D:/Google/Chrome/Application/chrome.exe"); option.setHeadless(true);WebDriver driver = new ChromeDriver(option);driver.manage().window().maximize();driver.manage().timeouts().implicitlyWait(7, TimeUnit.SECONDS);// 全局等待元素TimeUnit.SECONDS 线程String url = "https://www.jd.com/";try{driver.get(url);}catch(Exception ew){ew.printStackTrace();}WebDriverWait webDriverWait = new WebDriverWait(driver, 5);webDriverWait.until(ExpectedConditions.elementToBeClickable(By.id("key"))).sendKeys(title);webDriverWait.until(ExpectedConditions.elementToBeClickable(By.xpath("//div[@id='search']/div/div[2]/button"))).click();try {Thread.sleep(5000);current_url = driver.getCurrentUrl();} catch (InterruptedException e1) {e1.printStackTrace();}driver.quit();System.out.println("已关闭1");try {current_url = new String(current_url.getBytes("iso-8859-1"), "utf-8");} catch (UnsupportedEncodingException e) {// TODO Auto-generated catch blocke.printStackTrace();}return current_url;}
//获取页面的html代码
public String GetTitleHtml(String title) {String downloadresult = "";try {System.out.println("GetTitleHtml");System.setProperty("webdriver.chrome.driver", "G:\\Tools\\chromedriver.exe");// 相当于一个静态变量 ,存在内存里面!ChromeOptions option = new ChromeOptions();option.setBinary("D:/Google/Chrome/Application/chrome.exe");option.setHeadless(true);WebDriver driver = new ChromeDriver(option);driver.manage().window().maximize();driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);// 全局等待元素TimeUnit.SECONDS 线程String url = "https://www.jd.com/";try{Thread.sleep(2000);driver.get(url);//时间超时}catch(Exception e){e.printStackTrace();}WebDriverWait webDriverWait = new WebDriverWait(driver, 5);webDriverWait.until(ExpectedConditions.elementToBeClickable(By.id("key"))).sendKeys(title);webDriverWait.until(ExpectedConditions.elementToBeClickable(By.xpath("//div[@id='search']/div/div[2]/button"))).click();try {Thread.sleep(3000);downloadresult = driver.getPageSource();//时间超时} catch (Exception e1) {e1.printStackTrace();}driver.quit();System.out.println("已关闭2");} catch (Exception e) {e.printStackTrace();}return downloadresult;}

//解析当前页面的html代码以获取页码并返回
public int GetPage(String result){Document doc=Jsoup.parse(result);String link=doc.getElementById("J_topPage").select("span[class=fp-text]").select("i").text();if(link.isEmpty()){return 0;}return Integer.parseInt(link);}

(2)消费者从待处理队列中取出url(用多线程)对该url进行获取页面数据->解析要获取的数据->存入到mongodb数据库过程。具体看代码注释。

//消费者public void consumer() {lock.lock();try {//当待处理队列为空则该线程睡眠while (base.ToVisitEmpty()) {System.out.println("消费者" + Thread.currentThread().getName() + " waiting");condition.await();}//当待处理队列非空时一直处理直到处理完毕while (!base.ToVisitEmpty()) {ExecutorService executor = Executors.newSingleThreadExecutor();FutureTask<String> future = new FutureTask<String>(new Callable<String>() {// 使用Callable接口作为构造参数@Overridepublic String call() throws IOException, InterruptedException {// 从数据库中取数据读取链接String aimurl = base.GetToVisit();String aimhtml = "";// 下载aimurl的全部的HTML资源用于解析数据,这里和上面的的方法大体一样,就不一一赘述了aimhtml = get.GetAllHtml_aimurl(aimurl);//解析数据并存到mongodb数据库,看下面代码ana_value.deal_download_result(aimhtml);System.out.println("ana_value");System.out.println("aimurl:" + aimurl);//添加到已处理队列base.AddVisited(aimurl);return "执行成功";}});executor.execute(future);// 在这里可以做别的任何事情try {String result = future.get(3000, TimeUnit.MILLISECONDS); // 取得结果,同时设置超时执行时间为5秒。同样可以用future.get(),不设置执行超时时间取得结果System.out.println(result);} catch (InterruptedException e) {System.out.println("consumerInterruptedException:error");} catch (ExecutionException e) {System.out.println("consumerExecutionException:error");} catch (TimeoutException e) {System.out.println("consumerTimeoutException:error");} finally {executor.shutdown();}}//唤醒线程condition.signalAll();System.out.println("生产者" + Thread.currentThread().getName() + " Runnable");} catch (InterruptedException e) {e.printStackTrace();} finally {lock.unlock();}}
 //处理解析数据存入mongodb数据库public void deal_download_result(String downloadresult) {List<org.bson.Document> data = new ArrayList<org.bson.Document>();//使用jsoup解析,可以用正则替代,xpath也可以Document doc = Jsoup.parse(downloadresult);Elements elements = doc.select("ul[class=gl-warp clearfix]").select("li[class=gl-item]");String name = "";String price = "";String publish = "";String href = "";String Textcommit = "";String commith = "";for (Element ele : elements) {id++;name = ele.select("div[class=p-name p-name-type-2]").select("a").select("em").text();price = ele.select("div[class=p-price]").select("strong").select("i").text().trim();publish = ele.select("div[class=p-shop]").select("a").attr("title");href = ele.select("div[class=p-name p-name-type-2]").select("a").attr("href");Textcommit = ele.select("div[class=p-commit]").select("strong").select("a").text();commith = ele.select("div[class=p-commit]").select("strong").select("a").attr("href");if (publish.isEmpty()) {publish = "未知出版社";}org.bson.Document document = new org.bson.Document("name", name).append("price", price).append("publish", publish).append("href", href).append("Textcommit", Textcommit).append("commith", commith);data.add(document);}BatchData bachdata=new BatchData();bachdata.data_batch(data);

完整代码:https://gitee.com/zfenghan/internet_worm.git

网络爬虫——爬取京东数据相关推荐

  1. python爬虫爬取京东商品评价_网络爬虫-爬取京东商品评价数据

    前段时间做商品评价的语义分析,需要大量的电商数据,于是乎就自己动手爬取京东的数据.第一次接触爬虫是使用selenium爬取CNKI的摘要,基于惯性思维的我仍然想用selenium+Firefox的方法 ...

  2. 网络爬虫-爬取京东商品评价数据

    前段时间做商品评价的语义分析,需要大量的电商数据,于是乎就自己动手爬取京东的数据.第一次接触爬虫是使用selenium爬取CNKI的摘要,基于惯性思维的我仍然想用selenium+Firefox的方法 ...

  3. 基于Python的网络爬虫爬取天气数据可视化分析

    目录 摘 要 1 一. 设计目的 2 二. 设计任务内容 3 三. 常用爬虫框架比较 3 四.网络爬虫程序总体设计 3 四. 网络爬虫程序详细设计 4 4.1设计环境和目标分析 4 4.2爬虫运行流程 ...

  4. Python网络爬虫爬取招聘数据(利用python简单零基础)可做可视化

    爬取Boss直聘相关的招聘数据 一.相关需求分析 1.目的 二.直聘网页结构分析 1.网页相关值的查找 2.网页的下一页规律查找 三.Python相关的第三库介绍 1.Urllib的介绍 (1)url ...

  5. python爬虫爬取房源_手把手教你用Python网络爬虫爬取新房数据

    项目背景 大家好,我是J哥. 新房数据,对于房地产置业者来说是买房的重要参考依据,对于房地产开发商来说,也是分析竞争对手项目的绝佳途径,对于房地产代理来说,是踩盘前的重要准备. 今天J哥以「惠民之家」 ...

  6. python如何爬虫网页数据-python网络爬虫爬取网页内容

    1.什么是网络爬虫? 网络爬虫(又被称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者),是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本.另外一些不常使用的名字还有蚂蚁.自 ...

  7. 爬虫爬取京东商品详细数据 (品牌、售价、各类评论量(精确数量)、热评词及数量等)json解析部分数据

    文章目录 前言 一.数据保存格式设置及数据库准备(CentOS云mysql数据库) 1.分析数据需求(单一商品为例) 2.数据库保存格式 3.用到的数据库操作及指令 二.网页分析 1.分析网页源码,确 ...

  8. 三行代码爬取京东数据

    文章目录 三行代码爬取京东数据 python学习 关于数据 关于代码 三行代码爬取京东数据 潦潦草草 python学习 了解python爬虫 python程序里,爬取网络数据的虫子叫爬虫,它的实质是模 ...

  9. python爬虫数据分析可以做什么-python爬虫爬取的数据可以做什么

    在Python中连接到多播服务器问题,怎么解决你把redirect关闭就可以了.在send时,加上参数allow_redirects=False 通常每个浏览器都会设置redirect的次数.如果re ...

最新文章

  1. asyncio之Coroutines,Tasks and Future
  2. linux shell 文件路径 分解 解析 切分 ${str:a:b} 用法
  3. java编程那些事pdf下载_《Java编程那点事儿》读书笔记(六)
  4. typedef的四个用途和两个陷阱
  5. 错误400-The request sent by the client was syntactically incorrect
  6. TikZ绘图示例——尺规作图: 圆内接正五边形的近似画法
  7. GitHub上如何创建文件夹
  8. java HTableDescriptor类解析
  9. Docker入门者手册
  10. 基于Windows 7环境的WAPI无线网络应用层控制实现
  11. oracle 字符串中数字转中文大写,金额钱数转中文大写
  12. 湖北移动CM201-1-CH _S905L3B-UWE5621DS_线刷固件包
  13. 安卓移动开发实验:Android Studio设计微信界面
  14. page_to_phys()和virt_to_phys()
  15. 联想国产自主计算机,实现零的突破,第一款纯国产电脑诞生,网友:此刻联想怎么想?...
  16. i7处理器好吗_英特尔酷睿i5处理器和i7有什么区别
  17. matlab计算macd_[转载]4.K线图以及常用技术指标的Matlab实现-基于Matlab的量化投资...
  18. AT765 真冬日?真夏日?
  19. 初秋最时髦好看的搭配,竟是风衣里面套裙子!
  20. BLDC无刷电机6步换向步骤简述

热门文章

  1. 爬虫基础之HTTP基本原理
  2. 道不投不足与谋:(,决定放弃原来的博客空间,不再更新
  3. codeforces The Artful Expedient(数学思维题)
  4. android11用石墨文档,轻协作 | 石墨文档 for Android 版轻体验
  5. iOS——内存监控(Memory)
  6. 【第五周】新蜂团体贡献分
  7. 有赞和腾讯云、阿里云一同摘得“中国企业云科技服务商50强”
  8. imac mini 双系统_iMac,Mini和Pro:Apple的台式Mac比较
  9. 1.UEFI-edk2 开发环境搭建
  10. 【转】面向贡献者的 AOSP Java 代码样式指南