网络爬虫基础一

爬虫的分类

按使用场景:

  1. 通用爬虫:指搜索引擎的爬虫
  2. 聚焦爬虫:指针对特定网站的爬虫
  • 聚焦爬虫又可以分为大致3种:
  1. 累积式爬虫: 从开始到结束,一直不断爬取,过程中会进行去重操作;
  2. 增量式爬虫: 对已经下载的网页采取增量式更新和只爬行新产生的或者已经发生变化网页的爬虫;
  3. 深度爬虫: 不能通过静态链接获取的、隐藏在搜索表单后的,只有用户提交一些关键词才能获得的Web面;

requests模块的使用

说明:Requests是一个用于网络请求的第三方模块,继承了urllib的所有特性,但是其API比urllib容易使用,更符合操作习惯;

GET请求:

import requests
response = requests.get("http://www.baidu.com/")
# 或者
response = requests.request("get", "http://www.baidu.com/")

参数:

  • headers:添加请求头,字典格式,默认的请求头为request库,容易被服务器反爬;
  • params:添加get参数;
  • cookies:添加cookies;
  • timeout:设置超时,默认180s,超时后报错;
import requests
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"}
params = {‘word‘:"huo"}
response = requests.get("https://www.so.com/", headers=headers,params =params,timeout=5)

POST请求:

import requests
response = requests.post("http://www.baidu.com/",data=data)
# 或者
response = requests.request("post", "http://www.baidu.com/",data=data)

参数:

  • data:post请求一般需要提交数据,字典格式;
  • 其他参数和get请求一样,但没有params参数;

查看响应的内容:

response.url  # 查看url地址
response.status_code  # 查看响应状态码
response.encoding  # 查看相应头的字符编码
response.headers  # 查看相应头部
response.text  # 自动解码,返回unicode的自动解码的内容,有时会失败产生乱码
respones.content  # 返回二进制的内容
respones.json()  # 如果响应是json数据,可以使用
respones.cookies  # 获取cookie的信息,得到的是一个对象,需要装换格式
  • 注意:如果需要接收图片数据或不知道响应的编码格式,一般使用respones.content.decode("utf-8"),可以指定解码的格式;

常见的请求头的内容

  1. Host (主机和端口号)
  2. Connection (链接类型)
  3. Upgrade-Insecure-Requests (升级为HTTPS请求)
  4. User-Agent (浏览器名称)
  5. Accept (传输文件类型)
  6. Referer (页面跳转处)
  7. Accept-Encoding(文件编解码格式)
  8. Cookie (Cookie)

设置代理

  • 设置代理使用参数proxies;
  • 免费代理:不需要用户和密码,公开的,可去网上寻找
import requests
# 使用参数proxies
proxies = {
  "http": "http://host:port",  # http的访问方式
  "https": "http://host:port", # https的访问方式
}
response = requests.get("http://www.baidu.com", proxies = proxies)
  • 私密代理:需要用户和密码,需要购买
import requests
proxy = { "http": "用户名:密码@host:port" }
response = requests.get(url, proxies = proxy)

使用cookies和session

  • session:

session表示一个会话,登录一次后会自动记录cookie,验证一次后就可以绕过验证获取数据,用来获取那些需要登陆后才能获取的网页数据;

import requests
# 创建一个session会话
s = requests.session()
headers = {"User-Agent": "xxxxx"}
# 表单数据
data = {"user":"xxx", "password":"xxxxx"}
s.post(url, data = data)  # 提交 表单,相当于登陆一个网站,后面就可以直接访问需要登录才能访问的url了
  • cookies:

cookie是保存在本地的服务器发送的信息,常常可以使用cookie跳过登陆验证的环节;

import requests
from requests.utils import dict_from_cookiejar
cook = response.cookies
cookdict = dict_from_cookiejar(respones.cookies)  # 将获取的内容转化成字典的格式

从response中提取数据

  • 使用post或get方法提交请求后,会返回response对象,其可能是一个json对象,也可能是html对象,下面讨论从html中提取数据。
  • 使用正则表达式匹配:不常用
  • csspath:常用,和css选取节点的方法一样,这里不多做介绍;
  • xpath:(XML language path),常用;
