爬取页面:https://tieba.baidu.com/p/5522091060
现在要将这些图片全部爬下来,具体操作步骤如下:一、Network 抓包
Network 抓包看下返回的数据是否和 Element 一致,即是否包含想要的数据,而不是通过 JS 黑魔法进行加载的。复制下第一个图的图片链接,到 Network 选项卡里的 Response 里查找一下。
二、没有发现Ajax
在 Network 抓包中没有发现 Ajax 动态加载数据的踪迹。
三、点击第二页,抓包发现了 Ajax 加载的痕迹。
四、获取翻页
三个参数猜测 pn 为 page_number,即页数,postman 或者自己写代码模拟请求,记得塞入 Host 和 X-Requested-With,验证 pn=1 是否为第一页数据,验证通过,即所有页面数据都可以通过这个接口拿到。
五、Python实例代码
先加载拿到末页是第几页,然后走一波循环遍历即可解析数据获得图片 url,写入文件,使用多个线程进行下载,详细代码如下:
# 抓取百度贴吧某个帖子里的所有图片 import requests import time import threading import queue from bs4 import BeautifulSoup import chardet import os tiezi_url = "https://tieba.baidu.com/p/5522091060" headers = { 'Host': 'tieba.baidu.com', 'User-Agent': 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KH' 'TML, like Gecko) Chrome/90.0.4430.212 Safari/537.36', } pic_save_dir = 'tiezi_pic/' if not os.path.exists(pic_save_dir): # 判断文件夹是否存在,不存在就创建 os.makedirs(pic_save_dir) pic_urls_file = 'tiezi_pic_urls.txt' download_q = queue.Queue() # 下载队列 # 获得页数 def get_page_count(): try: resp = requests.get(tiezi_url, headers=headers, timeout=5) if resp is not None: resp.encoding = chardet.detect(resp.content)['encoding'] html = resp.text soup = BeautifulSoup(html, 'lxml') a_s = soup.find("ul", attrs={'class': 'l_posts_num'}).findAll("a") for a in a_s: if a.get_text() == '尾页': return a['href'].split('=')[1] except Exception as e: print(str(e)) # 下载线程 class PicSpider(threading.Thread): def __init__(self, t_name, func): self.func = func threading.Thread.__init__(self, name=t_name) def run(self): self.func() # 获得每页里的所有图片URL def get_pics(count): params = { 'pn': count, 'ajax': '1', 't': int(time.time()) } try: resp = requests.get(tiezi_url, headers=headers, timeout=5, params=params) if resp is not None: resp.encoding = chardet.detect(resp.content)['encoding'] html = resp.text soup = BeautifulSoup(html, 'lxml') imgs = soup.findAll('img', attrs={'class': 'BDE_Image'}) for img in imgs: print(img['src']) with open(pic_urls_file, 'a') as fout: fout.write(img['src']) fout.write('\n') return None except Exception: pass # 下载线程调用的方法 def down_pics(): global download_q while not download_q.empty(): data = download_q.get() download_pic(data) download_q.task_done() # 下载调用的方法 def download_pic(img_url): try: resp = requests.get(img_url, headers=headers, timeout=10) if resp.status_code == 200: print("下载图片:" + img_url) pic_name = img_url.split("/")[-1][0:-1] with open(pic_save_dir + pic_name, "wb+") as f: f.write(resp.content) except Exception as e: print(e) if __name__ == '__main__': print("检索判断链接文件是否存在:") if not os.path.exists(pic_urls_file): print("不存在,开始解析帖子...") page_count = get_page_count() if page_count is not None: headers['X-Requested-With'] = 'XMLHttpRequest' for page in range(1, int(page_count) + 1): get_pics(page) print("链接已解析完毕!") headers.pop('X-Requested-With') else: print("存在") print("开始下载图片~~~~") headers['Host'] = 'imgsa.baidu.com' fo = open(pic_urls_file, "r") pic_list = fo.readlines() threads = [] for pic in pic_list: download_q.put(pic) for i in range(0, len(pic_list)): t = PicSpider(t_name='线程' + str(i), func=down_pics) t.daemon = True t.start() threads.append(t) download_q.join() for t in threads: t.join() print("图片下载完毕") |
通过执行上面的代码,我们已经将链接页面里的所有表情包图片都下载到本地了。
不过虽然我们得到了表情包图片,但是由于文件名称都是毫无意义的由字母数字组合成的字符串,不利于我们快速的找到需要的图片,因此我们需要修改一下文件名称。
下篇文章我们通过 OCR 文字识别技术,直接把表情里的文字提出来,然后来命名图片,这样就可以直接文件搜索表情关键字,可以快速找到需要的表情图片。使用谷歌的 OCR 文字识别引擎:Tesseract,对于此类大图片小文字,不太适合,识别率太低,甚至无法识别,这时使用百度云 OCR 比较合适,它能够自动定位到图片中具体位置,并找出图片中所有的文字。