004:Python爬虫实战 由易到难(图文解析)
相信有了前面三章的基础了解,我们对爬虫的基础知识已经有所掌握。
本篇内容是从易到难给大家讲解一些常用爬虫的手写。
包括图片爬虫、链接爬虫、多线程爬虫等等。
京东图片爬虫实战:
实现目标:将京东商城手机类的商品图片全部下载到本地。
首先打开京东首页。选择我们要下载的商品分类链接。
点击链接之后,我们会看到这样一个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爬虫实战 由易到难(图文解析)相关推荐
- python爬虫图片实例-【图文详解】python爬虫实战——5分钟做个图片自动下载器...
我想要(下)的,我现在就要 python爬虫实战--图片自动下载器 之前介绍了那么多基本知识[Python爬虫]入门知识(没看的赶紧去看)大家也估计手痒了.想要实际做个小东西来看看,毕竟: talk ...
- 【图文详解】python爬虫实战——5分钟做个图片自动下载器
python爬虫实战--图片自动下载器 之前介绍了那么多基本知识[Python爬虫]入门知识,大家也估计手痒了.想要实际做个小东西来看看,毕竟: talk is cheap show me the c ...
- qq纵横四海源码_【0基础】纵横中文网python爬虫实战
原文在此~ [0基础]纵横中文网python爬虫实战mp.weixin.qq.com 大家好,我是你们的机房老哥! 在粉丝群的日常交流中,爬虫是比较常见的话题.python最强大的功能之一也是爬虫. ...
- python爬虫实战——猫眼电影案例
python爬虫实战--猫眼电影案例 ·背景 笔者上一篇文章<基于猫眼票房数据的可视化分析>中爬取了猫眼实时票房数据,用于展示近三年电影票房概况.由于数据中缺少导演/演员/编剧阵容等信 ...
- python爬虫实战---爬取大众点评评论
python爬虫实战-爬取大众点评评论(加密字体) 1.首先打开一个店铺找到评论 很多人学习python,不知道从何学起. 很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手. 很多 ...
- 看不懂别做爬虫-----python爬虫实战---大众点评评论
python爬虫实战-爬取大众点评评论(加密字体) 1.首先打开一个店铺找到评论 2.分析网页 查看到下面有些字体经过加密处理 刷新页面会发现 每一次加密的字体是不一样的 3.发送请求获取数据 查看网 ...
- python爬虫实战-爬取微信公众号所有历史文章 - (00) 概述
http://efonfighting.imwork.net 欢迎关注微信公众号"一番码客"获取免费下载服务与源码,并及时接收最新文章推送. 最近几年随着人工智能和大数据的兴起,p ...
- Python爬虫实战:京东拍拍验机(帮你买到最完美的二手iPhone)
文章目录 网站介绍&使用痛点 网站分析 项目实施 1. 爬取commodityId 1.1 失败的爬取思路 1.2 改进后的巧妙的爬取思路 2. 增加筛选项 3. 筛选所有商品 PS 网站介绍 ...
- Python爬虫实战之二 - 基于Scrapy框架抓取Boss直聘的招聘信息
Python爬虫实战之三 - 基于Scrapy框架抓取Boss直聘的招聘信息 ---------------readme--------------- 简介:本人产品汪一枚,Python自学数月,对于 ...
- 视频教程-Python爬虫实战视频教程-Python
Python爬虫实战视频教程 东北大学计算机专业硕士研究生,欧瑞科技创始人&CEO,曾任国内著名软件公司项目经理,畅销书作者,企业IT内训讲师,CSDN学院专家讲师,制作视频课程超过1000小 ...
最新文章
- c++ 类数组_输入输出流IO体系及常用类关系结构(精要收藏)
- linux下基于apache下的svn的搭建
- 1.Excel业务分析数据
- ArcGIS如何在一个矢量上用不同颜色进行标注
- 点到直线的距离c语言程序,点到线段的距离 题解(C++)
- 中科院自动化所研究员课题组PPT《如何撰写毕业论文?》
- postgresql python连接不用把密码写在代码里[.pgpass]
- 想要构建现代化数据中心?交给戴尔第14代PowerEdge服务器解决吧!
- 我应关注的AEC算法细分
- soapui oracle groovy,SoapUI Groovy 使用实例
- idc机房运维巡检_IDC机房运维心得
- 千人千面、个性化推荐:解读数据赋能商家背后的AI技术
- 微信公众平台模拟登录自动群发图文消息工具包
- 企业微信开发,嵌入自定义项目,及JS-SDK的引用
- Theory for the information-based decomposition of stock price
- 系统镜像的方法,大批量电脑重装的方法
- 4kw机柜无通道封闭CFD模拟分析及优化(上篇) -孙长青
- kerberos 部署
- 浅谈Arrays.asList()方法
- mysql 转储是什么意思_为什么要转储Internet Explorer