使用webdriver+urllib爬取网页数据(模拟登陆,过验证码)
目录
urilib是python的标准库,当我们使用Python爬取网页数据时,往往用的是urllib模块,通过调用urllib模块的urlopen(url)方法返回网页对象,并使用read()方法获得url的html内容,然后使用BeautifulSoup抓取某个标签内容,结合正则表达式过滤。但是,用urllib.urlopen(url).read()获取的只是网页的静态html内容,很多动态数据(比如网站访问人数、当前在线人数、微博的点赞数等等)是不包含在静态html里面的,例如我要抓取这个bbs网站中点击打开链接 各个板块的当前在线人数,静态html网页是不包含的(不信你查看页面源代码试试,只有简单的一行)。像这些动态数据更多的是由JavaScript、JQuery、PHP等语言动态生成的,因此再用抓取静态html内容的方式就不合适了。
本文将通过selenium webdriver模块的使用,以获取这些动态生成的内容,尤其是一些重要的动态数据。其实selenium模块的功能不是仅仅限于抓取网页,它是网络自动化测试的常用模块,在Ruby、Java里面都有广泛使用,Python里面虽然使用相对较少,但也是一个非常简洁高效容易上手的自动化测试模块。通过利用selenium的子模块webdriver的使用,解决抓取动态数据的问题,还可以对selenium有基本认识,为进一步学习自动化测试打下基础。
一 环境配置
1.1 selenium 驱动下载
如果你是用的是火狐浏览器,下载geckodriver.exe:
下载地址:https://github.com/mozilla/geckodriver/releases请根据系统版本选择下载;(如Windows 64位系统)
下载解压后将getckodriver.exe复制到Firefox的安装目录下,
如(C:\Program Files\Mozilla Firefox),并在环境变量Path中添加路径:C:\Program Files\Mozilla Firefox
如果你使用的是谷歌浏览器,下载chromedriver.exe:
下载地址https://npm.taobao.org/mirrors/chromedriver/请根据炼器版本选择下载。
1.2 安装selenium
pip install selenium
1.3 安装beautifulsoup4
Beautiful Soup 是一个可以从HTML或XML文件中提取数据的Python库.它能够通过你喜欢的转换器实现惯用的文档导航。
pip install beautifulsoup4
pip install lxml
pip install html5lib
1.4 安装faker
pip install faker
二 如何爬取落网某一期数据信息
2.1 目标页面分析
落网的网址是http://www.luoo.net,我们利用火狐浏览器打开该网址,随便选择一期音乐,这里我点击的是摇滚,
然后点击F12,选择第989期,进入该页面,我们就以爬取这一页的内容为例:
进入之后,我们可以看到该网页主要包括以下内容:期刊编号,期刊标题,期刊封面,期刊描述,歌单。
通过下方开发工具中的查看器,可以获取我们感兴趣数据的标签,选择器等信息。以歌单为例:
2.2 程序代码
程序代码如下:
# -*- coding: utf-8 -*- """ Created on Thu May 24 16:35:36 2018 @author: zy """ import os from bs4 import BeautifulSoup import random from faker import Factory import queue import threading import urllib.request as urllib from selenium import webdriver import time #"gbk" codec can't encode character "\xXX" in position XX : https://www.cnblogs.com/feng18/p/5646925.html #即字符编码是utf-8的字节,但是并不能转换成utf-8编码的字符串 ''' 爬取网页信息的类 ''' def random_proxies(proxy_ips): ''' 从proxy_ips中随机选取一个代理ip args: proxy_ips:list 每个元素都是一个代理ip ''' ip_index = random.randint(0, len(proxy_ips)-1) res = { 'http': proxy_ips[ip_index] } return res def fix_characters(s): ''' 替换掉s中的一些特殊字符 args: s:字符串 ''' for c in ['<', '>', ':', '"', '/', '\\', '|', '?', '*']: s = s.replace(c, '') return s def get_static_url_response_html(url): ''' 爬取静态页面数据:https://www.crummy.com/software/BeautifulSoup/bs4/doc/index.zh.html#find reture: 返回html代码 ''' fake = Factory.create() # 这里配置可用的代理IP,可以写多个 proxy_ips = [ '183.129.151.130' ] headers = {'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'Accept-Charset':'GB2312,utf-8;q=0.7,*;q=0.7', 'Accept-Language':'zh-cn,zh;q=0.5', 'Cache-Control':'max-age=0', 'Connection':'keep-alive', 'Host':'John', 'Keep-Alive':'115', 'Referer':url, 'User-Agent': fake.user_agent() #'User-Agent': 'User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36' } req = urllib.Request(url=url,origin_req_host=random_proxies(proxy_ips),headers = headers) #当该语句读取的返回值是bytes类型时,要将其转换成utf-8才能正常显示在python程序中 response = urllib.urlopen(req).read() #需要进行类型转换才能正常显示在python中 response = response.decode('utf-8') return response def download(url,dstpath=None): ''' 利用urlretrieve()这个函数可以直接从互联网上下载文件保存到本地路径下 args: url:网页文件或者图片以及其他数据路径,尽量不要下载网页,因为下载的是静态网页 dstpath:保存全路况 ''' if dstpath is None: dstpath = './code.jpg' try: urllib.urlretrieve(url,dstpath) print('Download from {} finish!'.format(url)) except Exception as e: print('Download from {} fail!'.format(url)) def get_dynamic_url_response_html(url): ''' selenium是一个用于Web应用自动化程序测试的工具,测试直接运行在浏览器中,就像真正的用户在操作一样 selenium支持通过驱动真实浏览器(FirfoxDriver,IternetExplorerDriver,OperaDriver,ChromeDriver) selenium支持通过驱动无界面浏览器(HtmlUnit,PhantomJs) 1、下载geckodriver.exe:下载地址:https://github.com/mozilla/geckodriver/releases请根据系统版本选择下载;(如Windows 64位系统) 2、下载解压后将getckodriver.exe复制到Firefox的安装目录下, 如(C:\Program Files\Mozilla Firefox),并在环境变量Path中添加路径:C:\Program Files\Mozilla Firefox return: 返回html代码 获取url页面信息后关闭连接 ''' browser = webdriver.Firefox(executable_path = r'D:\ff\geckodriver.exe') #html请求 browser.get(url) html = browser.page_source time.sleep(2) #html = browser.page_source.decode('utf-8') #关闭浏览器 browser.quit() return html class UrlSpyder(threading.Thread): ''' 使用Threading模块创建线程:http://www.runoob.com/python/python-multithreading.html 使用Threading模块创建线程,直接从threading.Thread继承,然后重写__init__方法和run方法: 主要思路分成两部分: 1.用来发起http请求分析出播放列表然后丢到队列中 2.在队列中逐条下载文件到本地(如果需要下载文件) 一般分析列表速度较快,下载速度比较慢,可以借助多线程同时进行下载 ''' def __init__(self, base_url, releate_urls, que=None): ''' args: base_url:网址 releate_urls:相对于网址的网页路径 list集合 que:队列 Python的queue模块中提供了同步的、线程安全的队列类,包括FIFO(先入先出)队列Queue,LIFO(后入先出)队列LifoQueue, 和优先级队列PriorityQueue。这些队列都实现了锁原语,能够在多线程中直接使用。可以使用队列来实现线程间的同步。 ''' threading.Thread.__init__(self) print('Start spider\n') print ('=' * 50) #保存字段信息 self.base_url = base_url if queue is None: self.queue = queue.Queue() else: self.queue = que self.releate_urls = releate_urls def run(self): ''' 把要执行的代码写到run函数里面 线程在创建后会直接运行run函数 ''' #遍历每一个网页 并开始爬取 for releate_url in self.releate_urls: self.spider(releate_url) print ('\nCrawl end\n\n') def spider(self, releate_url): ''' 爬取指定网页数据,并提取我们所需要的网页信息的函数 args: releate_url:网页的相对路径 ''' url = os.path.join(self.base_url,releate_url) print ('Crawling: ' + url + '\n') ''' 解析html 针对不同的网址,解析内容也不一样 ''' #获取指定网页的html代码 response = get_dynamic_url_response_html(url) #response = getUrlRespHtml(url) ) #使用BeautifulSoup解析这段代码,能够得到一个 BeautifulSoup 的对象,并能按照标准的缩进格式的结构输出: #soup = BeautifulSoup(response, 'lxml') soup = BeautifulSoup(response, 'html.parser') #输出网页信息 #print(soup.prettify()) #with open('./read.html','w',encoding='utf-8') as f: #两个内容是一样的 只是一个是标准缩进格式,另一个不是 #f.write(str(soup.prettify())) #f.write(str(response)) ''' 根据爬取网站不同,下面代码也会不一样 解析该网站某一期的所有音乐信息 主要包括: 期刊信息 期刊封面 期刊描述 节目清单 ''' #<span class="vol-number rounded">989</span> num = soup.find('span',class_='vol-number').get_text() #<span class="vol-title">曙色初动</span> 解析标题 find每次只返回第一个元素 title = soup.find('span',class_='vol-title').get_text() ''' <div class="vol-cover-wrapper" id="volCoverWrapper"> <img src="http://img-cdn2.luoo.net/pics/vol/554f999074484.jpg!/fwfh/640x452" alt="曙色初动" class="vol-cover"> <a href="http://www.luoo.net/vol/index/739" class="nav-prev" title="后一期" style="display: inline; opacity: 0;"> </a><a href="http://www.luoo.net/vol/index/737" class="nav-next" title="前一期" style="display: inline; opacity: 0;"> </a> </div> 解析对应的图片背景 ''' cover = soup.find('img', class_='vol-cover').get('src') ''' <div class="vol-desc"> 本期音乐为史诗氛围类音乐专题。<br><br>史诗音乐的美好之处在于能够让人有无限多的宏伟想象。就像这一首首曲子,用岁月沧桑的厚重之声,铿锵有力的撞击人的内心深处,绽放出人世间的悲欢离合与决绝!<br><br>Cover From Meer Sadi </div> 解析描述文本 ''' desc = soup.find('div', class_='vol-desc').get_text() ''' <a href="javascript:;" rel="nofollow" class="trackname btn-play">01. Victory</a> <a href="javascript:;" rel="nofollow" class="trackname btn-play">02. Mythical Hero</a> 解析歌单 find_all返回一个列表 所有元素 ''' track_names = soup.find_all('a', attrs={'class': 'trackname'}) track_count = len(track_names) tracks = [] # 12期前的音乐编号1~9是1位(如:1~9),之后的都是2位 1~9会在左边垫0(如:01~09) for track in track_names: _id = str(int(track.text[:2])) if (int(releate_url) < 12) else track.text[:2] _name = fix_characters(track.text[4:]) tracks.append({'id': _id, 'name': _name}) phases = { 'phase': num, # 期刊编号 'title': title, # 期刊标题 'cover': cover, # 期刊封面 'desc': desc, # 期刊描述 'track_count': track_count, # 节目数 'tracks': tracks # 节目清单(节目编号,节目名称) } #追加到队列 self.queue.put(phases) if __name__ == '__main__': luoo_site = 'http://www.luoo.net/vol/index/' spyder_queue = queue.Queue() ## 创建新线程 luoo = UrlSpyder(luoo_site, releate_urls=['1372','1370'], que=spyder_queue) luoo.setDaemon(True) #开启线程 luoo.start() ''' 从队列中取数据,并进行下载 ''' count = 1 while True: if spyder_queue.qsize() <= 0: time.sleep(10) pass else: phases = spyder_queue.get() print(phases) #下载图片 download(phases['cover'],'%d.jpg'%(count)) count += 1
运行结果如下:
并爬取了如下两种图片:
注意:我们一般使用 urllib.urlretrieve()函数下载图片,文件等,但是不要使用这个函数下载网页,因为下载下来也是静态网页。如果要保存网页html内容,我们使用selenium获取网页内容,然后写入到指定文件:
with open(file_name, 'w',encoding='utf-8') as f: f.write(self.browser.page_source)
三 使用selenium模拟登陆
刚才我们爬取的网站是不需要登陆的,如果遇到一个需要先登录,才能爬取数据怎么办?幸运的是selenium提供了模拟鼠标点击,和键盘输入的功能,下面我们将会演示一个登陆微博的程序,并利用微博进行搜索我们需要的内容,并把数据保存下来。
3.1 实现代码
下面我先列入完整代码,一会一点点讲解:
# -*- coding: utf-8 -*- """ Created on Thu May 24 16:35:36 2018 @author: zy """ import os import time from selenium import webdriver #from selenium.common.exceptions import NoSuchElementException from bs4 import BeautifulSoup class WeiboSpyder(): ''' python爬虫——基于selenium用火狐模拟登陆爬搜索关键词的微博:https://blog.csdn.net/u010454729/article/details/51225388 0.安装火狐 1.安装selenium,可通过pip安装:pip install selenium 2.程序里面改三处:用户名、密码、搜过的关键词search_text 3.需要手动输入验证码,并且验证码大小写敏感,若是输错了,等3秒再输入。 4.爬下来了,用BeautifulSoup提取,并且将相同文本的放在一起,并且排序 时间:5秒一个,不可缩短,不然加载不出来下一页这个按钮,然后程序就挂了,若网速快些,延时可以短些。 在每个点击事件之前或者之后都加time.sleep(2) ''' def __init__(self): #微博登录用户名,用户命名 self.username_ = "你的用户名" self.password_ = "你的密码" self.href = 'http://s.weibo.com/' #获取火狐浏览器对象 self.browser = webdriver.Firefox(executable_path = r'D:\ff\geckodriver.exe') #html请求 self.browser.get(self.href) time.sleep(2) #获取网页右上登陆元素 并点击 login_btn = self.browser.find_element_by_xpath('//a[@node-type="loginBtn"]') login_btn.click() time.sleep(2) #获取选择账号登录元素 并点击 name_login = self.browser.find_element_by_xpath('//a[@action-data="tabname=login"]') name_login.click() time.sleep(2) #获取输入用户名,密码元素 并输入用户名和密码 username = self.browser.find_element_by_xpath('//input[@node-type="username"]') password = self.browser.find_element_by_xpath('//input[@node-type="password"]') username.clear() username.send_keys(self.username_) password.clear() password.send_keys(self.password_) #获取提交登陆元素 并点击 sub_btn = self.browser.find_element_by_xpath('//a[@suda-data="key=tblog_weibologin3&value=click_sign"]') sub_btn.click() time.sleep(5) ''' #下面是验证码部分,如果需要验证码的化 while True: try: verify_img = browser.find_element_by_xpath('//img[@node-type="verifycode_image"]') except NoSuchElementException: break if verify_img: # 输入验证码 verify_code = browser.find_element_by_xpath('//input[@node-type="verifycode"]') verify_code_ = input('verify_code > ') verify_code.clear() verify_code.send_keys(verify_code_) # 提交登陆 sub_btn = browser.find_element_by_xpath('//a[@suda-data="key=tblog_weibologin3&value=click_sign"]') sub_btn.click() time.sleep(2) else: break ''' #获取搜索栏元素 #self.search_form = self.browser.find_element_by_xpath('//input[@class="searchInp_form"]') def get_weibo_search(self,search_text,max_length = 20): ''' 在网页中搜索指定信息,搜多到一页信息后,保存,然后搜索下一页信息,直至到max_length页 默认在当前路径下生成一个 名字为 search_text(去除下划线) 的文件夹,下面存放爬取得网页 args: search_text:需要搜索的内容 max_length:最大爬取网页个数 return: dst_dir:返回爬取网页所在的文件夹 ''' #将关键词送到搜索栏中,进行搜索 self.search_form = self.browser.find_element_by_xpath('//input[@class="searchInp_form"]') self.search_form.clear() self.search_form.send_keys(search_text) time.sleep(5) #获取搜索按钮元素 只有窗口最大化 才有搜索按钮 self.search_btn = self.browser.find_element_by_xpath('//a[@class="searchBtn"]') #点击搜索 self.search_btn.click() #进入循环之前,让第一页先加载完全。 time.sleep(2) print('Try download html for : {}'.format(search_text)) topics_name = search_text #将名字里面的空格换位_ 创建以搜索内容为名字的文件夹,保存爬取下来的网页 topics_name = topics_name.replace(" ","_") os_path = os.getcwd() dst_dir = os.path.join(os_path,topics_name) if not os.path.isdir(dst_dir): os.mkdir(dst_dir) #捕获异常,有的搜索可能没有下一页 遇到错误会跳过 try: count = 1 while count <= max_length: ''' #保存网页 构建目标文件路径 ''' file_name = os.path.join(dst_dir,'{}_{}.html'.format(topics_name, count)) #必须指定编码格式 with open(file_name, 'w',encoding='utf-8') as f: f.write(self.browser.page_source) print('Page {} download finish!'.format(count)) time.sleep(3) #获取下一页元素 self.next_page = self.browser.find_element_by_css_selector('a.next') #next_page = browser.find_element_by_xpath('//a[@class="page next S_txt1 S_line1"]') #有的时候需要手动按F5刷新,不然等太久依然还是出不来,程序就会挂,略脆弱。 self.next_page.click() count += 1 #完成一轮之前,保存之前,先让其加载完,再保存 如果报错,可以通过调节时间长度去除错误 time.sleep(10) except Exception as e: print('Error:',e) return dst_dir def get_weibo_text(self,file_name): ''' 将html文件里面的<p></p>标签的内容提取出来 args: text:返回一个list 每一个元素都是p标签的内容 args: file_name:html文件路径 ''' text = [] soup = BeautifulSoup(open(file_name,encoding='utf-8'),'lxml') #获取tag为div class_="WB_cardwrap S_bg2 clearfix"的所有标签 items = soup.find_all("div",class_="WB_cardwrap S_bg2 clearfix") if not items: text = [] #遍历每一额标签,提取为p的子标签内容 for item in items: line = item.find("p").get_text() #print line text.append(line) return text def get_weibo_all_page(self,path): ''' 文件夹下所有文件内容提取出来,然后合并起来 args: path:list 每个元素都是一个文件路径,加入我们在新浪搜索内容为火影忍者,则在当前路径下会生成一个为火影忍者的文件夹 path就是这个文件夹的路径 return: texts_all:返回合并之后的内容 是一个list ''' texts_all = [] file_names = os.listdir(path) #遍历当前文件夹下每个文件 for file_name in file_names: #将html文件里面的<p></p>标签的内容提取出来 texts = self.get_weibo_text(os.path.join(path,file_name)) #遍历每一个元素 for text in texts: text = text.replace("\t","") text = text.strip("\n") text = text.strip(" ") #若是重了,不加入到里面 if text in texts_all: pass else: texts_all.append(text) return texts_all def get_results_weibo(self,weibos_name): ''' 合并若干个文件夹下提取出来的微博 args: weibos_name:list 每一个元素都是一个搜索项提取出来的文本文件 args: ''' texts = [] for file_name in weibos_name: with open(file_name,encoding='utf-8') as f: text = f.readlines() for line in text: line = line.strip("\n") if line not in texts: texts.append(line) return texts if __name__ == '__main__': print('开始搜索') search = WeiboSpyder() #在新浪搜索中需要搜索内容 searchs_text = ["火影忍者","苍井空","波多野结衣"] #遍历要搜索的每一行 for search_text in searchs_text: path = search.get_weibo_search(search_text,max_length=5) texts_all = search.get_weibo_all_page(path) #文本排序 texts_all_sorted = sorted(texts_all) weibo_text_name = path + "_weibos.txt" with open(weibo_text_name,"w",encoding='utf-8') as f: #一行一行的写入 for text in texts_all_sorted: f.write(text + "\n") #将几个_weibos.txt文件合并到一起 print("Together:") file_names_weibos = [i for i in os.listdir(os.getcwd()) if i.endswith("_weibos.txt")] texts = search.get_results_weibo(file_names_weibos) with open("results.txt","w",encoding='utf-8') as f: for text in sorted(texts): f.write(text+"\n") print("Together finish!")
3.2 代码分析
微博的官网是http://s.weibo.com/,同样我们点击F12,打开网页:我们先获取右上角登陆按钮的标签信息:
我们怎样可以实现点击这个登陆的事件呢,在上面代码可以看到我定义了一个WeiboSpyder的类,其中在构造函数中负责网页的登陆功能。
我们首先通过向指定网址发送html请求,进行加载网页:
#获取火狐浏览器对象 self.browser = webdriver.Firefox(executable_path = r'D:\ff\geckodriver.exe') #html请求 self.browser.get(self.href) time.sleep(2)
然后通过find_element_by_xpath()函数获取登陆标签,获取该标签之后,我们触发点击事件,为了等到网页加载出来,我们在点击时候,睡眠2s。
#获取选择账号登录元素 并点击 name_login = self.browser.find_element_by_xpath('//a[@action-data="tabname=login"]') name_login.click() time.sleep(2)
同理,后面我们获取选择账号登陆标签,然后获取登陆名,登录密码元素,然后利用send_keys()方法输入登陆信息,最后获取登陆标签,开始登陆:
#获取选择账号登录元素 并点击 name_login = self.browser.find_element_by_xpath('//a[@action-data="tabname=login"]') name_login.click() time.sleep(2) #获取输入用户名,密码元素 并输入用户名和密码 username = self.browser.find_element_by_xpath('//input[@node-type="username"]') password = self.browser.find_element_by_xpath('//input[@node-type="password"]') username.clear() username.send_keys(self.username_) password.clear() password.send_keys(self.password_) #获取提交登陆元素 并点击 sub_btn = self.browser.find_element_by_xpath('//a[@suda-data="key=tblog_weibologin3&value=click_sign"]') sub_btn.click() time.sleep(5)
由于这里不需要验证码登陆,我们就跳过验证码了,在下一个案例中我会教大家如何过验证码。
完成登陆后,我们在主程序中开始利用微博的搜索引擎搜索指定内容:
if __name__ == '__main__': print('开始搜索') search = WeiboSpyder() #在新浪搜索中需要搜索内容 searchs_text = ["火影忍者","苍井空","波多野结衣"] #遍历要搜索的每一行 for search_text in searchs_text: path = search.get_weibo_search(search_text,max_length=5) texts_all = search.get_weibo_all_page(path) #文本排序 texts_all_sorted = sorted(texts_all) weibo_text_name = path + "_weibos.txt" with open(weibo_text_name,"w",encoding='utf-8') as f: #一行一行的写入 for text in texts_all_sorted: f.write(text + "\n") #将几个_weibos.txt文件合并到一起 print("Together:") file_names_weibos = [i for i in os.listdir(os.getcwd()) if i.endswith("_weibos.txt")] texts = search.get_results_weibo(file_names_weibos) with open("results.txt","w",encoding='utf-8') as f: for text in sorted(texts): f.write(text+"\n") print("Together finish!")
我在这里搜索的内容主要包括:
searchs_text = ["火影忍者","苍井空","波多野结衣"]
然后遍历每一项,开始调用get_weibo_search()方法:
def get_weibo_search(self,search_text,max_length = 20): ''' 在网页中搜索指定信息,搜多到一页信息后,保存,然后搜索下一页信息,直至到max_length页 默认在当前路径下生成一个 名字为 search_text(去除下划线) 的文件夹,下面存放爬取得网页 args: search_text:需要搜索的内容 max_length:最大爬取网页个数 return: dst_dir:返回爬取网页所在的文件夹 ''' #将关键词送到搜索栏中,进行搜索 self.search_form = self.browser.find_element_by_xpath('//input[@class="searchInp_form"]') self.search_form.clear() self.search_form.send_keys(search_text) time.sleep(5) #获取搜索按钮元素 只有窗口最大化 才有搜索按钮 self.search_btn = self.browser.find_element_by_xpath('//a[@class="searchBtn"]') #点击搜索 self.search_btn.click() #进入循环之前,让第一页先加载完全。 time.sleep(2) print('Try download html for : {}'.format(search_text)) topics_name = search_text #将名字里面的空格换位_ 创建以搜索内容为名字的文件夹,保存爬取下来的网页 topics_name = topics_name.replace(" ","_") os_path = os.getcwd() dst_dir = os.path.join(os_path,topics_name) if not os.path.isdir(dst_dir): os.mkdir(dst_dir) #捕获异常,有的搜索可能没有下一页 遇到错误会跳过 try: count = 1 while count <= max_length: ''' #保存网页 构建目标文件路径 ''' file_name = os.path.join(dst_dir,'{}_{}.html'.format(topics_name, count)) #必须指定编码格式 with open(file_name, 'w',encoding='utf-8') as f: f.write(self.browser.page_source) print('Page {} download finish!'.format(count)) time.sleep(3) #获取下一页元素 self.next_page = self.browser.find_element_by_css_selector('a.next') #next_page = browser.find_element_by_xpath('//a[@class="page next S_txt1 S_line1"]') #有的时候需要手动按F5刷新,不然等太久依然还是出不来,程序就会挂,略脆弱。 self.next_page.click() count += 1 #完成一轮之前,保存之前,先让其加载完,再保存 如果报错,可以通过调节时间长度去除错误 time.sleep(10) except Exception as e: print('Error:',e) return dst_dir
这个函数主要就做了以下事情:
- 将关键词送到搜索栏中,进行搜索
- 创建一个文件夹,把刚才搜索的网页保存下来
- 获取下一页元素,并触发点击事件,然后再把新的网页保存下来
- 重复上一步,直至保存了max_length页,或者触发的异常,停止搜索
- 返回文件夹路径
程序运行结果如下:
如果我们运行出现类似以下的错误:
这主要是因为我们页面没有加载完,所以才会找不到指定元素,我们可以通过延长睡眠时间解决该问题。
并且我们会生成三个文件夹:
为什么搜索苍井空和波多野结衣只有一条数据,主要是因为被屏蔽了:
后面的代码get_weibo_all_page()函数以及get_weibo_text(),get_results_weibo()函数就是利用BeautifulSoup对刚才获取的几个网页内容进行提取,这里就不过多介绍了,最终还会生成几个文件:
results.txt是对另外三个文件进行合并,内容如下:
四 爬取需要验证码的网站
4.1 安装pytesser3
亲爱的读者和支持者们,自动博客加入了打赏功能,陆陆续续收到了各位老铁的打赏。在此,我想由衷地感谢每一位对我们博客的支持和打赏。你们的慷慨与支持,是我们前行的动力与源泉。
日期 | 姓名 | 金额 |
---|---|---|
2023-09-06 | *源 | 19 |
2023-09-11 | *朝科 | 88 |
2023-09-21 | *号 | 5 |
2023-09-16 | *真 | 60 |
2023-10-26 | *通 | 9.9 |
2023-11-04 | *慎 | 0.66 |
2023-11-24 | *恩 | 0.01 |
2023-12-30 | I*B | 1 |
2024-01-28 | *兴 | 20 |
2024-02-01 | QYing | 20 |
2024-02-11 | *督 | 6 |
2024-02-18 | 一*x | 1 |
2024-02-20 | c*l | 18.88 |
2024-01-01 | *I | 5 |
2024-04-08 | *程 | 150 |
2024-04-18 | *超 | 20 |
2024-04-26 | .*V | 30 |
2024-05-08 | D*W | 5 |
2024-05-29 | *辉 | 20 |
2024-05-30 | *雄 | 10 |
2024-06-08 | *: | 10 |
2024-06-23 | 小狮子 | 666 |
2024-06-28 | *s | 6.66 |
2024-06-29 | *炼 | 1 |
2024-06-30 | *! | 1 |
2024-07-08 | *方 | 20 |
2024-07-18 | A*1 | 6.66 |
2024-07-31 | *北 | 12 |
2024-08-13 | *基 | 1 |
2024-08-23 | n*s | 2 |
2024-09-02 | *源 | 50 |
2024-09-04 | *J | 2 |
2024-09-06 | *强 | 8.8 |
2024-09-09 | *波 | 1 |
2024-09-10 | *口 | 1 |
2024-09-10 | *波 | 1 |
2024-09-12 | *波 | 10 |
2024-09-18 | *明 | 1.68 |
2024-09-26 | B*h | 10 |
2024-09-30 | 岁 | 10 |
2024-10-02 | M*i | 1 |
2024-10-14 | *朋 | 10 |
2024-10-22 | *海 | 10 |
2024-10-23 | *南 | 10 |
2024-10-26 | *节 | 6.66 |
2024-10-27 | *o | 5 |
2024-10-28 | W*F | 6.66 |
2024-10-29 | R*n | 6.66 |
2024-11-02 | *球 | 6 |
2024-11-021 | *鑫 | 6.66 |
2024-11-25 | *沙 | 5 |
2024-11-29 | C*n | 2.88 |

【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了