相信有了前面三章的基础了解,我们对爬虫的基础知识已经有所掌握。
本篇内容是从易到难给大家讲解一些常用爬虫的手写。
包括图片爬虫、链接爬虫、多线程爬虫等等。

京东图片爬虫实战:

实现目标:将京东商城手机类的商品图片全部下载到本地。

首先打开京东首页。选择我们要下载的商品分类链接。


点击链接之后,我们会看到这样一个Url

这就是我们要爬取的第一个页面。
复制下来他的url。https://list.jd.com/list.html?cat=9987,653,655
接下来将页面拖动到最后可看到
页面解析:

这里有很多分页。那么如何获取其他页面的信息呢。
我们需要观察网址的变化:点击分页观察url。


可发现,每页的字段都有一个page,通过GET的方式请求的。我们可以得到页面url的关键字段:

page=2代表着第几页。
所以我们可以使用for循环来获取其他的页面。

信息提取:
我们需要的是每个页面的图片信息。所以需要使用正则表达式来匹配源码中图片的链接部分。然后通过urllib.request.urlretrieve() 将对应链接的图片保存到本地。

信息过滤:
除了我们想要的手机图片外,还会匹配到其他跟我们目标不同的图片。
所以我们要先进行一次信息过滤。只留下我们所需要的。
我们F12进入审查模式

观察发现图片都是在
也就是说其实中的<div class="page clearfix">可以作为结束的特殊标识。所以我们进行的第一次过滤,我们的正则表达式可以构造为:
pat1='<div id ="plist".+?<div class = "page clearfix">'
每个页面之间的基本格式是一样的,只是其中的图片链接网址不一样,所以此时,我们可以根据该规律构造出我们需要的正则表达式:

'<img width="200" heght="200" data-img="1" data-lazy-img  = "//(.+?\.jpg)">'

编写代码:

import re           #导入re模块
import urllib.request,urllib.error   #导入urllib
def craw(url,page):     #定义一个函数html=urllib.request.urlopen(url).read() #获取页面信息html=str(html)        #将信息转化为字符串pat1='<div id="plist".+? <div class="page clearfix">'result1=re.compile(pat1).findall(html) #在html1内查询符合pat1的result1=result1[0]  #获取起始位置的plist,也就是第一个包含了所以图片的。pat2 ='<img width="220" height="220" data-img="1" data-lazy-img="//(.+?\.jpg)">'imagelist = re.compile(pat2).findall(result1)  #在result1内查询所以的图片链接x = 1for imageurl in imagelist:   #这里我没有用with open、是我手动创建的文件夹。imagename = "D:/work/日常任务2/img1/"+str(page)+str(x)+".jpg"imageurl = "http://"+imageurltry:urllib.request.urlretrieve(imageurl,filename=imagename)except urllib.error.URLError as e:if hasattr(e,"code"):x+=1if hasattr(e,"reason"):x+=1x+=1
if __name__ == '__main__':for i in range(1,30):                #30代表获取的范围url= "http://list.jd.com/list.html?cat=9987,653,655&page="+str(i)craw(url,i)



第一个实战也圆满结束了,我们获取了第一页到29页的所有目标图片,并且将图片存储到本地目录img1下。图片的名字为:页号+顺序号.jpg
通过这个项目的学习,相信大家已经对如何手写爬虫代码有了一定的思路,可以尝试下自己手写一个网络爬虫项目了。

链接爬虫实战:

所谓的 链接爬虫 就是说 我们想把一个网页中所有得链接地址提取出来,那么我们就需要来用链接爬虫来实现。
本项目链接爬虫实现的思路如下:
1、确定要爬取的入口链接。
2、根据需求构建好链接提取的正则表达式。
3、模拟成浏览器并爬取对应网页。
4、根据2中的正则表达式提取出该网页中包含的链接。
5、过滤掉重复的链接。
6、后续操作,保存写入打印等等

下面我们模拟一下获取blog.csdb.net网页上的所有链接。

import re
import urllib.request
def getlink(url):headers = ("User-Agent","Mozilla/5.0 (Windows NT 6.1; WOW64) ""AppleWebKit/537.36 (KHTML, like Gecko)"" Chrome/39.0.2171.71 Safari/537.36")opener = urllib.request.build_opener()      #模拟成浏览器opener.addheaders = [headers]urllib.request.install_opener(opener)  #将opener设置为全局globalfile = urllib.request.urlopen(url)      #获取页面信息data = str(file.read())                 #转换格式pat = '(https?://[^\s)";]+\.(\w|/)*)'    #根据需求构建好链接表达式link = re.compile(pat).findall(data)         #匹配我们需要的信息link = list(set(link))    #通过转换去除重复元素return link
url = "http://blog.csdn.net/"  #将爬取的地址赋值给url
linklist = getlink(url)           #获取对方网页中包含的链接地址for link in linklist:       #遍历我们需要的链接print(link[0])

