赞
踩
import requests
# 指定url
# 发起请求,get方法会返回一个响应对象
res=requests.get(r'https://www.sogou.com/')
# 获取响应数据,text返回字符串类型的响应数据
str=res.text
print(str)
# 持久化存储
with open('./sogou.html','w',encoding='utf-8') as fp:
fp.write(str)
print('爬取结束')
结果:
网址中有很多字母数字,我们只选择出有用的部分:
这么处理以后,页面还是一样的!
粘贴到Pycharm中会自动编码。(使用中文也没问题)
UA:User-Agent(请求载体的身份标识)
我们使用requess.get去请求网页就不再是以浏览器的身份去访问,而是以爬虫程序去访问,门户网站的服务器会检测对应请求的载体身份标识,如果检测到为某一款浏览器,这个请求会被当作正常用户请求。
但是,如果检测到不是基于浏览器访问,则被视为不正常请求!(爬虫),则服务器很有可能拒绝该请求!
查询User-Agent:
所以我们一定要进行UA伪装!!! 伪装成某一款浏览器。
import requests if __name__=='__main__': # UA伪装:将user-agent封装到字典中 headers={ 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36' } url='https://www.sogou.com/web' # 处理url携带的参数:封装到字典中(因为要动态收集) kw=input('enter a word:') param={ 'query':kw } # 对指定的url发起的请求对应的url是携带参数的,并且请求过程中处理了参数 # headers代表头信息(用于UA伪装) response=requests.get(url=url,params=param,headers=headers) page_text=response.text fileName=kw+'.html' with open(fileName,'w',encoding='utf-8') as fp: fp.write(page_text) print(fileName,'保存成功!!!')
比较翻译前后的url:
https://fanyi.baidu.com/?aldtype=16047#auto/zh/
# 翻译dog
https://fanyi.baidu.com/?aldtype=16047#en/zh/dog
# 翻译狗
https://fanyi.baidu.com/?aldtype=16047#zh/en/%E7%8B%97(这里也可以写成狗)
它实际上是在你输入内容后进行局部页面刷新(不用你自己刷新)从而实现翻译。
通过使用谷歌自带抓包工具,进行抓包,没输入一个字符就观察一次,因为它涉及到局部页面刷新,属于ajax请求,所以要在Network中选择XHR进行查看。
最后发现,是第三个sug中包含了我们输入的参数dog,所以我们只需要这个内容中的URL地址。
并且可以看到,返回的数据为json串。(就是我们想要的数据)
从Content-Type可以看出响应数据的类型!
data和params一样都用来处理参数。
上面的kw:dog就代表它的参数
实际上就是post是要携带用户信息的请求方式,get则是根据URL直接获取网页信息(即某个网址所包含的信息)。
post要获取的内容只靠网址是不能获取到的,需要提交一些额外的信息,这种信息在不同的网页中发挥不同功能。 例如在查询天气的网页,可能就是要输入城市信息;在登录某些网页时,又是账号和密码的载体。从这些可以看出get方法获取到的内容是稳定的(即每个人打开某个网页获得的信息相同),但是使用post需要输入特定信息,那么得到的网页内容就会有特异性。
post每次获取某个特定网页都需要输入额外信息,但get则直接输入URL即可(),这样也能看出post方法更加安全,因为额外信息不会直接暴露在网址上。
(百度翻译是post,因为需要我们向它传递dog这个数据,它才会返回值)
import requests import json if __name__=="__main__": # 1、指定url post_url='https://fanyi.baidu.com/sug' # 2、进行UA伪装 headers={ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36' } # 3、post请求参数处理(同get请求一致) data={ 'kw':'dog' } # 4、请求发送 response=requests.post(url=post_url,data=data,headers=headers) # 5、获取响应数据(返回的是json)使用.json()返回的是对象 # 如果确认服务器响应数据是json类型的,才可以使用.json() dic_obj=response.json() # print(dic_obj) # 6、持久化存储 fp=open('./dog.json','w',encoding='utf-8') # 使用json.dump存储json文件,因为结果有中文,中文不支持ascii码,所以要设置为False json.dump(dic_obj,fp=fp,ensure_ascii=False) print('Over!!!')
使用[‘data’]即可获取data部分的list,进而使用它的相关数据。
在翻译dog的基础上,我们同样可以将dog设置成一个参数,通过我们传入的参数不同以达到获取不同单词的翻译结果。
动态化获取:
import requests import json if __name__=="__main__": # 1、指定url post_url='https://fanyi.baidu.com/sug' # 2、进行UA伪装 headers={ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36' } # 3、post请求参数处理(同get请求一致) word=input('enter a word:') data={ 'kw':word } # 4、请求发送 response=requests.post(url=post_url,data=data,headers=headers) # 5、获取响应数据(返回的是json)使用.json()返回的是对象 # 如果确认服务器响应数据是json类型的,才可以使用.json() dic_obj=response.json() # print(dic_obj) # 6、持久化存储 filename='./'+word+'.json' fp=open(filename,'w',encoding='utf-8') # 使用json.dump存储json文件,因为结果有中文,中文不支持ascii码,所以要设置为False json.dump(dic_obj,fp=fp,ensure_ascii=False) print('Over!!!')
进入这个网址:豆瓣
当滑动滚轮时,滑到底部的时候页面会进行刷新使得右边的滑块又跑到了中央,所以我们可以利用这次刷新进行数据收集。
经过验证,确实是产生了ajax请求,和上面百度翻译类似。
下面是携带的五个参数。
意思就是说:我们让这个url发送get请求,并携带参数,就可以获取到响应的json文件,再进行持续化存储。
从?后开始到最后就是传递的参数,我们使用字典存储,也方便之后动态化。
我们也可以通过下图来获取具体的参数,直接复制到字典中存储即可。
根据每次滑动的变化,我们可以对每个参数值的含义进行猜测:(见代码)
import requests import json if __name__=="__main__": url='https://movie.douban.com/j/chart/top_list' param={ 'type':'24', 'interval_id':'100:90', 'action':'', 'start':'0', #从库中第几部电影去取 'limit':'20', #一次请求取出的个数 } headers={ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36' } # 属于get请求 response=requests.get(url=url,params=param,headers=headers) list_data=response.json() fp=open('./douban.json','w',encoding='utf-8') json.dump(list_data,fp=fp,ensure_ascii=False) print('Over!!!')
第一部电影确实是憨豆先生,实现了爬取。
(之后就是进一步的数据处理)
进入网址:http://www.kfc.com.cn/kfccda/storelist/index.aspx
发现,这又是一个局部网页刷新,所以和之前豆瓣一样,通过比对输入关键字前后抓包发生的变化,从而实现爬取。
import requests if __name__=="__main__": post_url='http://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=keyword' data={ 'cname':'', 'pid':'', 'keyword': '四川', 'pageIndex': '1', 'pageSize': '10', } headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36' } response=requests.post(url=post_url,data=data,headers=headers) # 返回对象是text类型,编码为utf-8 fp=open('./KFC.txt','w',encoding='utf-8') fp.write(response.text) print('Over!!!')
import requests
if __name__=="__main__":
url='http://scxk.nmpa.gov.cn:81/xk/'
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36'
}
response=requests.get(url=url,headers=headers)
print(response.text)
验证后发现,它并不是直接通过html实现数据的显示,可能是ajax实现,再进行验证。
也可以直接抓包,看对应的url是否有需要的数据:
这些由其它请求产生的数据,我们可以叫他们是动态加载出来的数据!
进行ajax抓包验证:
可以发现,首页的数据是由ajax提供的!
但我们需要的是每一家企业的详情页中的所有信息,该如何处理呢?
我们发现,每一行公司数据中都包含着一个ID数据,我们点开其中一个,进入详情页:
发现,该详情页的url是通过id来进行访问的,意思是每个id都对应了一个唯一的详情页面,我们可以先获取它的id,再以它的id为参数,进行详情页面的请求,即可实现详细信息的爬取。
我们对详情页进行抓包,又发现:
这个网页又是ajax刷新出来的动态网页,所以又可以通过之前的处理办法,提取其中的json文件:
同时也发现了它的参数(id)如下:
域名和id值进行拼接,拼接出一个完整的企业对应的详情页url。
注意:如果是post型,一定要记得传入参数!否则什么都得不到,因为post需要你向服务器提供数据,它才会返回相关的数据给你!
我们先对具体的详情页面进行试验,发现可以进行爬取:
import requests import json if __name__=="__main__": url='http://scxk.nmpa.gov.cn:81/xk/itownet/portalAction.do?method=getXkzsById' headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36' } data={ 'id': 'ed59438f34ae47e794f4c7ee5137c1f7', } response=requests.post(url=url,data=data,headers=headers) list_data=response.json() fp=open('./药监局.json','w',encoding='utf-8') json.dump(list_data,fp=fp,ensure_ascii=False) print('Over!!!')
接下来的任务就是将首页中获取的id与详情页面的url联系在一起,从而实现详情页的爬取:
import requests import pandas as pd import json if __name__=="__main__": # 1、批量获取不同企业的id值 url='http://scxk.nmpa.gov.cn:81/xk/itownet/portalAction.do?method=getXkzsList' # 首页的请求为post,返回值为json headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36' } # 传入post所需参数 data={ 'on': 'true', 'page': '1', #代表第几页 'pageSize': '15', 'productName':'', 'conditionType': '1', 'applyname':'', 'applysn':'', } response=requests.post(url=url,data=data,headers=headers) list_data=response.json()['list'] list_id=[] for i in list_data: # 存入相关的id(共15个) list_id.append(i['ID']) # print(i) # print(list_id) # ['ed59438f34ae47e794f4c7ee5137c1f7', 'd5046c860bbb4e5198fa0dd99382b262', '8bc468fcdb83488681c616d2f7c59149', # '5e45595403cc4509a266666a8a513c46', '246c9e4e2ad64e3f9518908e97a826f7', '76ec5f5a9048457986029282d0f99551', # '670daa3bed864e029c4a17479314240b', '6aab6520cc164b9c9a86d3b5a371152e', 'e8d9c8e820f64c9b8b4c913bafdffecc', # 'f546d7d0b7a34944814291e2c0808500', 'aa42d5a6f10349b98f2fea44867a792c', '7b11ca443c804922815a9410e1fc6c3a', # '72cf694b44a34627b27f6174332b69b1', '47cad475ffb6445da68a8eb83d89fd5f', '165b8a8d86314d5096ebe4e97ca0dd31'] # 2、获取企业详情数据 post_url='http://scxk.nmpa.gov.cn:81/xk/itownet/portalAction.do?method=getXkzsById' # 同样也是post型,需要传入具体的参数 final_data=[] for i in list_id: # 遍历之前我们获取到的每一个id,进行每一个数据的读取 post_data = { 'id': i } post_response = requests.post(url=post_url, data=post_data, headers=headers) final_data.append(post_response.json()) final_data=pd.DataFrame(final_data) # 将数据存入csv表格中 # csv表格的编码为gbk,pycharm自带的编码是utf-8 final_data.to_csv('药监局.csv',encoding='gbk')
进一步,对所有页码进行遍历:(就是多了个循环,用于对页码进行遍历)
import requests import pandas as pd if __name__=="__main__": # 用于存储所有获取到的数据 final_data = [] # 1、批量获取不同企业的id值 url='http://scxk.nmpa.gov.cn:81/xk/itownet/portalAction.do?method=getXkzsList' post_url = 'http://scxk.nmpa.gov.cn:81/xk/itownet/portalAction.do?method=getXkzsById' # 首页的请求为post,返回值为json headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36' } # 传入post所需参数 for page in range(1,6): #先只要前五页 page=str(page) data={ 'on': 'true', 'page': page, #代表第几页 'pageSize': '15', #代表一页有15个id 'productName':'', 'conditionType': '1', 'applyname':'', 'applysn':'', } response=requests.post(url=url,data=data,headers=headers) list_data=response.json()['list'] list_id=[] for i in list_data: # 存入相关的id(共15个) list_id.append(i['ID']) # print(i) # 2、获取企业详情数据 # 同样也是post型,需要传入具体的参数 for i in list_id: # 遍历之前我们获取到的每一个id,进行每一个数据的读取 post_data = { 'id': i } post_response = requests.post(url=post_url, data=post_data, headers=headers) final_data.append(post_response.json()) final_data=pd.DataFrame(final_data) # 将数据存入csv表格中 # csv表格的编码为gbk,pycharm自带的编码是utf-8 final_data.to_csv('药监局ALL.csv',encoding='gbk')
数据解析原理:使用数据解析,是因为有一些数据存在于标签之间或者在标签对应的属性值中。我们需要定位到具体标签的位置,或是标签相应的属性的位置,再获取标签中相关的数据。
大致有三类:
1、正则(适用于多种语言)
2、bs4(仅适用于Python)
3、xpath(重要)
编码流程变为:
1、指定url
2、发起请求
3、获取相应数据
4、数据解析
5、持久化存储
从网站中可以看到:
图片是存储在具体的一个网页中的。
import requests
if __name__=='__main__':
#如何爬取图片
url='http://pic.qiushibaike.com/system/pictures/12413/124132664/medium/LBBZ8DUMBG0M6JEZ.jpg'
#content返回的是二进制形式的图片数据
# text(字符串) content(二进制) json()(对象)
img_data=requests.get(url=url).content
with open('./qiutu.jpg','wb') as fp:
fp.write(img_data)
步骤如下:先获取一整个页面,再对这个页面进行解析,获取其中的图片。
进行滑动后发现,它并不会像豆瓣一样动态更新,而是直接一页显示完,我们可以通过遍历page来获取所有图片。
可以发现,红框标签中包含了这一页的所有糗图。
进一步发现,在每一个糗图子类中的thumb标签下,存储了糗图(只有糗图,没有其他文字):
img src中存放的就是图片的地址(.jpg):
import requests import re if __name__=="__main__": url='https://www.qiushibaike.com/imgrank/' headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36' } # 使用通用爬虫对url对应的一整张页面进行爬取 response=requests.get(url=url,headers=headers) # 获取源码数据 page_text=response.text # 使用聚焦爬虫将页面中所有具体图片进行聚焦爬虫 # 我们需要获取所有图片对应的src值,再对每个src值单独发送请求,得到每一张图片 # < div class ="thumb" > # # < a href = "/article/124132664" target = "_blank" > # < img src = "//pic.qiushibaike.com/system/pictures/12413/124132664/medium/LBBZ8DUMBG0M6JEZ.jpg" alt = "糗事#124132664" class ="illustration" width="100%" height="auto" > # < / a > # # < / div > ex='<div class="thumb">.*?<img src="(.*?)" alt.*?</div>' img_src_list=re.findall(ex,page_text,re.S) print(img_src_list) # 发现存下来的地址缺少协议头:https: # '//pic.qiushibaike.com/system/pictures/12412/124120243/medium/BOKRF0W5573YHP7J.jpg' # 在添加协议头后,再使用get即可获取图片
这里的html head body div都是tagName(标签名)
它只返回第一次出现的tagName对应的标签,不能返回多个。
1)soup.find(‘div’)等同于soup.div
2)属性定位(根据具体属性定位到对应属性的标签)
soup.find(‘div’,class_/id/attr=‘song’)(这里class要加下划线,不然会被当作关键字)
find_all会返回符合要求的所有标签,用法同soup.find()
需要传入某种选择器(id、类、标签选择器),返回是一个列表
class选择器:.类名
标签选择器:直接写标签名
id选择器:#Id
层级选择器:
(大于号表示一个层级,也可以将大于号替换为空格,代表之间有多个层级)
soup.select(’.tang > ul > li > a’):查找.tang类下的ul标签下的li标签下的a标签
print(soup.select('div .thumb > a > img'))
选择div标签中类名为thumb的类下面的标签为a的下面的标签为img的内容。
[<img alt="糗事#124138955" class="illustration" height="auto" src="//pic.qiushibaike.com/system/pictures/12413/124138955/medium/G7V66LF8S6TGOU6G.jpg" width="100%"/>, <img alt="糗事#124136388" class="illustration" height="auto" src="//pic.qiushibaike.com/system/pictures/12413/124136388/medium/48MW1SMPCL45S4Z4.jpg" width="100%"/>, <img alt="糗事#124123833" class="illustration" height="auto" src="//pic.qiushibaike.com/system/pictures/12412/124123833/medium/PGFQADGTCL8T0EMD.jpg" width="100%"/>, <img alt="糗事#124130144" class="illustration" height="auto" src="//pic.qiushibaike.com/system/pictures/12413/124130144/medium/0RUTLVJ9L534RDCG.jpg" width="100%"/>, <img alt="糗事#124129027" class="illustration" height="auto" src="//pic.qiushibaike.com/system/pictures/12412/124129027/medium/MZ936V0QCZBA0DIX.jpg" width="100%"/>, <img alt="糗事#124015279" class="illustration" height="auto" src="//pic.qiushibaike.com/system/pictures/12401/124015279/medium/B8ROANAYSIWZQ07X.jpg" width="100%"/>, <img alt="糗事#124039381" class="illustration" height="auto" src="//pic.qiushibaike.com/system/pictures/12403/124039381/medium/N6P3FHIGAV0N4Q1U.jpg" width="100%"/>, <img alt="糗事#124132227" class="illustration" height="auto" src="//pic.qiushibaike.com/system/pictures/12413/124132227/medium/C4MRAF8159IZEAD9.jpg" width="100%"/>, <img alt="糗事#124131947" class="illustration" height="auto" src="//pic.qiushibaike.com/system/pictures/12413/124131947/medium/ES1BAH06YM3O2AC7.jpg" width="100%"/>, <img alt="糗事#124137047" class="illustration" height="auto" src="//pic.qiushibaike.com/system/pictures/12413/124137047/medium/FZIWPL2PFOFYQMRQ.jpg" width="100%"/>, <img alt="糗事#124138959" class="illustration" height="auto" src="//pic.qiushibaike.com/system/pictures/12413/124138959/medium/EULVRT9M3ZZFDQOQ.jpg" width="100%"/>, <img alt="糗事#124139238" class="illustration" height="auto" src="//pic.qiushibaike.com/system/pictures/12413/124139238/medium/JY5AT3YY3JTA4SSY.jpg" width="100%"/>, <img alt="糗事#124128456" class="illustration" height="auto" src="//pic.qiushibaike.com/system/pictures/12412/124128456/medium/INCK9584YU11CLCO.jpg" width="100%"/>, <img alt="糗事#124134443" class="illustration" height="auto" src="//pic.qiushibaike.com/system/pictures/12413/124134443/medium/4WYYQG8Z3VD7AQ9Z.jpg" width="100%"/>, <img alt="糗事#124131716" class="illustration" height="auto" src="//pic.qiushibaike.com/system/pictures/12413/124131716/medium/LTK72H5NS7X3KO0R.jpg" width="100%"/>, <img alt="糗事#123999393" class="illustration" height="auto" src="//pic.qiushibaike.com/system/pictures/12399/123999393/medium/EWBBQAMBHDBE3H4G.jpg" width="100%"/>, <img alt="糗事#124135221" class="illustration" height="auto" src="//pic.qiushibaike.com/system/pictures/12413/124135221/medium/0R2D84TTU3GHBOJG.jpg" width="100%"/>, <img alt="糗事#124131622" class="illustration" height="auto" src="//pic.qiushibaike.com/system/pictures/12413/124131622/medium/BJS1EAY8DK0M2Q59.jpg" width="100%"/>, <img alt="糗事#124130884" class="illustration" height="auto" src="//pic.qiushibaike.com/system/pictures/12413/124130884/medium/TZF8FMUCXDKKZWM3.jpg" width="100%"/>, <img alt="糗事#124135578" class="illustration" height="auto" src="//pic.qiushibaike.com/system/pictures/12413/124135578/medium/9S28RZ4PIP610QQ5.jpg" width="100%"/>, <img alt="糗事#124136384" class="illustration" height="auto" src="//pic.qiushibaike.com/system/pictures/12413/124136384/medium/YHEGWI2C4DVYR7BV.jpg" width="100%"/>, <img alt="糗事#124134929" class="illustration" height="auto" src="//pic.qiushibaike.com/system/pictures/12413/124134929/medium/JP7Q2UQ4XTG8ZPGF.jpg" width="100%"/>, <img alt="糗事#124129563" class="illustration" height="auto" src="//pic.qiushibaike.com/system/pictures/12412/124129563/medium/FQAINA29JKXU181G.jpg" width="100%"/>, <img alt="糗事#124139821" class="illustration" height="auto" src="//pic.qiushibaike.com/system/pictures/12413/124139821/medium/V41ONJ5MYOZRHABV.jpg" width="100%"/>, <img alt="糗事#124123264" class="illustration" height="auto" src="//pic.qiushibaike.com/system/pictures/12412/124123264/medium/AHAVUX4WW70CAMRI.jpg" width="100%"/>]
之前是定位到具体的标签,现在是利用定位到的具体标签来提取其中的数据。
soup.a.text/string/get_text(),用于读取文本数据
text/get_text():可以获取一个标签中的所有文本内容
string:只可以获取该标签下面直系的文本内容
我们上面想要的src不属于文本数据!
直接使用 [ 属性名 ]
print(soup.select('div .thumb a img')[0]['src'])
我们成功从中提取到了src!!!
//pic.qiushibaike.com/system/pictures/12405/124058306/medium/X8FX01T2TYWYF66L.jpg
这个跟爬取药监局的例子相似,需要现在主页面获取到每一个子页面的url,再对每一个子页面进行访问,读取子页面中的文本内容。
这个网站并不是动态加载(ajax),而是将具体网址写入标签属性中,所以需要用到数据解析!(药监局那个是动态加载)
import requests from bs4 import BeautifulSoup if __name__=="__main__": # 对首页页面数据进行爬取 url='https://www.shicimingju.com/book/sanguoyanyi.html' # 进行UA伪装 headers={ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36' } page_text=requests.get(url=url,headers=headers).text # 在首页中解析出章节的标题和详情页的url # 1、实例化Beautiful Soup对象,将页面源码加载到该对象中 soup=BeautifulSoup(page_text,'lxml') # print(soup.select('.book-mulu li a')) book_list=soup.select('.book-mulu li a') book_url=[] # https://www.shicimingju.com/book/sanguoyanyi/1.html # 对比原网址,添加https://www.shicimingju.com head='https://www.shicimingju.com' for i in book_list: temp_str=head+i['href'] book_url.append(temp_str) # print(book_url) # 'https://www.shicimingju.com/book/sanguoyanyi/1.html' # 将书中内容存入字典 books={} fp=open('./sanguo.txt','w',encoding='utf-8') for url in book_url: page_text=requests.get(url=url,headers=headers).text soup=BeautifulSoup(page_text,'lxml') div_tag=soup.find('div',class_='chapter_content') content=div_tag.text print(content)
最常用且最便捷高效的一种新方法,通用性。
xpath解析原理:
1、实例化一个etree的对象,且需要将被解析的页面源码数据加载到该对象中
2、调用etree对象中的xpath方法,结合着xpath表达式实现标签的定位和内容的捕获
如何实例化一个etree对象:from lxml import etree
1、将本地html文档重点源码数据加载到etree对象中:
etree.parse(filePath)
2、可以将从互联网上获取的源码加载到该对象中:
etree.HTML(‘page_text’)
xpath(‘xpath表达式’),返回一个列表!
response=requests.get(url=url,headers=headers).text
tree=etree.HTML(response)
r=tree.xpath('/html/head/title')
r=tree.xpath('/html//div')
r=tree.xpath('//div')
/ 表示从根节点开始,一个 / 表示一个层级,而//表示多个层级,或者表示可以从任意位置开始定位。(所有)
属性定位:
tagName[@attrName=“attrValue”]
r=tree.xpath('//div[@class="song"]')
索引定位:
r=tree.xpath('//div[@class="song"]/p')
表示div标签下,类名为song下的p标签,可以在后面使用 [1] 索引,从1开始!!!
取文本:
r=tree.xpath('//div[@class="song"]/ul/li[1]/a/text()')
# 返回结果为列表
取得,a标签下的文本内容。
/text(),获取的是标签中直系的文本内容
//text(),获取的是标签中非直系(所有的)文本内容
取属性:
r=tree.xpath('//div[@class="song"]/img/@src')
# 返回结果为列表
/@属性名 (/@src,获取img标签下的src属性)
回顾一下,我们是怎么判断网页中的数据是否为动态加载:
打开抓包工具,在当前网页的url对应内容中进行搜索,看是否有相应的内容:
搜索不到,显然就是动态加载的!
那如何快速,准确的找到需要的数据在哪里呢?
在红框中按下 ctrl + f 输入你需要查询的信息,进行搜索。
可以发现,如果使用像上面的方法进行查找的话,会比较耗时,我们就需要使用selenium模块!
1、它能帮助便捷的获取网站中动态加载的数据!
2、便捷地使用模拟登陆!
selenium是基于浏览器自动化的一个模块。(就是自动地使用浏览器的相关功能,让他自己去操纵浏览器,不用我们自己去弄)
环境安装:pip install selenium
下载一个浏览器的驱动程序:
http://npm.taobao.org/mirrors/chromedriver/
驱动程序和版本要对应。对照表
再把驱动放在你项目的文件夹中。
实例化一个浏览器对象(传入浏览器的驱动程序)
from selenium import webdriver
# 实例化一个浏览器对象(传入浏览器的驱动程序)
bro=webdriver.Chrome(executable_path='./chromedriver.exe')
用代码操纵你的浏览器!
以药监局的例子为例:
1、先操纵浏览器打开药监局的网站:
from selenium import webdriver
# 实例化一个浏览器对象(传入浏览器的驱动程序)
bro=webdriver.Chrome(executable_path='./chromedriver.exe')
# 对指定网页发送请求
bro.get('http://scxk.nmpa.gov.cn:81/xk/')
2、获取浏览器当前页面的页面源码数据(公司名字)
from selenium import webdriver from lxml import etree from time import sleep # 实例化一个浏览器对象(传入浏览器的驱动程序) bro=webdriver.Chrome(executable_path='./chromedriver.exe') # 对指定网页发送请求 bro.get('http://scxk.nmpa.gov.cn:81/xk/') # 获取浏览器当前页面的源码数据 page_text=bro.page_source # 解析企业名称(以xpath为例) tree=etree.HTML(page_text) li_list=tree.xpath('//ul[@id="gzlist"]/li') for li in li_list: name=li.xpath('./dl/@title')[0] print(name) # 关闭浏览器 sleep(5) #暂停五秒后关闭 bro.quit()
3、其他自动化操作(以淘宝搜索为例)
我们要先找到搜索框在哪里?
打开检查,找到搜索框对应的源码,发现里面有一个input标签,id=‘q’。
标签定位:
search_input=bro.find_element_by_id('q')
如何向搜索框中传值呢?
search_input=bro.find_element_by_id('q')
# 标签交互(传入想输入搜索框的东西)
search_input.send_keys('Iphone')
我们还需要点击搜索按钮,我们再去找搜索按钮对应的源码:
它有两个标签名,用哪一个都行但不能一起用!
from selenium import webdriver from time import sleep bro=webdriver.Chrome(executable_path='./chromedriver.exe') bro.get('https://www.taobao.com/') # 想要通过搜索框搜索数据 # 先要找到那个搜索框(标签定位) search_input=bro.find_element_by_id('q') # 标签交互(传入想搜索的东西) search_input.send_keys('Iphone') # 点击搜索按钮 btn=bro.find_element_by_css_selector('.btn-search') #这里用class搜索也可以 sleep(3) btn.click()
因为没有登录,所以运行结果如下:
如何实现页面滚轮下滑效果呢?
进入网页检查中的console输入:
即可实现滚轮效果,现在需要使得程序知道怎么操作。
from selenium import webdriver from time import sleep bro=webdriver.Chrome(executable_path='./chromedriver.exe') # 发起请求 bro.get('https://www.taobao.com/') # 想要通过搜索框搜索数据 # 先要找到那个搜索框(标签定位) search_input=bro.find_element_by_id('q') # 标签交互(传入想搜索的东西) search_input.send_keys('Iphone') # 实现滚轮下滑效果 # 需要执行一组js程序 bro.execute_script('window.scrollTo(0,document.body.scrollHeight)') sleep(2) # 点击搜索按钮 btn=bro.find_element_by_css_selector('.btn-search') #这里用class搜索也可以 bro.get('https://www.baidu.com') sleep(2) # 回退(倒退) bro.back() sleep(2) # 前进 bro.forward() sleep(3) btn.click()
什么是iframe???
用于实现网页的嵌套。
我们来看看如何拖动一个方块:
我们先找到需要被拖动方块的源码。
为什么会报错呢?
它说没有找到我们想要的标签,我们id也没有输错。
原因:
它是包含在一个叫做iframe的标签下,所以才导致程序无法找到。
如何定位的标签存在于iframe标签之中,直接寻找是寻找不到的!
实现在iframe下的定位:
from selenium import webdriver
from time import sleep
bro=webdriver.Chrome(executable_path='./chromedriver.exe')
bro.get('https://www.runoob.com/try/try.php?filename=jqueryui-api-droppable')
# 如何定位的标签存在于iframe标签之中,直接寻找是寻找不到的!
# 传入的参数是Id
bro.switch_to.frame('iframeResult') #切换浏览器标签定位的作用域(默认为最外面大的html标签)
div=bro.find_element_by_id('draggable')
模拟人操作鼠标,进行滑块的拖动:
from selenium import webdriver from time import sleep # 导入动作链对应的类 from selenium.webdriver import ActionChains bro=webdriver.Chrome(executable_path='./chromedriver.exe') bro.get('https://www.runoob.com/try/try.php?filename=jqueryui-api-droppable') # 如何定位的标签存在于iframe标签之中,直接寻找是寻找不到的! # 传入的参数是Id bro.switch_to.frame('iframeResult') #切换浏览器标签定位的作用域(默认为最外面大的html标签) div=bro.find_element_by_id('draggable') # 动作链 action=ActionChains(bro) # 点击长按指定的标签 action.click_and_hold(div) for i in range(5): # perform()立即执行动作链操作 action.move_by_offset(17,0).perform() #做移动偏移(x,y)传入水平、竖直方向偏移 sleep(0.3) # 释放工作链 action.reset_actions() bro.quit()
主要就是红框中的三个模块:账号、密码、登录按钮。
由于,默认情况下,是要我们进行扫码,我们还需要点击右下角账号密码登录。
注意!这里的账号密码登录还是在iframe标签下!!所以不能直接请求。
from selenium import webdriver
from time import sleep
bro=webdriver.Chrome(executable_path='../../chromedriver.exe')
bro.get('https://qzone.qq.com/')
# 参数为id
bro.switch_to.frame('login_frame')
a_tag=bro.find_element_by_id('switcher_plogin')
a_tag.click() #定位到之后进行点击
定位账号和密码:
from selenium import webdriver from time import sleep bro=webdriver.Chrome(executable_path='../../chromedriver.exe') bro.get('https://qzone.qq.com/') # 参数为id bro.switch_to.frame('login_frame') a_tag=bro.find_element_by_id('switcher_plogin') a_tag.click() #定位到之后进行点击 # 寻找用户名、密码输入框 userName_tag=bro.find_element_by_id('u') passWord_tag=bro.find_element_by_id('p') # 录入数据 userName_tag.send_keys('1229482340') passWord_tag.send_keys('1111') # 寻找工作按钮 btn=bro.find_element_by_id('login_button') btn.click() sleep(3) bro.quit()
现在不能直接登录,需要进行滑块验证!
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
# 无可视化参数
chrome_options=Options()
chrome_options.add_argument('--headless')
chrome_options.add_argument('--disable-gpu')
bro=webdriver.Chrome(executable_path='./chromedriver.exe',options=chrome_options)
bro.get('https://www.baidu.com')
from selenium import webdriver # 实现无头浏览器 from selenium.webdriver.chrome.options import Options # 实现规避检测 from selenium.webdriver import ChromeOptions # 无可视化参数 chrome_options=Options() chrome_options.add_argument('--headless') chrome_options.add_argument('--disable-gpu') # 如何让selenium规避被检测到的风险 option=ChromeOptions() option.add_experimental_option('excludeSwitches',['enable-automation']) bro=webdriver.Chrome(executable_path='./chromedriver.exe',chrome_options=chrome_options,options=option) bro.get('https://www.baidu.com')
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。