概述
最近遇到一个有很多好看图片的网站,然后就想要爬取其中的图片,但是发现访问这个网站没有拦截,访问这个网站的图床就被拦截了。
于是就记录自己遇到的一些问题。
为了保护这个网站,这里就不放出网址。
python 版本:Python 3.11.7
使用到的库:requests selenium bs4 re
使用到的框架:scrapy
问题
1、使用scrapy框架,从网站获取图包信息
以前爬数据用的都是requests+bs4,听说用scrapy就不用自己造轮子了,那就用用看。
一组图片大概几十张,称为一个图包,要获取这个图包的以下信息:
#items.py
class SetusheItem(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
# 图包名
title = scrapy.Field()
# 图包内的图片数量
count = scrapy.Field()
# 图包作者
author = scrapy.Field()
# 图包风格类型
type = scrapy.Field()
# 显示图包信息的网页
base_url = scrapy.Field()
# 显示图包内图片的网页
pic_url = scrapy.Field()
# 图包内所有图片的源网址列表
image_urls = scrapy.Field()
获取图包信息后,设置保存:
# pipelines.py
class SetushePipeline:
path = r'图包信息保存路径' + '\\'
# 用来将 item 对象保存到一个 JSON 文件中
def open_spider(self, spider):
# 打开一个文件,用于写入
self.file = open(self.path + 'image_info.json', 'w', encoding='utf-8')
def process_item(self, item, spider):
# 将 item 对象转换成 JSON 格式的字符串
line = json.dumps(dict(item), ensure_ascii=False) + '\n'
# 写入文件
self.file.write(line)
# 返回 item 对象
return item
def close_spider(self, spider):
# 关闭文件
self.file.close()
最后在spider主体写下获取数据的方法:
#spider主体
class SetusheSpider(scrapy.Spider):
name = "setushe"
allowed_domains = [".com"]
start_urls = [
"https://?"
]
def parse(self, response):
item = SetusheItem()
item['base_url'] = response.url
info = response.xpath('/html/body/div[2]/div[1]/div')[0]
# "/text()"用于去除html标签
item["title"] = info.xpath('./h2[1]/text()').get()
item["count"] = re.search(r'[0-9]+', str(info.xpath('./p[1]/text()').get())).group()
item["author"] = list()
author_list = info.xpath('./p[2]/a')
for author in author_list:
item["author"].append(author.xpath('./text()').get())
item["type"] = list()
type_list = info.xpath('./p[3]/a')
for type in type_list:
item["type"].append(type.xpath('./text()').get())
item["pic_url"] = "https://" + SetuSpider.allowed_domains[0] + info.xpath(
'//a[@class="mdui-btn mdui-btn-block mdui-color-pink"]/@href').get()
# 去调用parse_pic函数,获取图片源网址
yield scrapy.Request(url=item["pic_url"], callback=self.parse_pic, meta={'item': item})
def parse_pic(self, response):
item = response.meta['item']
#使用bs4解析html,感觉更舒服
soup = BeautifulSoup(response.body, 'html.parser')
pic_list = soup.find_all('img', class_='tutu-img detail-image')
pic_bed = 'https://.com'
item['image_urls'] = list()
for pic_url in pic_list:
url = pic_bed + pic_url['data-src']
item['image_urls'].append(url)
yield item
2、获取cookie
原本以为已经获取到图片的源网址了,下载图片是个很简单的事情。
但是突然发现直接访问源网址会被cloudflare拦截,但是先访问图包的网站,再去访问图床就没问题。
于是我就通过浏览器的开发者工具检查两种访问方法请求头的不同之处。
最开始怀疑的是cookies。
因为scrapy刚入门,不熟,于是就用requests。
response = requests.get(
url=url,
headers=headers
)
print(response.cookies)
然后发现没有cookie?
网上查询相关资料,发现可以通过selenium获取cookie。
不过selenium的cookie格式是列表套字典,需要转换一下才是requests的cookie。
session = requests.session()
browser = webdriver.Firefox()
browser.get(
url='https://.com',
)
cookie = browser.get_cookies()
browser.close()
for ck in cookie:
session.cookies.set(ck['name'], ck['value'])
但是获取到了cookie也访问不了图片
3、设置Referer
referer在请求头内,表示访问当前网站前是从哪个网站跳转过来的。
对比请求头发现这个referer也是没有的。
所以就是在验证访问这个图床之前是访问了哪个网站。
那么这下子问题就解决了,其实没有cookie也没事,就是referer要有。
header = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/112.0',
'Referer': 'https://.com/',
}
这样子整个问题就都解决了
总结
再看看我的文章,有惊喜