700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > Python Selenium+Requests爬虫[双线程]--今日头条图片爬取【亲测能行!!!】

Python Selenium+Requests爬虫[双线程]--今日头条图片爬取【亲测能行!!!】

时间:2024-04-14 21:45:11

相关推荐

Python Selenium+Requests爬虫[双线程]--今日头条图片爬取【亲测能行!!!】

码前冷静分析

首先需要准备好selenium、requests库以及Chromedriver

这个就不细说了,有很多博客可以参考

然后讲一下大体思路

框架大体如下

框架是个大体思路(草稿),写代码的时候可以灵活来

def get_list(url): #目的是根据关键词搜索,抓取每一条结果的图片链接lst = []browser = webdriver.Chrome()wait = ww(browser, 10)#……等等等等return lst#胡乱摸索了线程简单的应用,就copy了另一个一样的下载函数def download_pic1(lst): #逐一遍历列表中的图片链接,下载美图return ''def download_pic2(lst): #逐一遍历列表中的图片链接,下载美图return ''def main(): global keywordkeyword = '鬼刀'basic_url = '/'lst = get_list(basic_url) #访问主页,搜索,收集结果的图片链接,返回列表download_pic(lst) #根据链接下载图片#就是这么小白式的简单粗暴,水平还不够,暂时就只弄两个函数吧#虽然是有点臃肿了,嘤嘤嘤

先声明下,本人是个小白,可能思路,代码存在一些个问题这里还请大家多多指教

完整代码在文末

开 码

首先把要用的库给喊粗来

库,函数的使用介绍有很多超棒的博客,本文会给出部分链接
好的,上代码

import requestsfrom time import sleepimport osimport os.path as opfrom selenium import webdriverfrom mon.by import Byfrom selenium.webdriver.support import expected_conditions as ECfrom selenium.webdriver.support.wait import WebDriverWait as wwimport threading

1.1 访问今日头条首页,关键词传送及点击搜索

def get_list(basic_url):lst = []browser = webdriver.Chrome()wait = ww(browser, 10)try:browser.get(basic_url)#找到搜索框节点input = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, '#rightModule > div.search-wrapper > div > div > div > input')))#找到搜索按钮节点click = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, '#rightModule > div.search-wrapper > div > div > div > div > button')))input.send_keys(keyword) #模拟传入搜索词sleep(2) #输入后停一下,要不然立马让你验证,来自小白的喵喵喵click.click() #模拟点击搜索按钮except Exception as er:print(er)

# 两个节点的查找看下图

节点查找~超详细解答如下博文

博主 Eastmount 原创

【[python爬虫] Selenium常见元素定位方法和操作的学习介绍】

wait用法详解~如下链接

博主 不码不成才 原创

【python+selenium中的wait事件】

CSS选择器用法介绍~博文链接如下

博主 MXuDong 原创

CSS选择器——cssSelector定位方式详解

到主页后右键—>检查—>开找
-首先是输入框查找(按照图示顺序很快就找到啦)
-然后右键点击节点,copy—>copy selector

啦啦啦~

接下来同样找到搜索按扭
同样的操作,只是要注意复制对节点信息哦

|

节点查找~超详细解答如下博文

博主 Eastmount 原创

【[python爬虫] Selenium常见元素定位方法和操作的学习介绍】

wait用法详解~如下链接

博主 不码不成才 原创

【python+selenium中的wait事件】

CSS选择器用法介绍~博文链接如下

博主 MXuDong 原创

CSS选择器——cssSelector定位方式详解

这样就进入到了搜索结果界面,接下来就是让它加载出更多结果,通过模拟滑动来实现

1.2 接下来便是模拟滑动页面,出加载更多结果,上码

# 首先把browser切换到当前搜索结果的页面browser.switch_to.window(browser.window_handles[1])#滑动多少自己可以任意发挥for i in range(0, 2001, 250):#下边这个方法来模拟滚动屏幕(详解可以参考其它博客)browser.execute_script(f'window.scrollBy(0, {i})')sleep(2)#滑的差不多了,您是不是该寻思着收集进入结果的''门''了?clicks = wait.until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, '.link.title')))

模拟滑动所用的方法【execute_script()】相关博客链接如下。

【博主 吾爱乐享 原创-----python学习之滚动页面函数execute_script】

+

