手持Python,斗图不输!
本文作者:张 宇
文字编辑:宁刘莹
技术总编:张 邯
爬虫俱乐部将于2019年8月22日至28日在湖北武汉举行为期一周的Stata编程技术定制培训,此次培训采用Stata16进行讲解,采取初级班和高级班分批次培训。课程通过案例教学模式,旨在帮助大家在短期内掌握Stata软件编程、金融计量知识和实证分析方法,使大家熟悉Stata核心的爬虫技术,以及Stata与其他软件交互的高端技术。目前正在火热招生中~
详细培训大纲及报名方式,请点击文末阅读原文呦~
本文以抓取“斗图啦”(http://www.doutula.com/)中的图片为例来介绍如何使用python和正则表达式完成最基本的爬虫和文件下载工作。
进入网站后,点击最新表情,并点击第二页,网页的url(http://www.doutula.com/photo/list/?page=2)同样发生了变化。不难发现,此网页的请求方式为最简单的get请求。
下面,我们将使用requests、re、os库来实现图片的抓取与下载。
一、导入python标准库
这里我们将用到三个标准库,os用来创建文件夹并更改缺省路径;requests用来抓取网页源代码;re用来提取源代码中我们需要的信息。
import os
import re
import requests
二、创建文件夹并更改缺省路径
os.mkdir(r"D:/斗图") #在D盘创建“斗图”文件夹,如果文件夹存在则会报错。
os.chdir(r"D:/斗图") #更改缺省路径到"D:/斗图"。
os.getcwd() #查看缺省路径是否已经更改。
三、构建headers,抓取网页源代码
首先,我们构建一个名为headers的字典,并传给requests.get()中的headers参数,requests将该参数作为请求报文的首部字段编制报文,字典headers中可以传入请求头的部分信息以防止网站反爬。那么,headers字典中的参数是从哪里得到的呢?参考爬虫俱乐部往期推文《一起来揪出网页真实链接!》,找到网页的一些请求头:即下图的Headers。
我们使用几个重要参数构建字典,程序如下:
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36',
'Host': 'www.doutula.com'
}
我们在这里设定字典中的两个key分别是User-Agent、Host,当然,请求头中的其他参数也可根据需求添加到字典中。接下来,使用requests.get()方法抓取网页源代码,程序如下:
response = requests.get("http://www.doutula.com/photo/list/?page=1",headers = headers)
print(response.text)
text = response.text
requests.get()方法中的第一个参数是url,此参数是必须传入的一个参数。此外,此方法中还有一些其他参数,例如:headers,传入请求头信息;proxies,传入代理地址;params,传入get请求的参数,例如“http://www.doutula.com/photo/list/?page=1”,get请求方式如果以“?”携带参数,可将参数“page=1”构建成字典传给params,此时requests.get()中传入的url则变成“http://www.doutula.com/photo/list/”。
打印网页源代码,发现python为我们解析出的网页源代码无乱码,可直接使用text变量来接收网页源代码。
四、使用正则表达式提取信息部分网页源代码如下:“data-original”属性的值就是图片的地址,而p标签中存放的则为图片名称,我们的目的就是利用图片的url将图片下载下来,将下载下来的文件名设定为图片原本的文件名,因此我们需要提取url和图片名。
首先使用re.findall方法将图片的url和名称提取出来,此方法第一个需要传入的参数为正则表达式,第二个参数为目标字符串,第三个参数re.S的作用是使正则表达式将目标字符串作为一个整体,将“\n”当做一个普通的字符加入到这个字符串中,使“.“能够匹配换行符,而无须在匹配之前将目标字符串中的空字符剔除。
imgs_url_name = re.findall('data-original="(.*?)".*?<p.*?>(.*?)</p>',text,re.S)
print(imgs_url_name)
len(imgs_url_name)
可以发现,findall方法返回一个列表,列表中的每一个元素都是一个元组,元组中的每条信息就是子表达式匹配到的内容。关于re库更详细的用法可参考爬虫俱乐部往期推文《Python标准库re:正则表达式》。
五、下载图片
这一步需将上边获取到的url和图片名称使用切片提取出来并使用requests.get()方法和文件操作的方法将图片下载到本地。程序如下:
for img in imgs_url_name: #img是包含图片url和名称的元组
name = img[1] #提取图片名称
name = re.sub(r'[\??\.,。!! /]','',name) #将图片名称中的一些不适合作为文件名的符号剔除。
#print(name)
url = img[0] #提取图片url
#print(url)
suffix = os.path.splitext(url)[1] #提取图片后缀
os.path.splitext()方法可分离文件名与扩展名,默认返回元组。例如,“http://img.doutula.com/production/uploads/image//2019/07/01/20190701929023_ZBfzXo.jpg“可分离成”http://img.doutula.com/production/uploads/image//2019/07/01/20190701929023_ZBfzXo“和“.jpg”.
#print(suffix)
filename = name + suffix #使用图片名称和后缀构造文件名
print(filename)
#获取每张图片的源代码,并将其以二进制形式写入文件。
r = requests.get(url)
with open(filename,"wb") as fp :
fp.write(r.content)
有了这些图片,你就是斗图界的专家啦!
以上是爬取单个页面的程序,如果我们想爬取多个页面,只需要对页码循环,并更改url中参数page的值即可,完整程序如下:
import os
import re
import requests
os.mkdir(r"D:/斗图")
os.chdir(r"D:/斗图")
os.getcwd()
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36',
'Host': 'www.doutula.com'
}
for page_num in range(1,5) :
response = requests.get("http://www.doutula.com/photo/list/?page={}".format(page_num),headers = headers)
print(response.text)
text = response.text
imgs_url_name = re.findall('data-original="(.*?)".*?<p.*?>(.*?)</p>',text,re.S)
print(imgs_url_name)
len(imgs_url_name)
for img in imgs_url_name:
name = img[1]
name = re.sub(r'[\??\.,。!!/ ]','',name)
print(name)
url = img[0]
print(url)
suffix = os.path.splitext(url)[1]
print(suffix)
filename = name + suffix
print(filename)
r = requests.get(url)
with open(filename,"wb") as fp :
fp.write(r.content)
对爬虫俱乐部的推文累计打赏超过1000元我们即可给您开具发票,发票类别为“咨询费”。用心做事,只为做您更贴心的小爬虫!
往期推文推荐
对抗bug方法介绍——爆款pysnooper你用了吗?(下篇)
关于我们
微信公众号“爬虫俱乐部”分享实用的stata命令,欢迎转载、打赏。爬虫俱乐部是由李春涛教授领导下的研究生及本科生组成的大数据分析和数据挖掘团队。
此外,欢迎大家踊跃投稿,介绍一些关于stata的数据处理和分析技巧。
投稿邮箱:statatraining@163.com
投稿要求:
1)必须原创,禁止抄袭;
2)必须准确,详细,有例子,有截图;
注意事项:
1)所有投稿都会经过本公众号运营团队成员的审核,审核通过才可录用,一经录用,会在该推文里为作者署名,并有赏金分成。
2)邮件请注明投稿,邮件名称为“投稿+推文名称”。
3)应广大读者要求,现开通有偿问答服务,如果大家遇到关于stata分析数据的问题,可以在公众号中提出,只需支付少量赏金,我们会在后期的推文里给予解答。