前几天就想写一个爬虫系列的文章,由于比较忙因此没有写(还不是由于懒),趁着如今屋里比较的凉爽,心也比较的静,总结下目前遇到的一些爬虫知识,本系列将从简单的爬虫开始提及,之后会逐渐的提高难度,同时会对反爬手段作一个总结,以及用具体的事例来演示,不一样的反爬现象和实现手段。php
本系列侧重点是应用和实战,因此,对于软件的安装这些基本操做不作详细讲解,我这里认为你已经有了必定的python基础,因此对于python的安装必定会有必定的了解了,这里废话很少说让咱们进入正题。html
鉴于大多数人的系统是windows系统,因此这里的全部内容都是在Windows下进行的,另外推荐安装浏览器,使用语言python,版本3.6(低版本不能使用requests_html)。主要的爬虫模块requests_html。node
做为一个合格的爬虫,首先得有一个headers,如何理解headers,咱们打开浏览器,而后F12,选择network选项卡,打开百度的首页,而后打开而后选择其中的一个连接,而后点击新弹出的窗口的headers,看到有一个'Request Headers',咱们看到下面红框的内容,这些由:组成的数据结构,共同构成了一个headers,在python中能够把这些字段做为一个字典传入。python
下面我来看一个基本爬虫代码,爬取百度的导航栏文字内容。
1.导入requests_html模块。windows
from requests_html import HTMLSession
2.建立一个session对象,目的是维持一次完整的会话。浏览器
session=HTMLSession()
3.经过get方法访问网络服务器
url='https://www.baidu.com' headers={'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.62 Safari/537.36'} req=session.get(url=url,headers=headers)
get方法须要传入两个参数,一个是url,一个是headers(字典类型)。通常的咱们传入一个user_agent就能够愉快的使用了。(这里只是说通常的对于有先网站服务器还会监测headers的其余属性内容)。咱们会获取一个response对象。网络
拓展:若是查看requests_html的源码会发现默认是给了几个headers属性的。session
def default_headers(): """ :rtype: requests.structures.CaseInsensitiveDict """ return CaseInsensitiveDict({ 'User-Agent': default_user_agent(), #这个就是一个随机的useragent 'Accept-Encoding': ', '.join(('gzip', 'deflate')),#接收编码类型 'Accept': '*/*',#接收文件类型 'Connection': 'keep-alive',#保持连接 })
4.获取网页返回的状态码
通常的咱们把200状态码认为是响应成功(并不必定是你想要的结果,好比登录失败有些也是200)。
其余常见的还有,404网页访问失败,500服务器拒绝访问,302和301做为网页的重定向。数据结构
if req.status_code==200: print("ok")
5.获取正确的网页编码
由于每一个页面的编码不一样,可能致使在解析的时候出现乱码的状况,对此requests_html模块为咱们提供了一个能够高准确率获取编码的方法,目前来看对于绝大对数html页面是没有问题的,因此能够放心使用。
req.encoding=req.apparent_encoding
6.查看获取html源码
此时咱们已经获取了编码以后的对象了,若是咱们须要查看获取的内容以及编码是否正确咱们可使用text属性来获取网页的源码,它是一个字符串格式的。
7.xpath表达式的使用
requets_html模块的一个好处就是集合了众多的网页解析模块好比,bs4,pyquery,lxml等,能够说至关的强大了,requests_html经过response的html属性调用xpath方法,来直接操做dom对象,经过观察咱们获取百度导航栏的标题的xpath,代码咱们能够这样写。
node_list=req.html.xpath("//div[@id='u1']/a/text()")
简单说下上面xpath表达式的含义,//从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置。/表示从根节点选取。后面跟的ediv表示是div节点,中括号里面通常是作属性判断@id就是判断id属性而后取其值为ul的,后面紧跟的/a,表示上面div节点的下级全部含有a的节点,而后后面的text()是表示获取该节点的文本信息。
8综合整理下上面的代码以下:
from requests_html import HTMLSession from traceback import format_exc class BaiDu(): def __init__(self): self.session=HTMLSession() self.url='https://www.baidu.com' self.headers={'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.62 Safari/537.36'} self.timeout=20 def gethtml(self): try: req=self.session.get(url=self.url,headers=self.headers,timeout=self.timeout) if req.status_code==200: req.encoding=req.apparent_encoding title_info=self.parse_html(req) return ' | '.join(title_info) except: print("出错了错误内容是",format_exc) def parse_html(self,req): node_list=req.html.xpath("//div[@id='u1']/a/text()") return node_list if __name__ == '__main__': baidu=BaiDu() title=baidu.gethtml() print(title)
输出结果:
新闻 | hao123 | 地图 | 视频 | 贴吧 | 学术 | 登陆 | 设置 | 更多产品