python多线程url采集器 + github_利用Python3.5多线程抓取妹子图

很久之前就写了这个爬妹子图的Python爬虫,并且开源到Github上,然而居然没有人给小心心,虽然现在失效了,妹子图网站开启了反爬虫机制,但还是可以作为大家学习的样例,注释也很清晰。

0x01 起因

很多人一开始学习编程技术都是源于兴趣,小东当时看到某博主,居然用Python爬虫批量下载图片,当时就给我震惊了

于是瞬间激发了我的学习兴趣,最后也就促成了这个GetMM爬虫项目。

0x02 分析

拿到妹子图的网站,先对网页结构进行了分析,然后使用python3.5版本,利用BeautifulSoup模块和urlib模块,同时实现了多线程抓取,下载,保存到对应文件夹的整个一个流程。

我知道你们看代码肯定很无聊,所以先放上一张成果图…

0x03 核心代码如下#这是主文件 This is the main file!

#coding: utf-8

import argparse #argparse模块的作用是用于解析命令行参数

import urllib

import requests#urllib的request模块抓取URL内容

import os#系统啦

#看到以上的引入,所以你需要配置这些环境,urllib和BeautifulSoup,我觉得真的是很强大,有Urlib2更新了,学习一波吧!

#不得不说正则表达,给我带来的感觉是非常不错的,这也体现了程序的便利性!-技术改变生活-2017-04-27

from MuchThread import MuchThread #引入多线程

from urllib import request #引入request

from bs4 import BeautifulSoup #BeautifulSoup 4.x引入,beautifulsoup可以从HTML或XML文件中提取(解析)数据的Python库

#得到网页HTML的内容,源代码 get_html(URL)

def get_html(url_address):

#构造请求头的客户端headers

headers = {'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:23.0) Gecko/20100101 Firefox/23.0'}

#urllib.request.Request(url,date,headers)

#获取网页

req = urllib.request.Request(url=url_address,headers=headers)

return urllib.request.urlopen(req)

#小东留名!啊哈哈-www.dyboy.cn

#get_soup(html) 将urlib获取的html封装到bs中,方便文档处理,返回bs的一个实例

def get_soup(html):

#判断是否成功获取了网页

if html == None:

return None

#使用方法BeautifulSoup(markup, "html.parser")

#html.read(),读取当前对象html文档的内容,html转化为unicode编码的,解析成xml

return BeautifulSoup(html.read(), "html.parser")

#get_img_dirs(soup),获取所有相册标题&链接,参数为bs的一个实例,返回字典(key:标题,value:内容)

def get_img_dirs(soup):

#判断对象是否存在

if soup == None:

return None

#bs.find(tag,attributes,recursive,text,keywords)函数

#bs.findAll(tag,attributes,recursive,text,limit,keywords)

#find(id="pic")find(name,attrs,recursive,text,**wargs)

'''这些参数相当于过滤器一样可以进行筛选处理,不同的参数过滤可以应用到以下情况:

查找标签,基于name参数

查找文本,基于text参数

基于正则表达式的查找

查找标签的属性,以及基于attrs参数

基于函数的查找'''

# soup.find(id="pins").findAll(name='li'),找到id="pins",下所有的li标签

lis = soup.find(id="pins").findAll(name='li') # findAll(name='a') # attrs={'class':'lazy'}

if lis != None:

img_dirs = {};#新的存储相册目录字典

for li in lis:

links = li.find('a')#找到li标签下的最近一个a标签内容

alt = links.find('img').attrs['alt']#在a标签内容中找到最近的img的属性alt的值

site = links.attrs['href']#在a标签下的属性href值为相册地址

img_dirs[alt] = site;#alt相册名字,site相册链接

print(img_dirs)#输出获取到的相册字典

return img_dirs#返回字典

#获取相册中的内页图片get_album_num(links, dir_soup),links:链接,get_soup:一个bs对象,返回图片总数

def get_album_num(links, dir_soup):

##############后期修改的地方#######################

#找到links页面下属性class为pagenavi的div

divs = dir_soup.findAll(name='div', attrs={'class':'pagenavi'})

