首先确定你要爬取的目标网站的表单提交方式,可以通过开发者工具看到。这里推荐使用chrome。
这里我用163邮箱为例
打开工具后再Network中,在Name选中想要了解的网站,右侧headers里的request method就是提交方式。status如果是200表示成功访问下面的有头信息,cookie是你登录之后产生的存储会话(session)信息的。第一次访问该网页需要提供用户名和密码,之后只需要在headers里提供cookie就可以登陆进去。
引入requests库,会提供get和post的方法。
import requests import ssl user_agent="Mozilla/5.0 (Windows NT 10.0; WOW64; rv:50.0) Gecko/20100101 Firefox/50.0" accept='text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' accept_language='zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3'
upgrade='1'
headers={ 'User-Agent':user_agent, 'Accept':accept, 'Accept-Language':accept_language, 'Cookie':'....'#这里填入你登陆后产生的cookie }
r = requests.get("http://mail.163.com/js6/main.jsp?sid=OAwUtGgglzEJoANLHPggrsKKAhsyheAT&df=mail163_letter#module=welcome.WelcomeModule%7C%7B%7D",headers=headers,verify=False) fp = open("/temp/csdn.txt","w",encoding='utf-8') fp.write(str(r.content,'utf-8')) fp.close()
这里我引入了ssl库,因为我第一次访问的网页证书过期。
如果我们使用爬虫进入这样的网站时,会报错:SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:581)
在requests的get和post方法中,有一个参数为verify,把他设为False后会禁掉证书的要求
python爬虫 urllib模块发起post请求过程解析
urllib模块发起的POST请求
案例:爬取百度翻译的翻译结果
1.通过浏览器捉包工具,找到POST请求的url
针对ajax页面请求的所对应url获取,需要用到浏览器的捉包工具。查看百度翻译针对某个字条发送ajax请求,所对应的url
点击clear按钮可以把抓包工具,所抓到请求清空
然后填上翻译字条发送ajax请求,红色框住的都是发送的ajax请求
抓包工具All按钮代表 显示抓到的所有请求 ,包括GET、POST请求 、基于ajax的POST请求
XHR代表 只显示抓到的基于ajax的POST请求
哪个才是我们所要的基于ajax的POST请求,这个POST请求是携带翻译字条的苹果请求参数
再看看这个POST请求 对应的请求URL ,这个URL是我们要请求的URL
发起POST请求之前,要处理POST请求携带的参数
3步流程:
一、将POST请求封装到字典
二、使用parse模块中的urlencode(返回值类型是字符串类型)进行编码处理
三、将步骤二的编码结果转换成byte类型
import urllib.request
import urllib.parse
# 1.指定url
url = 'https://fanyi.baidu.com/sug'
# 发起POST请求之前,要处理POST请求携带的参数 流程:
# 一、将POST请求封装到字典
data = {
# 将POST请求所有携带参数放到字典中
'kw':'苹果',
}
# 二、使用parse模块中的urlencode(返回值类型是字符串类型)进行编码处理
data = urllib.parse.urlencode(data)
# 三、将步骤二的编码结果转换成byte类型
data = data.encode()
'''2. 发起POST请求:urlopen函数的data参数表示的就是经过处理之后的
POST请求携带的参数
'''
response = urllib.request.urlopen(url=url,data=data)
data = response.read()
print(data)
把拿到的翻译结果 去json在线格式校验(在线JSON校验格式化工具(Be JSON)),
点击格式化校验和unicode转中文
import re,json,requests,os from hashlib import md5 from urllib.parse import urlencode from requests.exceptions import RequestException from bs4 import BeautifulSoup from multiprocessing import Pool
#请求索引页 def get_page_index(offset,keyword): #传送的数据 data={ 'offset': offset, 'format': 'json', 'keyword': keyword, 'autoload': 'true', 'count': '20', 'cur_tab': 1 } #自动编码为服务器可识别的url url="https://www.toutiao.com/search_content/?"+urlencode(data) #异常处理 try: #获取返回的网页 response=requests.get(url) #判断网页的状态码是否正常获取 if response.status_code==200: #返回解码后的网页 return response.text #不正常获取,返回None return None except RequestException: #提示信息 print("请求索引页出错") return None
#解析请求的索引网页数据 def parse_page_index(html): #json加载转换 data=json.loads(html) #数据为真,并且data键值存在与数据中 if data and 'data' in data.keys(): #遍历返回图集所在的url for item in data.get('data'): yield item.get('article_url')
#图集详情页请求 def get_page_detail(url): #设置UA,模拟浏览器正常访问 head = { 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36'} #异常处理 try: response=requests.get(url,headers=head) if response.status_code==200: return response.text return None except RequestException: print("请求详情页出错") return None
#解析图集详情页的数据 def parse_page_detail(html,url): #异常处理 try: #格式转换与图集标题提取 soup=BeautifulSoup(html,'lxml') title=soup.select('title')[0].get_text() print(title)
#正则查找图集链接 image_pattern = re.compile('gallery: (.*?), ', re.S) result = re.search(image_pattern, html) if result: #数据的优化 result=result.group(1) result = result[12:] result = result[:-2] #替换 result = re.sub(r'\', '', result) #json加载 data = json.loads(result) #判断数据不为空,并确保sub——images在其中 if data and 'sub_images' in data.keys(): #sub_images数据提取 sub_images=data.get('sub_images') #列表数据提取 images=[item.get('url') for item in sub_images] #图片下载 for image in images:download_images(image) #返回字典 return { 'title':title, 'url':url, 'images':images } except Exception: pass
#图片url请求 def download_images(url): #提示信息 print('正在下载',url) #浏览器模拟 head = { 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36'} #异常处理 try: response = requests.get(url, headers=head) if response.status_code == 200: #图片保存 save_image(response.content) return None except RequestException: print("请求图片出错") return None
#图片保存 def save_image(content): #判断文件夹是否存在,不存在则创建 if '街拍' not in os.listdir(): os.makedirs('街拍') #设置写入文件所在文件夹位置 os.chdir('E:python写网路爬虫CSDN爬虫学习街拍') #路径,名称,后缀 file_path='{0}/{1}.{2}'.format(os.getcwd(),md5(content).hexdigest(),'jpg') #图片保存 with open(file_path,'wb') as f: f.write(content) f.close()
#主函数 def mian(offset): #网页获取 html=get_page_index(offset,'街拍') #图集url for url in parse_page_index(html): if url!=None: #图集网页详情 html=get_page_detail(url) #图集内容 result=parse_page_detail(html,url) if __name__ == '__main__':
#创建访问的列表(0-9)页 group=[i*10 for i in range(10)]
#创建多线程进程池 pool=Pool()
#进程池启动,传入的数据 pool.map(mian,group)
python爬虫 基于requests模块的get请求实现详解
import requests
# 1.指定url
url = 'https://www.sogou.com/'
# 2.发起get请求:get方法会返回请求成功的响应对象
response = requests.get(url=url)
# 3.获取响应中的数据:text属性作用是可以获取响应对象中字符串形式的页面数据
page_data = response.text
# 4.持久化数据
with open("sougou.html","w",encoding="utf-8") as f:
f.write(page_data)
f.close()
print("ok")
requests模块如何处理携带参数的get请求,返回携带参数的请求
需求:指定一个词条,获取搜狗搜索结果所对应的页面数据
之前urllib模块处理url上参数有中文的需要处理编码,requests会自动处理url编码
发起带参数的get请求
params可以是传字典或者列表
def get(url, params=None, **kwargs): r"""Sends a GET request. :param url: URL for the new :class:`Request` object. :param params: (optional) Dictionary, list of tuples or bytes to send in the body of the :class:`Request`. :param **kwargs: Optional arguments that ``request`` takes. :return: :class:`Response <Response>` object :rtype: requests.Response
import requests # 指定url url = 'https://www.sogou.com/web'
# 封装get请求参数 prams = { 'query':'周杰伦', 'ie':'utf-8' } response = requests.get(url=url,params=prams) page_text = response.text with open("周杰伦.html","w",encoding="utf-8") as f: f.write(page_text) f.close() print("ok")
利用requests模块自定义请求头信息,并且发起带参数的get请求
get方法有个headers参数 把请求头信息的字典赋给headers参数
import requests # 指定url url = 'https://www.sogou.com/web'
# 封装get请求参数 prams = { 'query':'周杰伦', 'ie':'utf-8' }
# 自定义请求头信息 headers={ 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36', }
response = requests.get(url=url,params=prams,headers=headers) page_text = response.text
with open("周杰伦.html","w",encoding="utf-8") as f: f.write(page_text) f.close() print("ok")
python爬虫 基于requests模块发起ajax的get请求实现解析
基于requests模块发起ajax的get请求
需求:爬取豆瓣电影分类排行榜 https://movie.douban.com/中的电影详情数据
用抓包工具捉取 使用ajax加载页面的请求
鼠标往下下滚轮拖动页面,会加载更多的电影信息,这个局部刷新是当前页面发起的ajax请求,
用抓包工具捉取页面刷新的ajax的get请求,捉取滚轮在最底部时候发起的请求
这个get请求是本次发起的请求的url
ajax的get请求携带参数
获取响应内容不再是页面数据,是json字符串,是通过异步请求获取的电影详情信息
start和limit参数 需要注意,改变这两个参数获取的电影详情不一样
import requests import json
# 指定ajax-get请求的url(通过抓包进行获取) url = 'https://movie.douban.com/j/chart/top_list?'
# 封装ajax的get请求携带的参数(从抓包工具中获取) 封装到字典 param = { 'type': '13', 'interval_id': '100:90', 'action': '', 'start': '20', # 从第20个电影开始获取详情 'limit': '20', # 获取多少个电影详情 # 改变这两个参数获取的电影详情不一样 }
# 定制请求头信息,相关的头信息必须封装在字典结构中 headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36', }
# 发起ajax的get请求还是用get方法 response = requests.get(url=url,params=param,headers=headers) # 获取响应内容:响应内容为json字符串 data = response.text data = json.loads(data) for data_dict in data: print(data_dict["rank"],data_dict["title"]) ''' 芙蓉镇 沉静如海 淘金记 马戏团 情迷意乱 士兵之歌 战争与和平 怦然心动 大话西游之月光宝盒 罗马假日 音乐之声 一一 雨中曲 我爱你 莫娣 卡比利亚之夜 婚姻生活 本杰明·巴顿奇事 情书 春光乍泄 '''
post请求:
#!user/bin/python #coding=utf-8 或者 #-*-coding:utf-8-*- #导入工具,内置的库 import urllib import urllib2
#加一个可以换行 #response = #urllib2.urlopen("https://hao.360.cn/?wd_xp1") #print response.read()
request = urllib2.Request('http://www.baidu.com') #response = urllib2.urlopen(request)
#构造post请求 params={} params['account']='jredu' params['pwd']=''
#对数据进行编码 data = urllib.urlencode(params) response = urllib2.urlopen(request,data) print response.url print response.code print response.read()
get请求:
#导入工具,内置的库 import urllib import urllib2 #加一个可以换行 #response = #urllib2.urlopen("https://hao.360.cn/?wd_xp1") #print response.read() url='http://www.baidu.com' #response = urllib2.urlopen(request)
#构造post请求 params={} params['account']='jredu' params['pwd']=''
#对数据进行编码 data = urllib.urlencode(params) request = urllib2.Request(url+"?"+data) response = urllib2.urlopen(request) print response.url print response.code print response.read()
Python大数据之使用lxml库解析html网页文件示例
lxml是Python的一个html/xml解析并建立dom的库,lxml的特点是功能强大,性能也不错,xml包含了ElementTree ,html5lib ,beautfulsoup 等库。
使用lxml前注意事项:先确保html经过了utf-8解码,即code =html.decode('utf-8', 'ignore')
,否则会出现解析出错情况。因为中文被编码成utf-8之后变成 '/u2541' 之类的形式,lxml一遇到 "/"就会认为其标签结束。
具体用法:元素节点操作
1、 解析HTMl建立DOM
from lxml import etree
dom = etree.HTML(html)
2、 查看dom中子元素的个数 len(dom)
3、 查看某节点的内容:etree.tostring(dom[0])
4、 获取节点的标签名称:dom[0].tag
5、 获取某节点的父节点:dom[0].getparent()
6、 获取某节点的属性节点的内容:dom[0].get("属性名称")
对xpath路径的支持:
XPath即为XML路径语言,是用一种类似目录树的方法来描述在XML文档中的路径。比如用"/"来作为上下层级间的分隔。第一个"/"表示文档的根节点(注意,不是指文档最外层的tag节点,而是指文档本身)。比如对于一个HTML文件来说,最外层的节点应该是"/html"。
xpath选取元素的方式:
1、 绝对路径,如page.xpath("/html/body/p")
,它会找到body这个节点下所有的p标签
2、 相对路径,page.xpath("//p")
,它会找到整个html代码里的所有p标签。
xpath筛选方式:
1、 选取元素时一个列表,可通过索引查找[n]
2、 通过属性值筛选元素p =page.xpath("//p[@style='font-size:200%']")
3、 如果没有属性可以通过text()(获取元素中文本)、position()(获取元素位置)、last()等进行筛选
获取属性值
dom.xpath(.
/
/
a
/
@href)
获取文本
dom.xpath(
".//a/text()"
)
#!/usr/bin/python # -*- coding:utf-8 -*- from scrapy.spiders import Spider from lxml import etree from jredu.items import JreduItem class JreduSpider(Spider): name = 'tt' #爬虫的名字,必须的,唯一的 allowed_domains = ['sohu.com'] start_urls = [ 'http://www.sohu.com' ] def parse(self, response): content = response.body.decode('utf-8') dom = etree.HTML(content) for ul in dom.xpath("//div[@class='focus-news-box']/div[@class='list16']/ul"): lis = ul.xpath("./li") for li in lis: item = JreduItem() #定义对象 if ul.index(li) == 0: strong = li.xpath("./a/strong/text()") li.xpath("./a/@href") item['title']= strong[0] item['href'] = li.xpath("./a/@href")[0] else: la = li.xpath("./a[last()]/text()") item['title'] = la[0] item['href'] = li.xpath("./a[last()]/href")[0] yield item