# 需要用到lxml第三方库
from lxml import etree
import requests
response = requests.get("http://www.baidu.com/")
# 将返回的数据转化成一个html对象
html = etree.HTML(response.content.decode())
# 使用xpath提取数据
result = html.xpath(‘//*‘)
print(result)

方法:

  1. 如果是将响应数据转化为html对象,使用html = etree.HTML(response));
  2. 如果是读取一个html格式的文件,使用html = etree.parse(‘xxx.html‘))

保存数据

  • 保存为txt文档:一般的小文件使用
def save_text(data):
    with open("xxx.txt","w") as f:
        f.write(data)
  • 保存为json文件:在ajax加载上使用较多
import json
def save_json(data):
    with open("xxx.json","w") as f:
        # 使用dump将python的数据转换为json格式的数据
        # 参数 ensure_ascii=False 禁用ascii编码,按utf-8编码
        data = json.dump(data, ensure_ascii=False)
        f.write(data) 

更多json模块的方法,参考我的另一篇博文:python的json模块。

  • 使用redis、mongodb,mysql等数据库保存数据。

注意:

  • 很多时候需要知道网页的编码格式,如是utf-8或gbk等,编码和解码的格式必须一样,不然会产生乱码,这时可以用chardet模块查看编码。
import requests
import chardet
def req(url):
    # 设置请求头
    header ={
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.79 Safari/537.36",
    }
    response = requests.get(url, headers=header, timeout=5)
    print(chardet.detect(response.content))  # 得到编码
    return response
if __name__ == "__main__":
    response = req("http://www.baidu.com")
    print(response.content.decode())

    # 结果:{‘language‘: ‘‘, ‘confidence‘: 0.99, ‘encoding‘: ‘utf-8‘}

说明:detect方法返回一个字典,confidence表示判断的精度,即概率;encoding表示编码格式。

爬虫实例

说明:写一个完整的爬虫至少包括以下几个部分:

  1. 构建请求相关的参数,如headers,cookies,referer,proxes(代理)等,最重要的是初始的url;
  2. 请求数据,一般使用get,post或head(类似get方法,不过只获取头部信息);
  3. 解析数据:使用正则、jsonpath或xpath提取想要的数据和新的url
  4. 保存数据:将提取的数据保存到文件或数据库。
  • 一个单线程基础爬虫:

实现功能:爬百度贴吧(爱情吧),爬取内容:标题,回复人数,作者;

  1. 随机请求头;
  2. 有代理池;
  3. 可以爬取多页内容;
  4. url去重;
import requests as res
import sys
from queue import Queue
import random
from lxml import etree
import json