可看到打印结果:


链接爬取项目完成。

嗅事百科爬虫实战:

项目目标:爬取嗅事百科上的段子。
(www.qiushibaike.com)

本项目实现思路:
1、如同爬取京东图片一样,分析页面规律,构造出网址变量。通过循环进行爬取。
2、构建一个自定义函数,来实现爬取某个网页上的段子。
3、通过循环分别获取多页的各业URL链接,每页分别调用一次getcontent(url.page)函数。

长话短说、看了这么久直接上代码吧。



分别爬取了用户及其对应的内容。代码不难,加油

import urllib.request
import re
def getcontent(url,page):#老套路 先把自己模拟成浏览器   可百度搜索UA池headers = ("User-Agent","Mozilla/5.0 (Windows NT 6.1; WOW64)"" AppleWebKit/537.36 (KHTML, like Gecko)"" Chrome/38.0.2125.122 UBrowser/4.0.3214.0 Safari/537.36")opener = urllib.request.build_opener()  #构造opener.addheaders = [headers]urllib.request.install_opener(opener)  #设置opener为全局data = urllib.request.urlopen(url).read().decode('utf-8')#构建对应用户提取的正则表达式userpat ='<div class="author clearfix">.*?<h2>(.*?)</h2>'#构建内容提取的正则表达式contentpat = '<div.*?span>(.*?)</span>'#寻找所有的用户userlist = re.compile(userpat,re.S).findall(data)   #re.S在匹配时为点任意匹配模式#所有内容contentlist = re.compile(contentpat,re.S).findall(data)# print(data)x=1for content in contentlist:content = content.replace("\n","")name = "content"+str(x)exec(name+'=content')x+=1y=1for user in userlist:name = "content"+str(y)print("用户"+str(page)+str(y)+"是:"+user)print("内容是:")exec("print("+name+")")print("\n")y+=1
for i in range(1,3):            #rang(1,3)为爬取页面范围url = "http://www.qiushibaike.com/hot/page/"+str(i)getcontent(url,i)

运行结果如下:

多线程爬虫:

首先,什么是多线程爬虫。
之前我们写的爬虫,程序在执行起来是有先后顺序的,这种执行解构可以称为单线程结构,对应的爬虫称为单线程爬虫。如下图所示

而多线程爬虫,指的是爬虫中的某部分程序可以并行执行,既在多条线上执行,这种执行结构称为多线程爬虫,对应的爬虫称为多线程爬虫。如下图

多线程爬虫实战:

要在python中使用多线程,我们可以导入threading模块使用多线程功能。我们可以定义一个类并继承threading.Thread类,将该类定义成一个线程。
在该类中,可以使用__init__(self)方法对线程进行初始化,在run(self)方法中写上该线程要执行的程序。我们可以声明多个这样的类来构建多个线程并通过对应线程对象的start()方法启动对应的线程。

写一个简单的多线程功能:

import threading
class A(threading.Thread):def __init__(self):threading.Thread.__init__(self)def run(self):for i in range(10):print("我是线程A")
class B(threading.Thread):def __init__(self):threading.Thread.__init__(self)def run(self):for i in range(10):print("我是线程B")
t1=A()
t1.start()
t2=B()
t2.start()


可以看出,A与B是并行执行的。

下面是多线程爬取糗事百科段子的代码:
看不太明白也没关系,我们后续也会进行更细致的讲解。