【博主 qq_16069927 原创 ----selenium 如何控制滚动条逐步滚动】

来一起找这’'门’‘吧!

经过观察以及实践,点击标题链接可以进子入页面,就是你了皮卡丘!(就是蓝色阴影那个节点)首先观察,class有两个属性,所以CSS选择器因该是 ‘.link.title’,既然找到了,就都收集起来吧,哈哈

1.3 接下来,就开始邪恶的循环,打开子页面->回到搜索结果页->打开子页面->回到搜索结果页……

别问为什么,问就是网速慢,先打开页面,让成熟的它自己加载着,然后挨个收割美图链接不要问为什么不找到链接当时就给图片给下了,问就是缺少仪式感。

上码!

for clc in clicks[1:10]: # 搜索结果打开数自己定,我是因为穷,惨,所以就10个吧(嘤嘤嘤)clc.click()#进入子页面后,趁它不注意,赶快回到结果页browser.switch_to.window(browser.window_handles[1])sleep(4)

1.4 然后开始收割美图链接吧,哈哈!

上码!

for num in range(len(browser.window_handles) - 2):#逐个进入子页面browser.switch_to.window(browser.window_handles[num + 2])#等待所有图片节点加载粗来,收集它try: #可能会遇到视频界面,到时候这里判断错误就不管,进入下一个img = wait.until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, 'img[src]')))except:pass#提取链接到列表for mg in img:url = mg.get_attribute('src')if url.startswith('http://p') and 'thumb' not in url:lst.append(url)

老问题,找节点,上图!!!

通过分析,可以看出,文章中图片链接都在图中红线标注的 ‘路径’内,所以……
可以构造一个CSS选择器,筛选出所有含图链接节点 ,通过实战,发现有两种页面:
常见的一种是一页到底那种,图片在-> ‘.article-content div .pgc-img img[src]’,
另一种是跟ins一样左右切换那种
两种页面图片节点路径就不一样了,但是标签名都是<img>属性都是’src’,所以选择器就粗糙一点"img[src]"
这样就需要筛选一下了,粗糙的选择器就会获取到一些广告图,实战发现,广告图链接几乎都是’https://……”而图片链接是“http://……”这就很妙了,如代码

【这里很粗糙,还是可能会爬到不相关的,flag:以后有时间再改进改进】

2.接下来就是下载了!

这里我后来翻了一些优秀博客,胡乱摸索,写了个very简单(因为菜)的双线程下载
说白了就是同时运行两个下载函数,男人嘛,不能叫快要叫效率

上码

def download_pic1():#单独搞个文件夹存一下path = r'C:\Users\PXO\Desktop\杂\Toutiao_pic\\' + keywordif not op.exists(path):os.mkdir(path)ln = len(lst)id = [i for i in range(ln)]cnt = 1for url in lst[:ln//2]:#负责前半部分列表下载#开始搞事情,遍历图片链接,get get get!r = requests.get(url)#这里设置文件保存路径(含文件名)pic_path = path + '\\' + f'{keyword}_pic_{id.pop(0)}.jpg'#以二进制写入方式打开命名好的文件with open(pic_path, 'wb+') as ff:#写入获取到的图片(二进制)//养成好习惯,随手关闭ff.write(r.content)ff.close()#下边是一个小优化,刷新显示当前下载状态op1 = cnt*120//lnen = 60 - op1opp, enn = '-'*op1, '*'*enprint(f'\r[1]下载ing:已下{cnt}/{ln//2}张,[{opp}>{enn}] {(2 * cnt) / len(lst):.1%}', end='')cnt += 1#下边copy一下就是另一个啦def download_pic2():path = r'C:\Users\PXO\Desktop\杂\Toutiao_pic\\' + keywordif not op.exists(path):os.mkdir(path)ln = len(lst)id = [i for i in range(ln)]id.reverse()cnt = 1for url in lst[ln//2:]:#负责下载后半部分r = requests.get(url)pic_path = path + '\\' + f'{keyword}_pic_{id.pop(0)}.jpg'with open(pic_path, 'wb+') as ff:ff.write(r.content)ff.close()op1 = cnt*120//lnen = 60 - op1opp, enn = '-'*op1, '*'*enprint(f'\r[2]下载ing:已下{cnt}/{ln//2}张,[{opp}>{enn}] {(2 * cnt) / len(lst):.1%}', end='')cnt += 1

