本博客内容来自韦玮老师网络爬虫课堂笔记,仅用于个人学习和复习,请勿转载用于其他商业用途。
1、爬虫防屏蔽手段之代理服务器
使用代理服务器进行信息爬取,可以很好的解决IP限制的问题。
import urllib.request
def use_proxy(url, proxy_addr):
# 设置代理服务器:49.71.133.38为代理服务器地址,9999为代理服务器端口,中间使用冒号分隔
proxy = urllib.request.ProxyHandler({"http": proxy_addr})
# 由于urllib.request.urlopen不支持很多高级网页,因此使用build_opener方法生成对象
opener = urllib.request.build_opener(proxy, urllib.request.HTTPHandler)# 第二个参数是固定的
# 将opener安装为全局变量
urllib.request.install_opener(opener)
data = urllib.request.urlopen(url).read().decode("utf-8", "ignore")
return data
proxy_addr ='183.154.51.142:9999'
url = "http://www.baidu.com"
data = use_proxy(url, proxy_addr)
print(len(data))
#
39691
我们在运行过程中使用的是西刺的免费代理服务器。其实在操作过程中,基本没有代理服务器可以成功,看来如果想成功的话还是得花钱买专业版的……大部分出错显示如下:
urllib.error.URLError: <urlopen error [WinError 10060] 由于连接方在一段时间后没有正确答复或连接的主机没有反应,连接尝试失败。>
或者
ConnectionResetError: [WinError 10054] 远程主机强迫关闭了一个现有的连接。
或者
urllib.error.URLError: <urlopen error [WinError 10061] 由于目标计算机积极拒绝,无法连接。>
2、图片爬虫实战
图片爬虫,是从互联网中自动把对方服务器上的图片爬下来的爬虫程序。
首先我们登陆淘宝,选择好固定的商品名称,然后将网址复制下来:
https://s.taobao.com/list?spm=a21bo.2017.201867-links-0.23.5af911d9ptYTpF&q=%E8%83%8C%E5%BF%83%E5%90%8A%E5%B8%A6&cat=16&style=grid&seller_type=taobao
https://s.taobao.com/list?spm=a21bo.2017.201867-links-0.23.5af911d9ptYTpF&q=%E8%83%8C%E5%BF%83%E5%90%8A%E5%B8%A6&cat=16&style=grid&seller_type=taobao&bcoffset=0&s=60
https://s.taobao.com/list?spm=a21bo.2017.201867-links-0.23.5af911d9ptYTpF&q=%E8%83%8C%E5%BF%83%E5%90%8A%E5%B8%A6&cat=16&style=grid&seller_type=taobao&bcoffset=0&s=120
https://s.taobao.com/list?spm=a21bo.2017.201867-links-0.23.5af911d9ptYTpF&q=%E8%83%8C%E5%BF%83%E5%90%8A%E5%B8%A6&cat=16&style=grid&seller_type=taobao&bcoffset=0&s=180
通过观察我们可以发现,在q=至&cat之间就是我们要搜索的商品的名字,而最后的s=60则代表页码,第一页为0,第二页为60,第三页为120,以此类推。因此,我们的网址可以简化为:
https://s.taobao.com/list?spm=a21bo.2017.201867-links-0.23.5af911d9ptYTpF&q=“商品名称”&cat=16&style=grid&seller_type=taobao&bcoffset=0&s=“页码数”
至此,我们就分析出了网址的构造。然后我们对网址的图片进行分析。
我们选中一张图片右键复制图片网址,并在新的浏览页面中打开,得到了一张小图片,这貌似不是我们想要的:
然后我们打开页面源代码,在其中搜索图片的网址,并不能搜索到任何东西:
但是这不意味着,图片信息一定隐藏在JS中了。
我么再观察一下图片的网址:
我们把无关紧要的部分去掉,逐步留下核心的部分:
然后我们复制这个部分,再回到源码页面去找,果然找到了:
图片显示的格式如下:
g-search3.alicdn.com/img/bao/uploaded/i4/i1/51486753/O1CN01ZzJl9p1zkvCCizIQK_!!51486753.jpg
现在我们知道,这个就是图片存放在服务器上的地址。虽然没有http协议,但是我们在构造网址的时候可以将它构造出来。我们在浏览器中输入地址,可以发现这张图片是高清版原图而非缩略图:
这样,我们就可以用正则表达式来提取图片地址了。代码如下:
import urllib.request
import re
keyname = "背心吊带" # 如果希望搜索多次词,可以建一个列表,通过for循环执行
# 由于不识别中文,我们需要将中文进行编码
key = urllib.request.quote(keyname)
headers = ("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.81 Safari/537.36 SE 2.X MetaSr 1.0")
opener = urllib.request.build_opener()
opener.addheaders = [headers]
urllib.request.install_opener(opener)
for i in range(0, 3):
url = "http://s.taobao.com/list?spm=a21bo.2017.201867-links-0.23.5af911d9ptYTpF&q=" + key + "&cat=16&style=grid&seller_type=taobao&bcoffset=0&s=" + str(i*60)
data = urllib.request.urlopen(url).read().decode("utf-8", "ignore")
pat = 'pic_url":"//(.*?)"'
image_list = re.compile(pat).findall(data) # 所有图片的网址
for j in range(0, len(image_list)):
this_image = image_list[j]
this_image_url = "http://" + this_image
file = "D:/PROGRAMMING/数据分析/Python数据分析与挖掘实战视频教程/实验/img/" + str(i) + str(j) + ".jpg"
urllib.request.urlretrieve(this_image_url, filename=file)
看老师的视频,确实是成功了,我自己这个代码,毛都没爬下来……然后我换了个火狐浏览器,还是毛都没爬下来……
这就是传说中的脸黑吧……
然后我把老师的源码复制过来,改动了文件存储地址,报头那块也做了适当调整,发现还是啥也没有,说明这套技术已经不能在淘宝上面爬图了吗?我也搞不清……
3、实战:爬取千图网高清图片
import urllib.request
import re
import urllib.error
for i in range(1, 10):
url = "https://www.58pic.com/piccate/10-0-0-p0" + str(i) + ".html"
data = urllib.request.urlopen(url).read().decode("utf-8", "ignore")
pat = '<img class="lazy" data-original="//(.*?).jpg!'
image_list = re.compile(pat).findall(data)
for j in range(0, len(image_list)):
try:
this_image = image_list[j]
this_image_url = "http://" + this_image + ".jpg!w1024_new_0"
file = "D:/PROGRAMMING/数据分析/Python数据分析与挖掘实战视频教程/实验/img/" + str(i) + str(j) + ".jpg"
urllib.request.urlretrieve(this_image_url, filename=file)
print("第" + str(i) + "页第" + str(j) + "个图片爬取成功...")
except urllib.error.URLError as e:
if hasattr(e, "code"):
print(e.code)
if hasattr(e, 'reason'):
print(e.reason)
except Exception as e:
print(e)
#
第1页第0个图片爬取成功...
第1页第1个图片爬取成功...
第1页第2个图片爬取成功...
第1页第3个图片爬取成功...
第1页第4个图片爬取成功...
第1页第5个图片爬取成功...