# 使用了线程库
import threading
# 队列
from queue import Queue
# 解析库
from lxml import etree
# 请求处理
import requests
# json处理
import json
import timeclass ThreadCrawl(threading.Thread):def __init__(self, threadName, pageQueue, dataQueue):#threading.Thread.__init__(self)# 调用父类初始化方法super(ThreadCrawl, self).__init__()# 线程名self.threadName = threadName# 页码队列self.pageQueue = pageQueue# 数据队列self.dataQueue = dataQueue# 请求报头self.headers = {'User-Agent':'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.101 Safari/537.36'}def run(self):print("启动 " + self.threadName)while not CRAWL_EXIT:try:# 取出一个数字,先进先出# 可选参数block,默认值为True#1. 如果对列为空,block为True的话,不会结束,会进入阻塞状态,直到队列有新的数据#2. 如果队列为空,block为False的话,就弹出一个Queue.empty()异常,page = self.pageQueue.get(False)url = "http://www.qiushibaike.com/8hr/page/" + str(page) +"/"#print urlcontent = requests.get(url, headers = self.headers).texttime.sleep(1)self.dataQueue.put(content)#print len(content)except:passprint("结束 " + self.threadName)class ThreadParse(threading.Thread):def __init__(self, threadName, dataQueue, filename, lock):super(ThreadParse, self).__init__()# 线程名self.threadName = threadName# 数据队列self.dataQueue = dataQueue# 保存解析后数据的文件名self.filename = filename# 锁self.lock = lockdef run(self):print("启动" + self.threadName)while not PARSE_EXIT:try:html = self.dataQueue.get(False)self.parse(html)except:passprint("退出" + self.threadName)def parse(self, html):# 解析为HTML DOMhtml = etree.HTML(html)node_list = html.xpath('//div[contains(@id, "qiushi_tag")]')for node in node_list:# xpath返回的列表,这个列表就这一个参数,用索引方式取出来,用户名username = node.xpath('./div/a/@title')[0]# 图片连接image = node.xpath('.//div[@class="thumb"]//@src')#[0]# 取出标签下的内容,段子内容content = node.xpath('.//div[@class="content"]/span')[0].text# 取出标签里包含的内容,点赞zan = node.xpath('.//i')[0].text# 评论comments = node.xpath('.//i')[1].textitems = {"username" : username,"image" : image,"content" : content,"zan" : zan,"comments" : comments}# with 后面有两个必须执行的操作:__enter__ 和 _exit__# 不管里面的操作结果如何,都会执行打开、关闭# 打开锁、处理内容、释放锁with self.lock:# 写入存储的解析后的数据self.filename.write(json.dumps(items, ensure_ascii = False).encode("utf-8") + "\n")CRAWL_EXIT = False
PARSE_EXIT = Falsedef main():# 页码的队列,表示20个页面pageQueue = Queue(20)# 放入1~10的数字,先进先出for i in range(1, 21):pageQueue.put(i)# 采集结果(每页的HTML源码)的数据队列,参数为空表示不限制dataQueue = Queue()filename = open("duanzi.json", "a")# 创建锁lock = threading.Lock()# 三个采集线程的名字crawlList = ["采集线程1号", "采集线程2号", "采集线程3号"]# 存储三个采集线程的列表集合threadcrawl = []for threadName in crawlList:thread = ThreadCrawl(threadName, pageQueue, dataQueue)thread.start()threadcrawl.append(thread)# 三个解析线程的名字parseList = ["解析线程1号","解析线程2号","解析线程3号"]# 存储三个解析线程threadparse = []for threadName in parseList:thread = ThreadParse(threadName, dataQueue, filename, lock)thread.start()threadparse.append(thread)# 等待pageQueue队列为空,也就是等待之前的操作执行完毕while not pageQueue.empty():pass# 如果pageQueue为空,采集线程退出循环global CRAWL_EXITCRAWL_EXIT = Trueprint("pageQueue为空")for thread in threadcrawl:thread.join()print("1")while not dataQueue.empty():passglobal PARSE_EXITPARSE_EXIT = Truefor thread in threadparse:thread.join()print("2")with lock:# 关闭文件filename.close()print("谢谢使用!")if __name__ == "__main__":main()

总结:

本篇文章是基于前面3篇基础而做出来的实战项目。内容由易到难。
只要多回顾之前的知识,掌握好爬虫的思维,就能顺利写出来我们所需要的爬虫代码。
后续文章会继续讲解,请关注博客更新。
下一篇:初识Python爬虫框架Scrapy