小说明:这里就不传参数了,直接把列表定义为全局变量

线程的代码,还有博客参考如下

#大家可以参考下面给出的优秀博客threads = []th1 = threading.Thread(target=download_pic1)threads.append(th1)th2 = threading.Thread(target=download_pic2)threads.append(th2)for th in threads:th.setDaemon(True)th.start()th.join()

参考博客链接
[博主 n_laomomo 原创]----Python多线程threading用法
较详细介绍
【博主 DrStream 原创】----python:threading.Thread类的使用详解

奉上完整代码

注意:爬取的时候会出现超时,然后就over了,除了使用try来’试错‘,还可以适当用一下time库的sleep()

import requestsfrom time import sleepimport osimport os.path as opfrom selenium import webdriverfrom mon.by import Byfrom selenium.webdriver.support import expected_conditions as ECfrom selenium.webdriver.support.wait import WebDriverWait as wwimport threadingdef get_list(basic_url):'''#这里是无界面浏览器相关操作,不想要弹出界面的话,#把下边那行换成这些就okbrowser_options = webdriver.ChromeOptions()browser_options.add_argument('--headless')browser = webdriver.Chrome(options=browser_options)'''browser = webdriver.Chrome() #这行就是那行(手动滑稽)wait = ww(browser, 20)try:browser.get(basic_url)print('访问成功!!')sleep(1)input = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, '#rightModule > div.search-wrapper > div > div > div > input')))click = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, '#rightModule > div.search-wrapper > div > div > div > div > button')))input.send_keys(keyword)sleep(2)click.click()sleep(1)print('搜索成功!')browser.switch_to.window(browser.window_handles[1])for i in range(0, 2001, 250):browser.execute_script(f'window.scrollBy(0, {i})')print(f'\r加载中。。。{i/2000:.1%}', end='')sleep(3)print('')clicks = wait.until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, '.link.title')))cnt = 0want = 10 ## 爬取页面数 for clc in clicks[: want]: clc.click()sleep(2)cnt += 1browser.switch_to.window(browser.window_handles[1])print(f'\r已打开{cnt}个界面,比例{cnt/want:.2%}', end='')print()for num in range(want):browser.switch_to.window(browser.window_handles[num + 2])try:img = wait.until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, 'img[src]'))) #.article-content div .pgc-img img[src]except:passfor mg in img:url = mg.get_attribute('src')if url.startswith('http://p'):lst.append(url)except Exception as t:print(t)def download_pic1():path = r'C:\Users\PXO\Desktop\杂\Toutiao_pic\\' + keywordif not op.exists(path):os.mkdir(path)ln = len(lst)id = [i for i in range(ln)]cnt = 1for url in lst[:ln//2]:r = requests.get(url)pic_path = path + '\\' + f'{keyword}_pic_{id.pop(0)}.jpg'with open(pic_path, 'wb+') as ff:ff.write(r.content)ff.close()op1 = cnt*120//lnen = 60 - op1opp, enn = '-'*op1, '*'*enprint(f'\r[1]下载ing:已下{cnt}/{ln//2}张,[{opp}>{enn}] {(2 * cnt) / len(lst):.1%}', end='')cnt += 1def download_pic2():path = r'C:\Users\PXO\Desktop\杂\Toutiao_pic\\' + keywordif not op.exists(path):os.mkdir(path)ln = len(lst)id = [i for i in range(ln)]id.reverse()cnt = 1for url in lst[ln//2:]:r = requests.get(url)pic_path=path+'\\'+f'{keyword}_pic_{id.pop(0)}.jpg'with open(pic_path, 'wb+') as ff:ff.write(r.content)ff.close()op1 = cnt*120//lnen = 60 - op1opp, enn = '-'*op1, '*'*enprint(f'\r[2]下载ing:已下{cnt}/{ln//2}张,[{opp}>{enn}] {(2 * cnt) / len(lst):.1%}', end='')cnt += 1def main():global keyword, lstlst = []keyword = '鬼刀' basic_url = '/'get_list(basic_url)threads = []th1=threading.Thread(target=download_pic1)threads.append(th1)th2=threading.Thread(target=download_pic2)threads.append(th2)for th in threads:th.setDaemon(True)th.start()th.join()main()

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。