这几日利用闲暇时间自学了python爬虫,来爬取各个有营养的网站。。。。。看着我手上日益厚拙的老茧。。。怎么能不分享出来给大家补充补充营养呢
-------------手动分割线-------------------
介绍下这个小项目,做的是爬取百度贴吧某吧所有贴子中的图片。
为了让大家更好理解这些代码,我们先简要分析一下三个问题,便于有个好思路写代码。
1.我们的目的是什么?
为了获取某吧中所有贴子中的图片。这次实战展示的是美女吧和头像吧。
2.我们的要求是什么?
每个贴中的图片分文件夹存放。
3.达到目的的结果是什么?
???
下面我们从头详细分析
1.首先看图1-1
图1-1
我们可以看到这是美女吧的首页,图片已经标出了我们的目的,就是获取每个贴子中所有的美女图片。
当然了我们的目的不仅仅是这几个,而是本吧许许多多的内容,但是我们发现每页只有50名用户的贴子。
我们可以看到图中url,但是从这个url并不能分析出来多少多少页。我们尝试点击第二页第三页…会发现
第一页url变为了:https://tieba.baidu.com/f?kw=%E7%BE%8E%E5%A5%B3&ie=utf-8&pn=0
第二页url变为了:https://tieba.baidu.com/f?kw=%E7%BE%8E%E5%A5%B3&ie=utf-8&pn=50
第三页url变为了:https://tieba.baidu.com/f?kw=%E7%BE%8E%E5%A5%B3&ie=utf-8&pn=100
现在我们可以分析出每页的url都是遵循一定规则的就是pn后的值每次加50,那我们使用遍历的方法即可获得很多很多页数的内容。
2.我们随便点进一个贴子中(已打码,如有侵权请联系我,及时删除。)
可以看到图上面的url也是遵循一定规则的https://tieba.baidu.com/p/XXXXXXXXX
后面的XXXXXXXX就是每个账号的ID,我们继续尝试别的贴子,发现都是这种规律,那么我们就可以使用遍历的方式获取很多很多页的很多很多用户ID,就可以访问每位用户发的贴子内容,由此爬取每位用户发的图片。
图2-1
3.下面我们看图3-1
假设上面我的讲述你可以明白的话,那么看完这里你的思路应该就很明确了。
我们可以看到途中每个用户发的贴都在名为: “j_thread_list clearfix”的class标签下。
我们还获取了贴子的ID以及标题,那么我们马上就可以抓了,抓取发帖用户的ID,便于下面抓取该ID下的图片。
图3-1
4.分析每位用户帖内的图片
好了,如果上面的内容都可以ok的话,看完这步就可以开始写代码了~
图4-1中的大黑框就是每个楼层信息,看底下的图片url,只要我们获取这个贴子中所有url就可以抓取图片了。
图4-1
代码部分:
本次项目需要引入的模块,如果没有的话百度教程就ok很简单。
from pyquery import PyQuery
import os,time,requests
1.测试连通:
def get_requests(url):
#网址
# url="https://www.dbmeinv.com/?pager_offset=1"
#请求头 --模拟浏览器--
headers = {
"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:64.0) Gecko/20100101 Firefox/64.0"
} #设置一个头,更逼真模拟浏览器访问网页....但是再本次爬虫中到最后我才发现没有调用这个方法,只是再最开始的时候为了测试是否连接成功。
html = requests.get(url=url, headers=headers).content
return html
2.获取账号信息:
#获取账号信息
def get_account(html,listA):
#加html数据
html_py=PyQuery(html)
#获取指定标签 下的内容 便于下面解析出路径
item=html_py(".threadlist_title.pull_left.j_th_tit ").items()
# global count
for each in item:
temp=[]
url_img=each.find("a").attr("href")
name=each.find("a").attr("title")
# print("名称:%s 路径:%s"%(name,url_img))
temp=[name,url_img]
listA.append(temp) #把抓取的所有发帖标题和发帖的ID存入列表中
3.获取图片
def get_image(html,account,name,path):
#为了给获取的图片计数 引入全局变量count
global count
#加html数据
html_py=PyQuery(html)
#获取指定标签 下的内容 便于下面解析出路径
item=html_py(".p_postlist")
a=item(".d_post_content.j_d_post_content ").items()
#获取图片url
for i in a:
url_image=i.find("img").attr("src")
#判断 所获取的图片路径的有效性
if url_image!=None and url_image[-3:]=="jpg":
download_img_url=requests.get(url=url_image).content
with open("%s/"%(path)+str(count)+".jpg","wb") as file:
file.write(download_img_url)
count+=1
print("正在爬取%s的图片,第%s份数据。\n"%(account,count))
#检测文件夹是否写入图片 若为空 则删除
if not os.listdir("%s"%(path)):
os.removedirs("%s"%(path))
4.主函数
def Main(count,listA):
#listA 为了获取 用户账号
for i in range(0,501,50): #获取 十页 用户发出的贴子 url
url=r"https://tieba.baidu.com/f?kw=%E7%BE%8E%E5%A5%B3&ie=utf-8&pn={}".format(i)
#https://tieba.baidu.com/f?kw=%E7%BE%8E%E5%A5%B3&ie=utf-8&pn={} 美女吧
#http://tieba.baidu.com/f?kw=%E5%A4%B4%E5%83%8F&ie=utf-8&pn={} 头像吧
get_account(url,listA)
#遍历出该账号在本吧 发的贴子url
for i in range(len(listA)):
url="http://tieba.baidu.com"+str(listA[i][1])
#如果以账号命名的文件夹不存在 则创建
if not os.path.exists("贴吧2/"+listA[i][1][3:]):
os.makedirs("贴吧2/"+listA[i][1][3:])
#进程相隔0.5秒 以免被拒绝访问 #我也不知道有没有实质作用,测试时发现如果没有进程睡眠这步的话大概获取70-100张图片就被禁止访问了,但是如果每次相隔0.5秒大概获取600张图片还没有被拒绝,或许是我的网络问题,可以自行测试。
time.sleep(0.5)
get_image(url,listA[i][1],listA[i][0],path="贴吧2/"+listA[i][1][3:])
#---------------------------------------美丽的分割线-------------------------------------------
count=0
listA=[]
Main(count,listA) #调用主函数
5.全部代码:
import requests
from pyquery import PyQuery
import os,time
def get_requests(url):
headers = {
"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:64.0) Gecko/20100101 Firefox/64.0"
}
# 请求网络数据 并解码
html = requests.get(url=url, headers=headers).content.decode("utf-8")
return html
#获取账号信息
def get_account(html,listA):
#加html数据
html_py=PyQuery(html)
# print(html_py)
item=html_py(".threadlist_title.pull_left.j_th_tit ").items()
# global count
for each in item:
temp=[]
url_img=each.find("a").attr("href")
name=each.find("a").attr("title")
# print("名称:%s 路径:%s"%(name,url_img))
temp=[name,url_img]
listA.append(temp)
#获取贴中 用户发的图
def get_image(html,account,name,path):
global count
#加html数据
html_py=PyQuery(html)
item=html_py(".p_postlist")
a=item(".d_post_content.j_d_post_content ").items()
#获取图片url
for i in a:
url_image=i.find("img").attr("src")
if url_image!=None and url_image[-3:]=="jpg":
download_img_url=requests.get(url=url_image).content
with open("%s/"%(path)+str(count)+".jpg","wb") as file:
file.write(download_img_url)
count+=1
print("正在爬取%s的图片,第%s份数据。\n"%(account,count))
#检测文件夹是否写入图片 若为空 则删除
if not os.listdir("%s"%(path)):
os.removedirs("%s"%(path))
def Main(count,listA):
#listA 为了获取 用户账号
for i in range(0,501,50):
url=r"https://tieba.baidu.com/f?kw=%E7%BE%8E%E5%A5%B3&ie=utf-8&pn={}".format(i)
#https://tieba.baidu.com/f?kw=%E7%BE%8E%E5%A5%B3&ie=utf-8&pn={} 美女吧
#http://tieba.baidu.com/f?kw=%E5%A4%B4%E5%83%8F&ie=utf-8&pn={} 头像吧
get_account(url,listA)
#遍历出该账号在本吧 发的贴子url
for i in range(len(listA)):
url="http://tieba.baidu.com"+str(listA[i][1])
#如果以账号命名的文件夹不存在 则创建
if not os.path.exists("贴吧2/"+listA[i][1][3:]):
os.makedirs("贴吧2/"+listA[i][1][3:])
#进程相隔0.5秒 以免免被拒绝访问
time.sleep(0.5)
get_image(url,listA[i][1],listA[i][0],path="贴吧2/"+listA[i][1][3:])
#---------------------------------------美丽的分割线-------------------------------------------
count=0
listA=[]
Main(count,listA)
#----------------------------------------------------------------更美的分割线------------------------------------------------------------------
程序实测:
写在最后:自学了几天爬虫,当看到自己写的代码可以运行并能获取到自己想要的东西后,非常的激动开心。第一次写博客教程(本人小白一枚),如有相关技术讲述错误,请提出我会及时更改,谢谢。
再次声明以上图片如有侵权请及时联系博主本人。