|
爬虫1.什么是爬虫2.基础入门之简单的页面设计3.urllib基本使用,一个类型六个方法4.urllib下载5.请求对象的定制6.get请求的quote方法7.get请求urlencode方法8.urllib_post请求百度翻译9.百度翻译详细版10.urllib_ajax的get请求豆瓣电影的第一页11.get请求豆瓣电影的前十页12.ajax_post请求肯德基官网13.异常14.微博的cookie登录15.handler处理器的基本使用16.urllib代理17.代理池18.xpath的基本使用19.解析_百度一下20.站长素材21.jsonpath22.用jsonpath解析淘票票23.BeautifulSoup24.bs4获取星巴克数据25.Selenium26.selenium元素定位27.举例Selenium邓紫棋28.Selenium其他操作29.selenium-phantomjs30.selenium-handless31.request基本使用request中的get请求32.request中的post请求33.request_代理34.request免验证登录古诗词网35.scrapy基本使用36.58同城实例37.汽车之家38.当当网39.电影天堂40.crawlspider1.什么是爬虫网络爬虫(又被称为网页蜘蛛,网络机器人)就是模拟浏览器发送网络请求,接收请求响应,一种按照一定的规则,自动地抓取互联网信息的程序。2.基础入门之简单的页面设计这一部分主要是为了展示怎样在爬虫中寻找网页中信息,在这些代码中展示的是一个列表,姓名年龄性别张三18男铁锅炖大鹅小鸡炖蘑菇锅包肉穿衣服下床洗漱123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051523.urllib基本使用,一个类型六个方法首先引用urllib,其中url代表我们想访问的网站网址,接下来我们要模拟一个浏览器向服务器发送请求,使用responce=urllib.request.urlopen(url)1来向服务器发送请求,用urllib来接收,从而我们就接收到了来自网站的源码,之后我们使用read()方法来读取,但是read()返回的是字节形式的二进制数据,我们无法读取,这时我们就可以解码,把二进制数据解码为字符串,使用decode(‘UTF-8’),这样我们就可以读取了。**一个类型六个方法**一个类型指的是我们上面提到的responce,也就是从服务器返回的数据,是HTTPResponce类型的。六个方法:content=responce.read(5)#读取五个字节#read读取时是按照字节去读取的,括号中是5说明读取5个字节content=responce.readline()#读取一行content=responce.readlines()#读取所有行,一行一行读,直到读完print(responce.getcode())#一个小知识,返回状态码,如果是200,说明没问题print(responce.geturl())#获取网站的地址,url指向的网站print(responce.getheaders())#获取headers,也就是模拟的浏览器的信息123456789101112#基本使用#使用urllib获取百度首页的源码importurllib.request#(1)定义一个url就是要访问的地址url='http://www.baidu.com'#(2)模拟浏览器向服务器发送请求,responce就是响应responce=urllib.request.urlopen(url)#(3)获取响应中的原码#read方法,返回的是字节形式的二进制数据#要将二进制数据转换成字符串#二进制->字符串解码decode('编码的格式')#content=responce.read().decode('UTF-8')#一个类型和六个方法#responce是HTTPResponce类型print(type(responce))#按照一个字节一个字节去读#content=responce.read(5)#读取五个字节#print(content)#(4)打印数据#print(content)#读取一行#content=responce.readline()#一行一行地读直到读完#content=responce.readlines()#print(content)#返回状态码如果是200,证明我们没有错#print(responce.getcode())#返回url地址print(responce.geturl())#获取的一些状态信息print(responce.getheaders())#一个类型HTTPresponce#六个方法readreadlinereadlinesgetcodegeturlgetheaders1234567891011121314151617181920212223242526272829303132334.urllib下载下载需要使用urllib.request.urlretrieve(url=url,filename='filename')1其中url代表一个下载的网页,filename代表文件的名字,其中文件名字后要加文件格式,例如jpg,mp4等#下载importurllib.request#下载一个网页#url_page='http://www.baidu.com'#url代表下载的路径,filename代表文件的名字#在python中,可以变量的名字,也可以直接写值#urllib.request.urlretrieve(url_page,'baidu.html')#下载图片url_img='https://img2.baidu.com/it/u=260402465,3171771956&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=889'urllib.request.urlretrieve(url=url_img,filename='you.jpg')#下载视频url_video='https://vdept3.bdstatic.com/mda-mhej5kskcde2e1e3/cae_h264_nowatermark/1629034712771677277/mda-mhej5kskcde2e1e3.mp4?v_from_s=hkapp-haokan-hbe&auth_key=1721966751-0-0-d761b7436e0f490614a8f1832a35f960&bcevod_channel=searchbox_feed&pd=1&cr=0&cd=0&pt=3&logid=0351188068&vid=3964562110483450965&klogid=0351188068&abtest='urllib.request.urlretrieve(url_video,'ban.mp4')12345678910111213145.请求对象的定制有些网站中的开头为https://,说明在其中加入了ssl,这也是一种反爬虫的手段。https://www.baidu.com/s?tn=15007414_15_dg&ie=utf-8&wd=邓紫棋1分析这个网址,其中有协议https://,有主机www.baidu.com,有路径s,参数wd#http/httpswww.baidu.com80/443swd=邓紫棋##协议主机端口号路径参数锚点#http端口号80#https443#mysql3306#oracle1521#redis6379#mongodb2701712345678我们需要构建一个请求对象来访问在这里我们可以获得User-Agent的信息,来假借这一信息来向服务器发送信息,又因为urlopen中不能存放字典,所以我们可以通过request=urllib.request.Request(url=url1,headers=headers)来接收headers和url,并且由于参数顺序问题我们只能通过关键字传参的方式importurllib.requesturl1='https://www.baidu.com'#url的组成#https中加入了ssl#https://www.baidu.com/s?tn=15007414_15_dg&ie=utf-8&wd=邓紫棋#http/httpswww.baidu.com80/443swd=邓紫棋##协议主机端口号路径参数锚点#http端口号80#https443#mysql3306#oracle1521#redis6379#mongodb27017headers={'User-Agent':'Mozilla/5.0(WindowsNT10.0;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/127.0.0.0Safari/537.36'}#请求对象的定制#因为urlopen中不能储存字典,所以headers不能传递出去#因为参数顺序问题,不能直接写url和headersrequest=urllib.request.Request(url=url1,headers=headers)responce=urllib.request.urlopen(request)content=responce.read().decode('utf-8')print(content)#第一个反爬:UA123456789101112131415161718192021222324252627286.get请求的quote方法当我们访问https://www.baidu.com/s?tn=15007414_15_dg&ie=utf-8&wd=%E9%82%93%E7%B4%AB%E6%A3%8B这个网站时,我们看不懂后面的这些乱码,所以我们改为https://www.baidu.com/s?wd=邓紫棋1可是这时却报错,因为浏览器不认识中文,这时我们就应该把‘邓紫棋’换成unicode编码的形式,使用:name=urllib.parse.quote('邓紫棋')1这样我们就可以获取到邓紫棋三个字的unicode编码了。然后把之前的url和name结合起来就可以获取网址了。#https://www.baidu.com/s?tn=15007414_15_dg&ie=utf-8&wd=%E9%82%93%E7%B4%AB%E6%A3%8Bimporturllib.requestimporturllib.parse#需求获取https://www.baidu.com/s?wd=邓紫棋的网页源码url='https://www.baidu.com/s?wd='#请求对象的定制,是为了解决反爬的第一种手段headers={'User-Agent':'Mozilla/5.0(WindowsNT10.0;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/127.0.0.0Safari/537.36'}#将邓紫棋三个字变成unicode编码的格式#我们依赖urllib.parsename=urllib.parse.quote('邓紫棋')url=url+name#请求对象的定制request=urllib.request.Request(url=url,headers=headers)#模拟浏览器向服务器发送请求responce=urllib.request.urlopen(request)#获取相应的内容content=responce.read().decode('UTF-8')print(content)1234567891011121314151617181920212223242526277.get请求urlencode方法上面的实例中只有‘邓紫棋’一个中文,当我们有多个中文检索词时,还用quote就比较麻烦了,这是我们有一个更好的方法:data={'wd':'周杰伦','sex':'男','location':'中国台湾'}new_data=urllib.parse.urlencode(data)123456这样我们就可以把这些元素都融合在一起了,这时我们就可以获取到想要的带有中文检索字的网址了,然后再定制请求对象想服务器发送请求就可以了。#urlencode应用场景:多个参数的时候#importurllib.parse#https://www.baidu.com/s?wd=周杰伦&sex=男#data={#'wd':'周杰伦',#'sex':'男'#}#a=urllib.parse.urlencode(data)#print(a)importurllib.requestimporturllib.parsebase_url='https://www.baidu.com/s?'data={'wd':'周杰伦','sex':'男','location':'中国台湾'}new_data=urllib.parse.urlencode(data)print(new_data)#路径url=base_url+new_dataheaders={'User-Agent':'Mozilla/5.0(WindowsNT10.0;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/127.0.0.0Safari/537.36'}#请求对象的定制request=urllib.request.Request(url=url,headers=headers)#模拟浏览器向服务器发送请求responce=urllib.request.urlopen(request)#获取网页源码的数据content=responce.read().decode('UTF-8')print(content)123456789101112131415161718192021222324252627282930313233343536378.urllib_post请求百度翻译我们在对百度翻译进行爬虫时,需要先找到网址'https://fanyi.baidu.com/sug'然后我们可以在图中发现RequestMethod是POST,我们需要知道post的请求参数必须要进行编码,我们在图中得知一个字典类型的数据,这就是我们要在网站中查找的内容,我们用data来接收它,然后用urlencode编码一下:data=urllib.parse.urlencode(data)1但是这样得到的是字符串,我们传入的是字节码,所以说post传入的参数需要编码,data=urllib.parse.urlencode(data).encode('UTF-8'),而且post传入的参数不会拼接到url后面,而是放到请求对象定制的参数中,request=urllib.request.Request(url=url,data=data,headers=headers)1之后模拟浏览器向服务器发送请求,得到的数据我们看不懂,所以我们要对其进行改变,把字符串变成json数据,importjsonobj=json.loads(content)print(obj)1234#post请求importurllib.parseimporturllib.requesturl='https://fanyi.baidu.com/sug'headers={'User-Agent':'Mozilla/5.0(WindowsNT10.0;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/127.0.0.0Safari/537.36'}data={'kw':'spider'}#post的请求参数必须要进行编码#data=urllib.parse.urlencode(data)北京上海武汉深圳河北东北1234567891011121314151617181920首先我们要先调用fromlxmlimportetree,然后我们用xpath来解析本地文件,tree=etree.parse('XPATH.html')然后就可以个根据不同的需求获取不同的信息。#获取网页源码部分数据的一种方式fromlxmlimportetree#xpath解析#(1)本地文件etree.parse#(2)服务器响应文件responce.read().decode('utf-8')*****etree.HTML()#xpath解析本地文件tree=etree.parse('XPATH.html')#1.路径查询:#//:查找所有子孙节点,不考虑层级关系#/:查找子节点#tree.xpath('xpath路径')#lilist=tree.xpath('//body//ul')#判断列表的长度#print(len(lilist))#2.谓词查询#//div[@id]#//div[@id="maincontent"]#test()获取标签的内容lilist=tree.xpath('//ul/li[@id]')print(lilist)#找到标签为l1的标签li_list=tree.xpath('//ul/l1[@id="l1"]')print(len(li_list))#查找到id为l1标签的class属性值#3.属性查询://@classli=tree.xpath('//ul/li[@id="l1"]/@class')print(li)#4.模糊查询#//div[contains(@id,"he")]id包含he#//div[starts-with(@id,"he")]id以he开头li__list=tree.xpath('//ul/li[contains(@id,"l")]')print(li__list)#查询id的值以l开头的li标签liilist=tree.xpath('//ul/li[starts-with(@id,"l")]')print(liilist)#查询id为l1并且class为c1的li_list=tree.xpath('//ul/li[@id="l1"and@class="c1"]')print(li_list)12345678910111213141516171819202122232425262728293031323334353637383940414219.解析_百度一下当我们想象获取“百度一下”这四个字时,用到了xpath工具importurllib.requesturl='https://www.baidu.com'headers={'User-Agent':'Mozilla/5.0(WindowsNT10.0;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/127.0.0.0Safari/537.36'}request=urllib.request.Request(url=url,headers=headers)responce=urllib.request.urlopen(request)content=responce.read().decode('utf-8')#获取我们想要的fromlxmlimportetree#解析服务器相应的文件tree=etree.HTML(content)result=tree.xpath('//input[@id="su"]/@value')[0]print(result)1234567891011121314151617181920212220.站长素材当我们在站长素材这个网站上下载图片时,首先我们要找到图片的网址,我们发现第一页和其他页不同,第一页是没有page的,所以我们用if-else语句来分别提取出第一页和其他页,然后模拟浏览器向服务器发送请求,并且根据获得的源码在其中找到图片名字和网址所在的子孙类,下载就可以了。importurllib.requestfromlxmlimportetree#需求:前十页图片,第一页和其他页的数据不同#https://sc.chinaz.com/tupian/weimeiyijingtupian.html#https://sc.chinaz.com/tupian/weimeiyijingtupian_2.html#请求对象的定制defcreate_request(page):if(page==1):url='https://sc.chinaz.com/tupian/weimeiyijingtupian.html'else:url='https://sc.chinaz.com/tupian/weimeiyijingtupian_'+str(page)+'.html'headers={'User-Agent':'Mozilla/5.0(WindowsNT10.0;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/127.0.0.0Safari/537.36'}request=urllib.request.Request(url=url,headers=headers)returnrequest#获取网页源码defget_content(request):responce=urllib.request.urlopen(request)content=responce.read().decode('utf-8')returncontent#下载defdown_load(content):#下载图片#urllib.request.urlretrieve('图片地址','文件名字')tree=etree.HTML(content)namelist=tree.xpath('//div[@class="container"]//img//@alt')#一般图片网站都会懒加载srclist=tree.xpath('//div[@class="container"]//img//@data-original')foriinrange(len(namelist)):name=namelist[i]src=srclist[i]url='https:'+srcurllib.request.urlretrieve(url=url,filename='./lovlmg/'+name+'.jpg')if__name__=='__main__':start_page=int(input('请输入起始页码'))end_page=int(input('请输入结束页码'))forpageinrange(start_page,end_page+1):#请求对象的定制request=create_request(page)#获取网页源码content=get_content(request)#下载down_load(content)1234567891011121314151617181920212223242526272829303132333435363738394041424344454621.jsonpath下面是一个json文件,我们使用jsonpath来查找我们想要的元素。在此之前我们都要提前下载jsonpath,在json库中就可以下载{"store":{"book":[{"category":"reference","author":"NigelRees","title":"SayingsoftheCentury","price":8.95},{"category":"fiction","author":"EvelynWaugh","title":"SwordofHonour","price":12.99},{"category":"fiction","author":"HermanMelville","title":"MobyDick","isbn":"0-553-21311-3","price":8.99},{"category":"fiction","author":"J.R.R.Tolkien","title":"TheLordoftheRings","isbn":"0-395-19395-8","price":22.99}],"bicycle":{"color":"red","price":19.95}}}12345678910111213141516171819202122232425262728293031importjsonimportjsonpathobj=json.load(open('解析jsonpath.json','r',encoding='utf-8'))#print(obj)#书店所有书的作者author_list=jsonpath.jsonpath(obj,'$.store.book[*].author')#print(author_list)#所有的作者author_list=jsonpath.jsonpath(obj,'$..author')#print(author_list)#store下面的所有元素tag_list=jsonpath.jsonpath(obj,'$.store.*')#print(tag_list)#store里所有的钱price_list=jsonpath.jsonpath(obj,'$.store..price')print(price_list)#第三个书book=jsonpath.jsonpath(obj,'$..book[2]')print(book)#最后一本书book=jsonpath.jsonpath(obj,'$..book[(@.length-1)]')print(book)#前面的两本书book_list=jsonpath.jsonpath(obj,'$..book[0,1]')print(book_list)#条件过滤需要在()前面加一个?号#过滤出所有含有isbn的书book_list=jsonpath.jsonpath(obj,'$..book[?(@.isbn)]')print(book_list)#哪本书超过了十块钱book_list=jsonpath.jsonpath(obj,'$..book[?(@.price>10)]')print(book_list)12345678910111213141516171819202122232425262728293031323334353637383940414222.用jsonpath解析淘票票这一节我们要在淘票票网站中获取城市信息,首先我们找到网站和城市的json文件,在其中我们要进行切割来获取我们想要的部分。importurllib.requesturl='https://dianying.taobao.com/cityAction.json?activityId&_ksTS=1722168119996_108&jsoncallback=jsonp109&action=cityAction&n_s=new&event_submit_doGetAllRegion=true'headers={'accept':'text/javascript,application/javascript,application/ecmascript,application/x-ecmascript,*/*;q=0.01','accept-language':'zh-CN,zh;q=0.9','bx-v':'2.5.14','cookie':'t=164d761e0b05d3b06cdd6bf1f9b678a7;cookie2=18db62f7815a4ae14ef8d13a956326d3;v=0;_tb_token_=fbe3708e067b3;cna=u/MsH/Vh8XoCAXzuRuYVHkpC;xlly_s=1;isg=BJCQTO2mwrV1Gp6xP-s5jLwjYd7iWXSjvRF2bIpgH-u-xTFvMmnmM167nY0lECx7','priority':'u=1,i','referer':'https://dianying.taobao.com/','sec-ch-ua':'"Not)A;Brand";v="99","GoogleChrome";v="127","Chromium";v="127"','sec-ch-ua-mobile':'?0','sec-ch-ua-platform':'"Windows"','sec-fetch-dest':'empty','sec-fetch-mode':'cors','sec-fetch-site':'same-origin','user-agent':'Mozilla/5.0(WindowsNT10.0;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/127.0.0.0Safari/537.36','x-requested-with':'XMLHttpRequest'}request=urllib.request.Request(url=url,headers=headers)responce=urllib.request.urlopen(request)content=responce.read().decode('utf-8')#切割content=content.split('(')[1].split(')')[0]withopen('淘票票.json','w',encoding='utf-8')asfp:fp.write(content)importjsonimportjsonpathobj=json.load(open('淘票票.json','r',encoding='utf-8'))city_list=jsonpath.jsonpath(obj,'$..regionName')print(city_list)123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495023.BeautifulSoupBeautifulSoup是一种解析HTML和XML的第三方库,可以查找文件中的特定标签的元素。比如以下的HTML文件:张三李四王五嘿嘿嘿嘿哈哈哦好啊
呵呵呵12345678910111213141516171819202122232425frombs4importBeautifulSoup#通过解析本地文件来讲解bs4的基础语法#默认打开文件格式是gbksoup=BeautifulSoup(open('BeautifulSoup.html',encoding='utf-8'),'lxml')#print(soup)#bs4基本语法#(1)根据标签名字来查找节点#找到的是第一个符合条件的数据#print(soup.a)#print(soup.a.attrs)#获取标签的属性和属性值#bs4的一些函数#(1)find返回的是第一个符合条件的数据#print(soup.find('a'))#使用title标签来找到相应的对象#print(soup.find('a',title="a2"))#可以加一个_来代表html中的class,因为class是python中的类#print(soup,find('a',class_="a1"))#(2)find_all返回的是一个列表并且返回了所有的a标签#print(soup.find_all('a'))#如果想获取多个标签的数据,那么需要在find_all的参数中添加的是列表的数据#print(soup.find_all(['a','span']))#limit作用是查找前几个数据#print(soup.find_all('li',limit=2))#(3)select(推荐)#select方法返回的是一个列表,并且会返回多个数据print(soup.select('a'))#可以通过.代表class,我们把这种操作叫做类选择器print(soup.select('.a1'))#id#id=l1,用#代替print(soup.select('#l1'))#属性选择器#查找到li标签中有id的标签print(soup.select('li[id]'))#找到id为l2的标签print(soup.select('li[id="l2"]'))#层级选择器#后代选择器#找到div下面的liprint(soup.select('divli'))#子代选择器#某标签的第一级子标签#注意:很多的计算机编程语言中如果不加空格不会输出内容,但是在bs4中不会报错print(soup.select('div>ul>li'))#找到a标签和li标签的所有对象print(soup.select('a,li'))#节点信息#获取节点内容obj=soup.select('#d1')[0]#如果标签对象中只有内容,但是如果标签对象中除了内容还有标签,那么string中获取不到数据,而get_text()是可以获取的print(obj.string)print(obj.get_text())#节点的属性#通过id来获取p标签obj=soup.select('#p1')[0]#name是标签的名字print(obj.name)#将属性值作为一个字典返回print(obj.attrs)#获取节点的属性opj=soup.select('#p1')[0]print(obj.attrs.get('class'))print(obj.get('class'))print(obj['class'])1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787924.bs4获取星巴克数据当我们想获取星巴克中咖啡种类的数据时,首先我们找到官网,然后获取到返回数据,使用name_list=soup.select('ul[gridpadded-3product]strong')来获取咖啡名importurllib.requesturl='https://www.starbucks.com.cn/menu/'headers={}responce=urllib.request.Request(url=url)content=responce.read().decode('utf-8')frombs4importBeautifulSoupsoup=BeautifulSoup(content,'lxml')#//ul[@class="gridpadded-3product"]//strong/text()name_list=soup.select('ul[gridpadded-3product]strong')fornameinname_list:print(name.string)12345678910111213141516171819202125.SeleniumSelenium是一个fromseleniumimportwebdriver#Chrome浏览器driver=webdriver.Chrome()driver.get('https://www.jd.com')#获取网页源码content=driver.page_sourceprint(content)1234567891011121326.selenium元素定位(1)id可以唯一定位到一个元素(全局唯一)find_element(By.ID,"id名")(2)name要确保是全局唯一的find_element(By.NAME,"name名")(3)classname相当于样式容易重复find_element(By.CLASS_NAME,"class名)"(4)linktext有时候不是一个输入框也不是一个按钮,而是一个文字链接,例如百度搜索界面左上角的新闻,可能重复。find_element(By.LINK_TEXT,"link_text名称")(5)partiallinktext部分链接定位,链接的部分名称,会有重复的可能。find_element(By.PARTIAL_LINK_TEXT,"名称")(6)tagname标签(很多),类似driver.find_element(By.ID,"toolbar-search-input")#driver.find_element_by_id#name定位#driver.find_element(By.NAME,"keywords")#driver.find_element_by_name#class定位#driver.find_element(By.CLASS_NAME,"toolbar-search-container")123456789101112131415161727.举例Selenium邓紫棋fromseleniumimportwebdriver#获得浏览器驱动importtimefromselenium.webdriver.common.byimportBy#获得谷歌浏览器驱动,注意一定要大写浏览器名称driver=webdriver.Chrome()#输入要打开的网址url="https://www.baidu.com/"driver.get(url)time.sleep(3)#用id来定位百度搜索框,定位一个是element,定位多个是elements#kw和su都是名字,框中输入名字,点击百度一下#driver.find_elements_by_id("kw").send_keys("邓紫棋")写法已经被弃用driver.find_element(By.ID,"kw").send_keys("邓紫棋")time.sleep(3)driver.find_element(By.ID,"su").click()#太快看不到添加sleeptime.sleep(3)#滑到底部js_buttom='document.documentElement.scrollTop=100000'driver.execute_script(js_buttom)time.sleep(2)#获取下一页的按钮next=driver.find_element(By.XPATH,"//a[@class='n']")#点击下一页next.click()time.sleep(2)#回到上一页driver.back()time.sleep(3)#quit在关闭的同时还能进行清理,close只是关闭driver.quit()1234567891011121314151617181920212223242526272829303132333435363738394028.Selenium其他操作元素定位好之后进行(1)click点击对象click()#点击百度一下driver.find_element(By.ID,"su").click()123(2)send_keys在对象上模拟按键输入send_keys("要输入的内容")#搜索框中输入邓紫棋driver.find_element(By.ID,"kw").send_keys("邓紫棋")123(3)clear清除对象的内容clear()#清除搜索框中的内容driver.find_element(By.ID,"kw").clear()123(4)submit提交表单如果出现type=“submit”的情况submit可以替换click操作,效果一样。.submit()#点击百度一下driver.find_element(By.ID,"su").submit()123(5)text用于获取元素的文本信息.text#获取百度界面上的信息(之后用print打印出来)text=driver.find_element(By.ID,"s-top-left").text123浏览器的操作(1)浏览器最大化maximize_window()driver.maximize_window()12(1)设置浏览器宽、高set_window_size(宽,高)driver.set_window_size(600,600)12(1)操作浏览器的前进、后退#后退back()driver.back()#前进forward()driver.forward()123456(4)控制浏览器滚动条用js语言,数值为0滚动条往顶端拉,数值越大滚动条往下端拉。js1="varq=documentElement.Scro1lTop=数值"#滚动条往顶端拉js1="varq=documentElement.Scro1lTop=0"#滚动条往下拉js1="varq=documentElement.Scro1lTop=10000"#执行操作driver.execute_script(js1)12345676.键盘事件以一些常用键举例(1)enter键fromselenium.webdriverimportKeyssend_keys(Keys.ENTER)12以禅道的登录为例fromseleniumimportwebdriverimporttimefromselenium.webdriver.common.byimportBy#导入键盘包fromselenium.webdriverimportKeysdriver=webdriver.Chrome()time.sleep(3)url="复制禅道登录界面的地址"driver.get(url)#浏览器最大化driver.maximize_window()#输入自己的用户名和密码,输完密码后在密码框中点击enter键登录driver.find_element(By.ID,"account").send_keys("用户名")driver.find_element(By.NAME,"password").send_keys("密码")driver.find_element(By.NAME,"password").send_keys(Keys.ENTER)time.sleep(6)driver.quit()12345678910111213141516171819(2)Tab键切换焦点fromselenium.webdriverimportKeyssend_keys(Keys.TAB)123fromseleniumimportwebdriverimporttimefromselenium.webdriverimportKeysfromselenium.webdriver.common.byimportBydriver=webdriver.Chrome()time.sleep(3)url="输入自己的禅道登录的地址"driver.get(url)driver.maximize_window()#把光标从登录框切换到密码框driver.find_element(By.ID,"account").send_keys("admin")driver.find_element(By.ID,"account").send_keys(Keys.TAB)time.sleep(6)driver.quit()12345678910111213141516(3)键盘组合用法#ctrl+a全选输入框内容send_keys(Keys.CONTROL,'a')#ctrl+x剪切输入框内容send_keys(Keys.CONTROL,'x')12347.鼠标事件模拟鼠标(1)常用鼠标事件fromselenium.webdriverimportKeys,ActionChains#右击.context_click()#双击double_click()#拖动drag_and_drop()#移动,把鼠标移动到相应位置move_to_element()123456789(2)举例#导包fromselenium.webdriverimportKeys,ActionChains#假设已经处于禅道登录界面,输入用户名su=driver.find_element(By.ID,"account").send_keys("admin")#ActionChains首先要知道要操作的是哪个浏览器#右击登录输入框#perform执行ActionChains(driver).context_click(su).perform()1234567829.selenium-phantomjs由于phantomjs已经被很多公司淘汰不再使用,所以这里不做赘述fromseleniumimportwebdriverfromselenium.webdriver.common.byimportBydriver=webdriver.Phantomjs()driver.get('http://www.baidu.com')print(driver.page_source.encode("utf-8"))driver.quit()#已经弃用123456789101130.selenium-handlessChromeHeadless是一个无界面的浏览器环境,它是GoogleChrome浏览器在59版本之后新增的一种运行模式。与传统的浏览器不同,ChromeHeadless可以在后台执行网页操作,而无需显示可见的用户界面。ChromeHeadless提供了一种方便的方式来进行自动化测试、网络爬虫和数据抓取等任务。它通过模拟用户在浏览器中的行为,实现了对网页的自动化操作和交互。在执行过程中,ChromeHeadless可以访问和操纵网页的DOM结构、执行JavaScript代码、提交表单、点击按钮等。由于没有可见的界面,ChromeHeadless相比传统浏览器具有一些优势。首先,它更轻量级,节省了系统资源,并且执行速度更快。其次,它稳定性高,不受弹窗、广告或其他干扰因素的影响。此外,ChromeHeadless还提供了丰富的调试工具和API,方便开发者进行调试和监控。使用Selenium框架结合ChromeHeadless可以实现自动化测试和网页爬虫等应用场景。开发人员可以利用Selenium的API来编写脚本,控制ChromeHeadless执行各种操作,并获取网页内容和处理结果。#fromseleniumimportwebdriver#fromselenium.webdriver.chrome.optionsimportOptions#chrome_options=Options()#chrome_options.add_argument('--headless')#chrome_options.add_argument('--disable-gpu')#path=r'C:\ProgramFiles\Google\Chrome\Application\chrome.exe'#chrome_options.binary_location=path#browser=webdriver.Chrome(options=chrome_options)#url='https://www.baidu.com'#browser.get(url)#封装fromseleniumimportwebdriverfromselenium.webdriver.chrome.optionsimportOptionsdefshare_browser():chrome_options=Options()chrome_options.add_argument('--headless')chrome_options.add_argument('--disable-gpu')#path是Google浏览器的位置path=r'C:\ProgramFiles\Google\Chrome\Application\chrome.exe'chrome_options.binary_location=pathbrowser=webdriver.Chrome(options=chrome_options)returnbrowserbrowser=share_browser()url='https://www.baidu.com'123456789101112131415161718192021222324252627282930313231.request基本使用request类似于urllib,但是request是python中独有的库,能用更简短的代码写出和urllib同样的效果,request中有一个类型和六个属性,和urllib是相似的importrequestsurl='https://www.baidu.com'responce=requests.get(url=url)#一个类型和六个属性#responce类型print(type(responce))#设置编码格式responce.encoding='utf-8'#以字符串的形式返回了网页源码print(responce.text)#返回一个url地址print(responce.url)#返回的是二进制的数据print(responce.content)#返回相应的状态码print(responce.status_code)#返回的是响应头print(responce.headers)1234567891011121314151617181920212223request中的get请求首先分析一下urllib和request的区别,然后我们在request中只需要responce=requests.get(url=url,params=data,headers=headers)content=responce.text123这两行代码就可以搞定,还是很便捷的。再传入时,在get中有一个param参数,是可以传入输入参数的。#urllib#(1)一个类型和六个方法#(2)get请求#(3)post请求,百度翻译#(4)ajax的post请求#(5)ajax的post请求#(6)cookie登录微博#(7)代理#request#(1)一个类型和六个属性#(2)get请求#(3)post请求#(4)代理#(5)cookie验证码importrequests#问号也可以不加url='https://www.baidu.com/s?'headers={'User-Agent':'Mozilla/5.0(WindowsNT10.0;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/127.0.0.0Safari/537.36'}data={'wd':'北京'}#url叫做请求资源路径,params叫做参数,kwargs是字典responce=requests.get(url=url,params=data,headers=headers)content=responce.textprint(content)#参数无需urlencode编码#参数需要params传递#不需要请求对象定制1234567891011121314151617181920212223242526272829303132333435363732.request中的post请求在request中post请求中,我们还是据百度翻译的例子,这次post请求中的data也是传入的参数,由于content返回的是字符串类型,我们通过json编码为字典,这样我们就可以看懂了。importrequestsurl='https://fanyi.baidu.com/sug'headers={'User-Agent':'Mozilla/5.0(WindowsNT10.0;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/127.0.0.0Safari/537.36','cookie':'BAIDUID_BFESS=7AD549AF735289E0C107221311EA1BE0:FG=1;BIDUPSID=7AD549AF735289E0C107221311EA1BE0STM=1722243178;ZFY=:Aw39gqGc9br6vsj:BXTHad0qWcTvm9FKwjHVw648DZCg:C;BA_HECTOR=01040k8ga405052l0405a12l9ostdu1jajvkn1u;BDRCVFR[V3EOV_cRy1C]=mk3SLVN4HKm;H_PS_PSSID=60453_60470_60492_60500_60519_60552_60566_60554;delPer=0SINO=1;BDORZ=FFFB88E999055A3F8A630C64834BD6D0;ab_sr=1.0.1_NTU5NjJiZTkxMGQ4YWM4YzkzODU2YzIwMGE1MmIxNTg3MDc5ODIxZGI2YWY4NDY1YmZlOWY2ZmNjNjc2MjdmZTdmMTRkMjdkZjJkZGM3MjBhZDI5MWM0NzMzODVkYjkwYzZiNTcxNDk3YjZjZjQ3NmYyNDE1OWNkYzU3NzBjODg5NWNjYWM3YzY3ZTcyMGQxMTgzY2QwMTI5ZDRmZTZiZQ==;RT="z=1&dm=baidu.com&si=24cae920-18e9-4b5b-8bb3-c1f662e67412&ss=lz9u6d1w&sl=1&tt=l0&bcn=https%3A%2F%2Ffclog.baidu.com%2Flog%2Fweirwood%3Ftype%3Dperf&ld=1d0"'}data={'kw':'eye'}#url请求地址,data请求参数,kwargs字典responce=requests.post(url=url,headers=headers,data=data)content=responce.textimportjsonobj=json.loads(content)print(obj)1234567891011121314151617181920212223242533.request_代理这个也就是多个ip传入防止被查封,只要把proxy代理ip传入就可以了importrequestsurl='https://www.baidu.com/s?'headers={'User-Agent':'Mozilla/5.0(WindowsNT10.0;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/127.0.0.0Safari/537.36'}data={'wd':'ip'}proxy={'https':'121.230.210.31:3256'}responce=requests.get(url=url,params=data,headers=headers,proxies=proxy)content=responce.textwithopen('daili2.html','w',encoding='utf-8')asfp:fp.write(content)12345678910111213141516171819202134.request免验证登录古诗词网在这其中我们也不知道那些数据是有用的,所以我们先观察:在这些数据中由两个我们没有找到的#__VIEWSTATE:vmkHKKt/kQxZnU3DdbFiulx/YaTER7m22csaKd4SZSS8an8DiKnioUZXZti28v5Kj7ouFNngtqLop5buxudkBNq5I+0NvucbIfDZjyUxRs5l5Iv7EY/tkDhCR0Ez21N/6JCIXHwPhAy055YerBP/kY98yi8=__VIEWSTATEGENERATOR:C93BE1AE,这时我们在源码中找到:这里显示这两个Hidden的数据,说明这两个我们是无法查看的,之后我们用request获取网页源码,并用bs4来获取这两个数据,之后我们又在登录页面找到了验证码的相关图片,我们把它下载下来,通过session的工具来表示我们这两次登录(我们下一次还要登陆),是相同的,然后利用ddddocr来读取图片中的信息,importddddocr#导入ddddocrocr=ddddocr.DdddOcr(show_ad=False)#实例化withopen('code.jpg','rb')asf:#打开图片img_bytes=f.read()#读取图片res=ocr.classification(img_bytes)#识别12345这样我们就可以获取到所有的信息了,之后通过data传入后我们就可以登录进页面了。#古诗词网#通过登录然后进入到主页面#通过找登录接口发现登录的时候需要的参数很多#__VIEWSTATE:vmkHKKt/kQxZnU3DdbFiulx/YaTER7m22csaKd4SZSS8an8DiKnioUZXZti28v5Kj7ouFNngtqLop5buxudkBNq5I+0NvucbIfDZjyUxRs5l5Iv7EY/tkDhCR0Ez21N/6JCIXHwPhAy055YerBP/kY98yi8=#__VIEWSTATEGENERATOR:C93BE1AE#from:http://www.gushiwen.cn/user/collect.aspx#email:19933725376#pwd:jijiji#code:ZVMZ#denglu:登录#我们观察到__VIEWSTATE,__VIEWSTATEGENERATOR,不认识#code是一个变化的量#难点(1):__VIEWSTATE,__VIEWSTATEGENERATOR#通过源码可以知道我们找到了这两个值,所以只要我们获取源码,再解析就可以了#难点(2):验证码importrequests#登录页面url='https://www.gushiwen.cn/user/login.aspx?from=http://www.gushiwen.cn/user/collect.aspx'headers={'User-Agent':'Mozilla/5.0(WindowsNT10.0;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/127.0.0.0Safari/537.36'}#获取页面源码responce=requests.get(url=url,headers=headers)content=responce.text#解析页面源码,然后获取__VIEWSTATE,__VIEWSTATEGENERATORfrombs4importBeautifulSoupsoup=BeautifulSoup(content,'lxml')#获取__VIEWSTATEviewstate=soup.select("#__VIEWSTATE")[0].attrs.get('value')#获取__VIEWSTATEGENERATORviewstategenerator=soup.select('#__VIEWSTATEGENERATOR')[0].attrs.get('value')#获取验证码图片code=soup.select('#imgCode')[0].attrs.get('src')code_url='https://so.gushiwen.cn'+code#session()方法使请求对象变成一个对象session=requests.session()responce_code=session.get(code_url)#注意此时要使用二进制数据content_code=responce_code.content#wb的模式就是将二进制数据写入文件withopen('code.jpg','wb')asfp:fp.write(content_code)#把图片下载到本地之后,观察验证码importddddocr#导入ddddocrocr=ddddocr.DdddOcr(show_ad=False)#实例化withopen('code.jpg','rb')asf:#打开图片img_bytes=f.read()#读取图片res=ocr.classification(img_bytes)#识别#点击登录url_post='https://www.gushiwen.cn/user/login.aspx?from=http://www.gushiwen.cn/user/collect.aspx'data_post={'__VIEWSTATE':viewstate,'__VIEWSTATEGENERATOR':viewstategenerator,'from':'http://www.gushiwen.cn/user/collect.aspx','email':'19933725376','pwd':'Ylp197419','code':res,'denglu':'登录'}responce_post=session.post(url=url,headers=headers,data=data_post)content_post=responce_post.textwithopen('gushiwen.html','w',encoding='utf-8')asfp:fp.write(content_post)12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747535.scrapy基本使用scrapy项目的建立1.创建爬虫的项目scrapystartproject项目的名字注意:项目的名字不允许使用数字开头也不能包含中文2.创建爬虫文件:要在spider文件夹中去创建爬虫文件cd项目的名字\项目的名字\spiderscdscrapy_baidu_001\scrapy_baidu_001\spiders创建爬虫文件scrapygenspider爬虫文件的名字要爬取的网页eg:scrapygenspiderbaiduwww.baidu.com一般不需要添加https://因为文件中自动添加https://123453.运行爬虫代码scrapycrawl爬虫的名字eg:scrapycrawlbaiduimportscrapyclassBaiduSpider(scrapy.Spider):#爬虫的名字用于使用爬虫的时候使用的值name="baidu"#允许访问的域名allowed_domains=["www.baidu.com"]#起始的url地址指的是第一次访问的域名也就是在allowed_domains的前面加了https://start_urls=["https://www.baidu.com"]#运行start_urls之后执行的方法,方法中的responce就是返回的对象#相当于responce=urllib.request.urlopen()#也相当于responce=requests.get()defparse(self,response):print("苍茫的天涯是我的爱")123456789101112131415161736.58同城实例1.scrapy项目的结构项目名字项目名字spiders文件夹(存储的是爬出文件)init自定义的爬虫文件inititems定义数据结构的地方,爬取的内容都包含哪些middlewares中间件代理pipelines管道用来处理下载的数据settings配置文件一般robot协议,ua定义等2.responce的属性和方法responce.text获取相应的字符串responce.body获取的是二进制数据responce.xpath(’这里写xpath路径')直接用xpath方法来解析responce中的内容responce.extract()提取seletor对象的data属性值responce.extract_first()提取列表的第一个数据importscrapyclassTcSpider(scrapy.Spider):name="tc"allowed_domains=["cangzhou.58.com"]start_urls=["https://cangzhou.58.com/sou/?key=%E5%89%8D%E7%AB%AF%E5%BC%80%E5%8F%91"]defparse(self,response):content=response.textprint("====================")print(content)1234567891011121337.汽车之家importscrapyclassCarSpider(scrapy.Spider):name="car"allowed_domains=["car.autohome.com.cn"]#后面是html时,后面不能加/start_urls=["https://car.autohome.com.cn/price/brand-15.html"]defparse(self,response):name_list=response.xpath('//div[@class="main-title"]/a/text()')price_list=response.xpath('//div[@class="main-lever"]//span/span/text()')foriinrange(len(name_list)):name=name_list[i]price=price_list[i]print(name,price)1234567891011121314151617BOT_NAME="scrapy_carhome_003"SPIDER_MODULES=["scrapy_carhome_003.spiders"]NEWSPIDER_MODULE="scrapy_carhome_003.spiders"1234538.当当网当当网爬取书名,图片和价格importscrapyfromscrapy_dangdang_004.itemsimportScrapyDangdang004ItemclassDangSpider(scrapy.Spider):name="dang"allowed_domains=["category.dangdang.com"]start_urls=["https://category.dangdang.com/cp01.01.02.00.00.00.html"]base_url='https://category.dangdang.com/pg'page=1defparse(self,response):#pipeline下载数据#item定义数据结构#src='//ul[@id="component_59"]/li//img/@data-original'#alt='//ul[@id="component_59"]/li//img/@alt'#price='//ul[@id="component_59"]/li//p[@class="price"]/span[1]/text()'li_list=response.xpath('//ul[@id="component_59"]/li')forliinli_list:#第一张图片和其他的不一样src=li.xpath('.//img/@data-original').extract_first()ifsrc:src=srcelse:src=li.xpath('.//img/@src').extract_first()name=li.xpath('.//img/@alt').extract_first()price=li.xpath('.//p[@class="price"]/span[1]/text()').extract_first()book=ScrapyDangdang004Item(src=src,name=name,price=price)#yield就是返回一个值,有一个book就交给pipelinesyieldbook#每一页的爬取的业务逻辑都是一样的,所以我们只需要将执行的那个页面的请求再次调用parse方法就可以了ifself.page
|
|