004:Python爬虫实战 由易到难(图文解析)相关推荐

  1. python爬虫图片实例-【图文详解】python爬虫实战——5分钟做个图片自动下载器...

    我想要(下)的,我现在就要 python爬虫实战--图片自动下载器 之前介绍了那么多基本知识[Python爬虫]入门知识(没看的赶紧去看)大家也估计手痒了.想要实际做个小东西来看看,毕竟: talk ...

  2. 【图文详解】python爬虫实战——5分钟做个图片自动下载器

    python爬虫实战--图片自动下载器 之前介绍了那么多基本知识[Python爬虫]入门知识,大家也估计手痒了.想要实际做个小东西来看看,毕竟: talk is cheap show me the c ...

  3. qq纵横四海源码_【0基础】纵横中文网python爬虫实战

    原文在此~ [0基础]纵横中文网python爬虫实战​mp.weixin.qq.com 大家好,我是你们的机房老哥! 在粉丝群的日常交流中,爬虫是比较常见的话题.python最强大的功能之一也是爬虫. ...

  4. python爬虫实战——猫眼电影案例

    python爬虫实战--猫眼电影案例 ·背景   笔者上一篇文章<基于猫眼票房数据的可视化分析>中爬取了猫眼实时票房数据,用于展示近三年电影票房概况.由于数据中缺少导演/演员/编剧阵容等信 ...

  5. python爬虫实战---爬取大众点评评论

    python爬虫实战-爬取大众点评评论(加密字体) 1.首先打开一个店铺找到评论 很多人学习python,不知道从何学起. 很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手. 很多 ...

  6. 看不懂别做爬虫-----python爬虫实战---大众点评评论

    python爬虫实战-爬取大众点评评论(加密字体) 1.首先打开一个店铺找到评论 2.分析网页 查看到下面有些字体经过加密处理 刷新页面会发现 每一次加密的字体是不一样的 3.发送请求获取数据 查看网 ...

  7. python爬虫实战-爬取微信公众号所有历史文章 - (00) 概述

    http://efonfighting.imwork.net 欢迎关注微信公众号"一番码客"获取免费下载服务与源码,并及时接收最新文章推送. 最近几年随着人工智能和大数据的兴起,p ...

  8. Python爬虫实战:京东拍拍验机(帮你买到最完美的二手iPhone)

    文章目录 网站介绍&使用痛点 网站分析 项目实施 1. 爬取commodityId 1.1 失败的爬取思路 1.2 改进后的巧妙的爬取思路 2. 增加筛选项 3. 筛选所有商品 PS 网站介绍 ...

  9. Python爬虫实战之二 - 基于Scrapy框架抓取Boss直聘的招聘信息

    Python爬虫实战之三 - 基于Scrapy框架抓取Boss直聘的招聘信息 ---------------readme--------------- 简介:本人产品汪一枚,Python自学数月,对于 ...

  10. 视频教程-Python爬虫实战视频教程-Python

    Python爬虫实战视频教程 东北大学计算机专业硕士研究生,欧瑞科技创始人&CEO,曾任国内著名软件公司项目经理,畅销书作者,企业IT内训讲师,CSDN学院专家讲师,制作视频课程超过1000小 ...

最新文章

  1. c++ 类数组_输入输出流IO体系及常用类关系结构(精要收藏)
  2. linux下基于apache下的svn的搭建
  3. 1.Excel业务分析数据
  4. ArcGIS如何在一个矢量上用不同颜色进行标注
  5. 点到直线的距离c语言程序,点到线段的距离 题解(C++)
  6. 中科院自动化所研究员课题组PPT《如何撰写毕业论文?》
  7. postgresql python连接不用把密码写在代码里[.pgpass]
  8. 想要构建现代化数据中心?交给戴尔第14代PowerEdge服务器解决吧!
  9. 我应关注的AEC算法细分
  10. soapui oracle groovy,SoapUI Groovy 使用实例
  11. idc机房运维巡检_IDC机房运维心得
  12. 千人千面、个性化推荐:解读数据赋能商家背后的AI技术
  13. 微信公众平台模拟登录自动群发图文消息工具包
  14. 企业微信开发,嵌入自定义项目,及JS-SDK的引用
  15. Theory for the information-based decomposition of stock price
  16. 系统镜像的方法,大批量电脑重装的方法
  17. 4kw机柜无通道封闭CFD模拟分析及优化(上篇) -孙长青
  18. kerberos 部署
  19. 浅谈Arrays.asList()方法
  20. mysql 转储是什么意思_为什么要转储Internet Explorer

热门文章

  1. MYSQL选修课的心得体会_选修课心得体会
  2. 标准模型与随机预言模型的比较
  3. ArchLinux-KDE桌面美化
  4. 基于pytorch卷积人脸表情识别--毕业设计
  5. mui+hbuilder h5+内置获取当前地理位置以及各种权限 兼容iOS/安卓
  6. Spring5之IOC容器中IOC操作之Bean管理(二)之p名称空间注入、外部bean、内部bean、级联赋值
  7. RT_thread 临界区保护
  8. Environment 的使用
  9. Win10中文输入法加入美式英文键盘并默认英文键盘
  10. 可汗学院公开课——统计学学习:35-46