爬虫获取二次元图片
爬虫准备
本次我们以http://animepicsx.net/网站为例。爬虫首先要确定的是爬虫的合法性,需要在爬取前查看网站的robots.txt,打开http://animepicsx.net/robots.txt,查看权限,并没有不允许爬取的内容,于是可以开始着手爬取了。
知识准备
需要了解python及其正则表达式,html,js和http请求相关知识,这里不再赘述。
工具准备
爬取时使用python较为方便,python语言简单且库丰富,这次使用正则匹配的方式做爬虫,需要准备以下库,可以使用pip或conda安装(视你的环境而定):
- requests库
- re库
另外本次为方便使用anaconda的jupyter lab进行开发
寻找网页并爬取
首先我们需要查看网页结构,还是以图片为主,在按住F12后刷新网页:
右侧出现了网页的html结构。
选中右侧窗口左上角的箭头
再选中其中任一张图片
该元素所对应的部分就会颜色加深。
<img data-original="https://pics.animepicsx.net/images/PRQ/XUg/SxYUeL4m_r_300.jpeg" alt="" width="300" height="318" class="lazy" src="https://pics.animepicsx.net/images/PRQ/XUg/SxYUeL4m_r_300.jpeg" style="">
这样我们就清楚了图片来源,正是https://pics.animepicsx.net/images/PRQ/XUg/SxYUeL4m_r_300.jpeg
原图还是剪裁后的版本: 注意到url最后有“_300”的字样,这表明图片是经过大小规范化的版本,去掉后就是原图https://pics.animepicsx.net/images/PRQ/XUg/SxYUeL4m_r.jpeg。
同时这个网站有很多的tags,如果想要tags的话就不应在这个地方直接获取图片,而是到他的详细页面中获取,
继续观察网页结构,发现点击的a标签的href为“/37418”,这是详细页的具体地址,
即 http://animepicsx.net/37418。
进入http://animepicsx.net/37418,同样的步骤,查看网页结构,用之前提到的箭小头点击tags的部分,一个部分亮了起来:
这里的各种a标签中间的东西便是需要的tag文本
好的,思路已经清楚了,接下来就该动手实践了
爬取并保存
先写一个初始版本代码import requests
import re
root_url = "http://animepicsx.net/"
root_html = requests.get(root_url)
#将html文本里的\n都换为空
root_html_text = root_html.text.replace("\n", "")
# print(root_html.text)
re_pattern = re.compile('<ahref="(/\d+)" class="card-image js_open_pic" target="_blank"data-img="https://.*?.jpeg" data-id="\d+"><imgdata')
detail_urls = re_pattern.findall(root_html_text);
# print(detail_urls)
发现结果只有一点数据
['/37419', '/37417', '/37416', '/37415', '/37414', '/37413', '/37411', '/37409', '/37408', '/37407', '/37406', '/37405', '/37402', '/37400', '/37397', '/37396', '/37391', '/37390', '/37379', '/37359', '/37377', '/37358', '/37376', '/37357', '/37375', '/37356']
但是数据十分有规律,于是再试试‘/5’可不可以,发现果然可以
所以之后这些网页的编号可以自行规定了,只要不超出范围即可,目前假设范围在37000张以内,之后就只需爬取具体网页即可。
先试着爬取37000的tags和高清图,
import requests
import re
detail_url = "http://animepicsx.net/" + "/37000"
detail_html = requests.get(detail_url);
# 得到具体内容后根据内容调整格式,将一些特殊字符替换
# detail_html_text = detail_html.text.replace("\n", " ")
# print(detail_html_text)
#进行正则匹配
re_pattern = re.compile('<img src="(https://pics\.animepicsx\.net/images/.*?\.jpeg)" class="z-depth-4 responsive-img">')
detail_img = re_pattern.findall(detail_html_text)
print(detail_img)
运行后果然可以获得正常的图片url。
再试着获取tags:
import requests
import re
detail_url = "http://animepicsx.net/" + "/37000"
detail_html = requests.get(detail_url);
# 得到具体内容后根据内容调整格式,将一些特殊字符替换
# detail_html_text = detail_html.text.replace("\n", " ")
# print(detail_html_text)
#进行正则匹配
re_pattern = re.compile('<img src="(https://pics\.animepicsx\.net/images/.*?\.jpeg)" class="z-depth-4 responsive-img">')
detail_img = re_pattern.findall(detail_html_text)
# print(detail_img)
re_pattern = re.compile('<a href="/site/tag\?tag=(.*?)">#.*?</a>')
detail_tags = re_pattern.findall(detail_html_text)
print(detail_tags)
果然可以获得结果,与网站上的相同
接下来就是尝试保存图片和tags到本地,不妨就用刚刚获得的数据:
首先在本地新建一个image文件夹,名字可以在代码中改
img_url = 'https://pics.animepicsx.net/images/oH5/YS3/XRYxZJj9Vo.jpeg'
img_tags = ['blush', 'brown-hair', 'anthropomorphism', 'yellow-eyes', 'food', 'christmas']
img_data = requests.get(img_url)
img_file = open("./image/" + "37000" + ".jpeg", 'wb')
img_file.write(img_data.content)
img_file.close()
tags_file = open("./tags/" + "37000" + ".txt", 'w')
for tag in img_tags:
tags_file.write(tag + "\n")
tags_file.close()
尝试后发现可以获得图片和tags文件,成功
接下来进行初始化准备:
# 添加os
import os
def main():
# 创建文件夹,路径需要自己更改
root_dir = "your_path"
image_dir = root_dir + "/image"
tags_dir = root_dir + "/tags"
if not os.path.exists(image_dir):
os.makedirs(image_dir)
if not os.path.exists(tags_dir):
os.makedirs(tags_dir)
将各种代码化为函数
import requests
import re
import os
def save_img_and_tags(img_dir, tags_dir, img_id, img_url, img_tags):
img_data = requests.get(img_url)
img_format = ".jpge"
#可能有多种格式,需要的话再添加
if img_url[-4: -1] == ".pn":
img_format = ".png"
img_file = open(img_dir + "/" + img_id + img_format, 'wb')
img_file.write(img_data.content)
img_file.close()
tags_file = open(tags_dir + "/" + img_id + ".txt", 'w')
for tag in img_tags:
tags_file.write(tag + "\n")
tags_file.close()
'''
获取该网站中特定imgId的图片和tags
@Params String imgId
'''
def get_target_message(image_dir, tags_dir, img_id):
detail_url = "http://animepicsx.net/" + img_id
detail_html = requests.get(detail_url)
detail_html_text = detail_html.text
# print(detail_html_text)
re_pattern = re.compile('<img\nsrc="(https://pics\.animepicsx\.net/images/.*?)" class="z-depth-4 responsive-img">')
detail_img = re_pattern.findall(detail_html_text)
#print(detail_img)
img_url = detail_img[0]
re_pattern = re.compile('<a\nhref="/site/tag\?tag=(.*?)">#.*?</a>')
detail_tags = re_pattern.findall(detail_html_text)
print("tags: ", detail_tags)
save_img_and_tags(image_dir, tags_dir, img_id, img_url, detail_tags)
def main():
# 创建文件夹
root_dir = "your_path"
image_dir = root_dir + "/image"
tags_dir = root_dir + "/tags"
# 规定网站图片张数,与网站更新到的索引有关,目前最大约37300
image_arrange = [30000, 30010]
if not os.path.exists(image_dir):
os.makedirs(image_dir)
if not os.path.exists(tags_dir):
os.makedirs(tags_dir)
for i in range(image_arrange[0], image_arrange[1]):
get_target_message(image_dir, tags_dir, str(i))
另外错误处理是少不了的,在获取url后应检查是否为空,并在主函数中加入try,except处理部分,即是完整代码
import requests
import re
import os
def save_img_and_tags(img_dir, tags_dir, img_id, img_url, img_tags):
img_data = requests.get(img_url)
img_format = ".jpge"
if img_url[-4: -1] == ".pn":
img_format = ".png"
img_file = open(img_dir + "/" + img_id + img_format, 'wb')
img_file.write(img_data.content)
img_file.close()
tags_file = open(tags_dir + "/" + img_id + ".txt", 'w')
for tag in img_tags:
tags_file.write(tag + "\n")
tags_file.close()
'''
获取该网站中特定imgId的图片和tags
@Params String imgId
'''
def get_target_message(image_dir, tags_dir, img_id):
detail_url = "http://animepicsx.net/" + img_id
detail_html = requests.get(detail_url)
detail_html_text = detail_html.text
# print(detail_html_text)
re_pattern = re.compile('<img\nsrc="(https://pics\.animepicsx\.net/images/.*?)" class="z-depth-4 responsive-img">')
detail_img = re_pattern.findall(detail_html_text)
#print(detail_img)
if len(detail_img) != 1:
raise Exception("图片获取失败")
else:
print("imgurl: " + detail_img[0])
img_url = detail_img[0]
re_pattern = re.compile('<a\nhref="/site/tag\?tag=(.*?)">#.*?</a>')
detail_tags = re_pattern.findall(detail_html_text)
print("tags: ", detail_tags)
save_img_and_tags(image_dir, tags_dir, img_id, img_url, detail_tags)
def main():
# 创建文件夹
root_dir = "D:/program/humanPos2D"
image_dir = root_dir + "/image"
tags_dir = root_dir + "/tags"
# 规定网站图片张数,与网站更新到的索引有关,目前最大约37300
image_arrange = [30000, 30010]
if not os.path.exists(image_dir):
os.makedirs(image_dir)
if not os.path.exists(tags_dir):
os.makedirs(tags_dir)
for i in range(image_arrange[0], image_arrange[1]):
try:
get_target_message(image_dir, tags_dir, str(i))
print(str(i) + " succeed!")
except Exception as e:
print(str(i) + " error: ", e)
main()
完成,可以看到文件夹里都有了可以使用的图片及tags
代码放在github了,可以去看看,Try and Enjoy!