navi = divs[0]#有相同的取第一个

code = navi['class']#code 为 div下class对应的值-pagenavi

links2 = navi.findAll(name='a')

if links2 == None:

return None

a = []

url_list = []

#循环获取div下的数字

for link in links2:

h = str(link['href'])#获取links2下的href的属性值-网址,转化为字符串便于使用str.replace(old, new[, max])

n = h.replace(links+"/", "")#得到字符数字

#异常处理,把int(n)加到a[]的末尾

try:

a.append(int(n))

except Exception as e:

print(e)

_max = max(a)#获取a[]下最大的数字,即为最大页数

for i in range(1, _max):

u = str(links+"/"+str(i))#构造页面链接

url_list.append(u)#添加到链接列表

return url_list#返回链接列表

#获取相册下的图片download_img_from_page(name, page_url)

def download_img_from_page(name, page_url):

dir_html = get_html(page_url)#获取网页HTML

dir_soup = get_soup(dir_html)#封装到bs中

# 得到当前页面的图片

main_image = dir_soup.findAll(name='div', attrs={'class':'main-image'})#找到当前页面下的“main-image”对应的div

if main_image != None:

for image_parent in main_image:

imgs = image_parent.findAll(name='img')#找到img标签的内容

if imgs != None:

img_url = str(imgs[0].attrs['src'])#找到第一个img下属性src的值,转换为字符串

filename = img_url.split('/')[-1]#文件名为src的网址用split分割/,取最后一个作为文件名,避免重复

print("开始下载:" + img_url + ", 保存为:"+filename)

save_file(name, filename, img_url)#保存

#定义保存图片save_file()

def save_file(name, filename, img_url):

print(img_url+"=========")

img = requests.get(img_url)#获取图片

name = str(name+"/"+filename)#文件夹名

#with expresion as variable

with open(name, "wb") as code:

code.write(img.content)

#download_imgs(info):下载图片函数info为一个字典(相册列表)

def download_imgs(info):

if info == None:

return

name = info[0]#album->alt

links = info[1]#album->href

if name == None or links == None:

return None#获取内容失败

print("正在创建相册:" + name +" " + links)

#异常处理

try:

os.mkdir(name)#当前目录创建文件夹 还有makedirs(path[,mode]) mode默认0777

except Exception as e:

print("文件夹:"+name+",已经存在了,呱唧~")

print("正在获取相册《" + name + "》内,图片的数量...")

dir_html = get_html(links)#获取网页内容,返回HTML

dir_soup = get_soup(dir_html)#编码HTML,封装到bs中

img_page_url = get_album_num(links, dir_soup)#获取当前相册下的照片数量

'''

# 得到当前相册的封面,Just for a test!

main_image = dir_soup.findAll(name='div', attrs={'class':'main-image'})

if None != main_image:

for image_parent in main_image:

imgs = image_parent.findAll(name='img')

if None != imgs:

img_url = str(imgs[0].attrs['src'])

filename = img_url.split('/')[-1]

print("开始下载:" + img_url + ", 保存为:"+filename)

save_file(t, filename, img_url)'''

# 获取相册下的图片

for photo_web_url in img_page_url:

download_img_from_page(name, photo_web_url)

#main

if __name__ == '__main__':

parser = argparse.ArgumentParser()#命令行下

parser.add_argument("echo")

# parser.add_argument("url")

# url = int(args.url)

args = parser.parse_args()

url = str(args.echo)

print("开始解析:" + url)

html = get_html(url)#获取用户输入的链接的相册列表网页

soup = get_soup(html)#封装至bs

img_dirs = get_img_dirs(soup)#获取相册的名字及链接

if img_dirs == None:

print("呱唧!无法获取该网页下的相册内容...")

else:

for d in img_dirs:

my_thread = MuchThread(download_imgs, (d, img_dirs.get(d)))

my_thread.start()

my_thread.join()

0x04 总结

其实python写爬虫真的很简单,之前在CSDN上发的文章很细节,同时在Github上有对应的源码,小东就不再赘述了,如果您有任何问题,欢迎交流!

项目开源地址:Github

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值