class Baidu_Tieba(object):
    def __init__(self, pn):
        # 构建请求头池
        self.headers = [
            {"User-Agent": "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)"},
            {"User-Agent": "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0)"},
            {"User-Agent": "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; by TSG)"},
            {"User-Agent": "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; .NET CLR 1.0.3705)"},
        ]
        # 构建代理ip池
        self.proxies = [
            {‘http‘: ‘http://120.236.142.103:8888‘},
            {‘http‘: ‘http://203.195.232.60:8000‘},
            {‘http‘: ‘http://202.38.254.247:3128‘},
            {‘http‘: ‘http://116.199.2.209:80‘},
            {‘http‘: ‘http://111.62.251.130:8081‘},
            {‘http‘: ‘http:116.199.115.78:80‘},
            {‘http‘: ‘http://120.236.142.103:8888‘}
        ]
        # 设置爬取多少页
        self.pn = pn
        # 设置初始url
        self.base_url = ‘https://tieba.baidu.com/f?ie=utf-8&kw=爱情吧&fr=search‘
        # 用来去重的集合
        self.url_set = set()
        # url请求队列,无所谓深度和广度优先,使用先进先出队列
        self.url_list = Queue()

    # 请求数据
    def get_page(self, url):
        header = random.choice(self.headers)
        proxies = random.choice(self.proxies)
        response = res.get(url, headers=header, proxies=proxies)
        return response.content

    # 解析数据
    def analysis_data(self, data):
        html = etree.HTML(data.decode())
        # 提取页面内容
        nodes = html.xpath(‘//*[@id="thread_list"]/li/div‘)
        data_list = []
        # 获取内容
        for node in nodes:
            item = {}
            item["标题"] = node.xpath(‘./div[2]/div[1]/div[1]/a/text()‘)
            item["评论"] = node.xpath(‘./div[1]/span/text()|./div[1]/div/text()‘)
            item[‘用户‘] = node.xpath(‘./div[2]/div[1]/div[2]/span[1]/span[1]/a/text()‘)
            data_list.append(item)
            print(item)
        # 获取url
        url_nodes = html.xpath(‘//*[@id="frs_list_pager"]/a/@href‘)
        print(url_nodes)
        for url in url_nodes:
            url = ‘https:‘ + url
            self.url_list.put(url)
        return data_list

    # 保存数据
    def save_data(self, data):
        filename = ‘爱情吧.json‘
        with open(filename, "w", encoding=‘utf-8‘) as f:
            for d in data:
                da = json.dumps(d)
                f.write(da+‘,\n‘)

    def run(self):
        # 将初始url加入到url队列
        self.url_list.put(self.base_url)
        i = 0
        while i < self.pn:
            # 取出一条url
            url = self.url_list.get()
            # print(url)
            # 验证
            if url not in self.url_set:
                i += 1
                print(i)
                self.url_set.add(url)
                data = self.get_page(url)
                data_list = self.analysis_data(data)
                self.save_data(data_list)

if __name__ == "__main__":
    if len(sys.argv) < 3:
        print("参数不足,如‘python 百度贴吧爬虫.py 3‘")
    else:
        np = sys.argv[1]
        tieba = Baidu_Tieba(int(np))
        tieba.run()
  • 注意

百度贴吧的html对以Chrome为内核的浏览器发送的是被注释的源码,所以xpath得不到相关的内容,必须设置User-Agent是ie内核的。

  • 说明:

上述爬虫是最基础的单线程爬虫,其效率和抗风险的能力是很差的,如:

  1. 当代理服务器失效,或无法访问的时候,会阻塞爬虫的运行或超时错误;
  2. 当百度贴吧的服务器没有响应的时候,程序阻塞;
  3. 当爬取的页面过多时,可能会陷入死循环;

为了提高爬虫的效率和抗风险的能力,需要进一步学习爬虫知识,下一篇博文将继续介绍。

  • 作者:天宇之游
  • 出处:http://www.cnblogs.com/cwp-bg/
  • 本文版权归作者和博客园共有,欢迎转载、交流,但未经作者同意必须保留此段声明,且在文章明显位置给出原文链接。

原文地址:https://www.cnblogs.com/cwp-bg/p/8182219.html

时间: 2024-09-30 22:05:20

网络爬虫基础一的相关文章

java网络爬虫基础学习(一)

刚开始接触java爬虫,在这里是搜索网上做一些理论知识的总结 主要参考文章:gitchat 的java 网络爬虫基础入门,好像要付费,也不贵,感觉内容对新手很友好. 一.爬虫介绍 网络爬虫是一个自动提取网页的程序,它为搜索引擎从万维网下载网页,是搜索引擎的重要组成部分. 传统爬虫: 获得URL ->放入队列 ->抓取网页,分析信息 ->新的URL ->放入队列 ->抓取网页,分析信息... ->满足一定条件,停止. 聚焦爬虫: 根据一定的网页分析算法过滤与主题无关的链接

java网络爬虫基础学习(三)

尝试直接请求URL获取资源 豆瓣电影 https://movie.douban.com/explore#!type=movie&tag=%E7%83%AD%E9%97%A8&sort=time&page_limit=20&page_start=0 浏览器打开该地址: 发现是这样的 在这里我们需要用java抓取电影的信息,首先要找到资源链接,浏览器右键->检查打开谷歌调试工具 我们可以看到下图 有很多的资源请求,在这里我是一个个搜索,看那个是电影信息的Headers 发

Java版网络爬虫基础(转)

网络爬虫不仅仅可以爬取网站的网页,图片,甚至可以实现抢票功能,网上抢购,机票查询等.这几天看了点基础,记录下来. 网页的关系可以看做是一张很大的图,图的遍历可以分为深度优先和广度优先.网络爬虫采取的广度优先,概括的说来如下: 2个数组,一个记录已访问的网页(Al),一个记录未访问的网页(Un).假设网页A为爬取的起始点,分析A中的所有的超链接B,C,D,将B,C,D加入到Un,分析B中的所有的超链接E,F,将E,F加入到Un末尾,将B从Un除去并加入到AL.依次分析Un中的超链接并加入到Un中就

Java版网络爬虫基础

网络爬虫不仅仅可以爬取网站的网页,图片,甚至可以实现抢票功能,网上抢购,机票查询等.这几天看了点基础,记录下来. 网页的关系可以看做是一张很大的图,图的遍历可以分为深度优先和广度优先.网络爬虫采取的广度优先,概括的说来如下: 2个数组,一个记录已访问的网页(Al),一个记录未访问的网页(Un).假设网页A为爬取的起始点,分析A中的所有的超链接B,C,D,将B,C,D加入到Un,分析B中的所有的超链接E,F,将E,F加入到Un末尾,将B从Un除去并加入到AL.依次分析Un中的超链接并加入到Un中就

Python网络爬虫基础知识学习

对Python有一些简单了解的朋友都知识Python编程语言有个很强大的功能,那就是Python网络爬虫(http://www.maiziedu.com/course/python/645-9570/),一提到Python,就会想到相关的Python爬虫和scrapy等等,今天就来简单认识学习Python爬虫的基础知识,有了一定的相关爬虫知识,以后学习scrapy.urllib等等知识时,会相对轻松些. 爬虫: 网络爬虫是一个自动提取网页的程序,它为搜索引擎从万维网上下载网页,是搜索引擎的重要组

【python学习】网络爬虫——基础案例教程

一,获取整个页面数据 Urllib 模块提供了读取web页面数据的接口,我们可以像读取本地文件一样读取www和ftp上的数据.首先,我们定义了一个getHtml()函数: urllib.urlopen()方法用于打开一个URL地址. read()方法用于读取URL上的数据,向getHtml()函数传递一个网址,并把整个页面下载下来.执行程序就会把整个网页打印输出. #coding=utf-8 import urllib def getHtml(url):     page = urllib.ur

网络爬虫基础练习

练习: 新建一个用于练习的html文件,在浏览器中打开. <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Simple DOM Demo</title> </head> <body> <h1>This is the document body</h1> &l

java网络爬虫基础学习(四)

jsoup的使用 jsoup介绍 jsoup是一款Java的HTML解析器,可直接解析某个URL地址.HTML文本内容.它提供了一套非常省力的API,可通过DOM,css以及类似于Jquery的操作方法来取出和操作数据. 主要功能 从一个URL,文件或字符串中解析出HTML. 使用DOM或css选择器来查找.取出数据. 可操作HTML元素.属性.文本. 直接请求URL 一开始直接使用jsonp的connect方法调用上节说的请求电影json数据会报错 错误如下: 这里不太清楚发生错误的原因,毕竟

java网络爬虫基础学习(二)

正则表达式 正则表达式写法 含义 \d 代表0-9的任意数字 \D 代表任何非数字字符 \s 代表空格类字符 \S 代表非空格类字符 \p{Lower} 代表小写字母[a-z] \p{Upper} 代表大写字母[A-Z] \p{Alpha} 代表字母 \p{Blank} 代表空格或制表符 HTTP状态码 分类 描述 1** 信息,服务器收到请求,需要请求者继续执行操作. 2** 成功,操作被成功接收并处理. 3** 重定向,需要进一步的操作已完成请求. 4** 客户端错误,请求包含语法错误或无法