小白和SPIDER

网 络 爬 虫?

-模拟客户端(浏览器,电脑和手机APP)发送请求并获取响应
按照规则提取数据
-自动批量采集网络资源

关于我对写爬虫的讨论

  1. url (知道url地址的规律和页码数:构造url地址的列表,或者start_url)
  2. 发送请求,获取响应 (requests)
  3. 提取数据 (返回json字符串用json,返回html用lxml和xpath
  4. 保存

HTTP?HTTPS?

-HTTP是超文本传输协议,以明文的形式传输,效率高,不安全
-HTTPS是HTTP+SSL(安全套接字层),传输前加密,之后解密,效率低,安全
-HTTP之请求头
(F12再F5点击任意一个请求,再点击headers,我用的是谷歌)
在这里插入图片描述

requests 模块的学习

  1. 发送get,post请求
response=requests.get(url)
response=requests.post(url,data={请求体的字典})

在这里插入图片描述

  • 获取网页源码
    -response.text
    常出现乱码,可在后面加上resonse.enconding=‘utf-8’
    -response.content.decode()
    将响应的二进制字节流转化为str类型
获取网页源码的正确方式
  • response.content.decode()
  • response.content.decode(‘gbk’)
  • response.text
发送带headers的请求
#可以带上更多的键值对
headers={"user-agent":" Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1","referer": "https://fanyi.baidu.com/?aldtype=16047"}

在这里插入图片描述

超时参数

有时候由于网络波动,请求不成功,需要设置超时参数,在规定时间结束请求

response=requests.get(url,headers=headers,timeout=3)
#在三秒必须返回响应否则报错

但是往往面对没有响应我们会去多次请求,这就需要用到retrying模块

retrying模块的学习

基本使用方法
from retrying import retry
#下面函数的最大报错次数是3,即是错三次才会报错
@retry(stop_max_attemp_number=3)
def fun1:
	print("no")
	raise ValueError("erroe")

在这里插入图片描述

处理Cookie相关请求

我登录的是安大教务处,有两种方法

  1. 直接携带cookie请求url(就是必须进入要登录的网站,这时候的url就是地址栏的url,cookie就在左边的第一个包里面,用get)
    1)可以写成csharpheaders={...,"Cookie": "JSESSIONID=2A8EDAD25C766D03B05FCFB381234A1C.TM2"}
    2)可以写成response=res.get(url,headers=headers,cookies=cookie_dict)
    在这里插入图片描述
    在这里插入图片描述
  2. 先发送post请求,获取cookie,再带上cookie一起请求登录后的页面
session=requests.session()
#session具有的方法和requests一样
session.post(url,data.headers)
#这使服务器设置再本地的cookie会存在session
session.get(url,headers)
#会带上之前保存在session里面的cookie,可以请求成功

感觉这个方法好麻烦,直接把cookie写到headers里面它不香吗
在这里插入图片描述

数据提取方法

就是从我们得到的源码中提取数据,有很多种方法,可以用正则,beatifulsoup,json,lxml

json:看起来像python的列表 或字典

  • 数据交换格式:数据从后端传到前端的过程叫数据交换,数据交换的时候我们往往会使用json的格式

  • 哪里会返回json数据
    -浏览器切换到手机版
    -抓包app

#可以把json字符串转化成python类型
import json
json loads(json字符串)
把python类型转化为json字符串
json.dumps({'a':'a'})
#但写文件到本地时,是不可以把字典写入的,所以我们可以用json.dumps

json.dumps(json_str,ensure_ascii=False,indent=2)
#ensure_ascii:让中文显示中文
#indent(n):能让下一行在上一行的基础上多n个空格

在这里插入图片描述

xpath和lxml

xpath:一门从html里面提取数据的语言
xpath语法
xpath helper:帮助我们从elements中定位数据

- 如何让选择标签

'/'能够选中html下head下(一级)的所有的meta标签
/html/head/meta

'//'能从任意节点开始选择
//li :当前页面上所有的li标签 
//html//head//link:head下的所有(多级)link标签

./是当前节点

@符号的用途
1.选择具体某个元素
选择class='xh'的dic下的ul下li
//dic[@class='xh']/ul/li
2.选择a的href的值
a/@href

获取文本
获取a的文本
/a/text()
获取a下的所有文本
/a//text()

-lxml

注意:由于element的元素和response的元素一般不一样,所以我们在用xpath提取元素的时候看到的标准是在response里面的

from lxml import etree
element=etree.HTML('html字符串')
element.xpath(' ')

在这里插入图片描述

上手的第二个程序-糗事百科

xpath

# -*- coding: utf-8 -*-
"""
Created on Mon Feb 10 04:12:46 2020

@author: acer
"""
import requests
from lxml import etree
import json



class QIUSHISPIDER:
    def __init__(self):
        self.headers={"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36"}
        self.url='https://www.qiushibaike.com/hot/page/{}/'
    def get_url_list(self):#根据url的规律,构造url_list
        url_list=[self.url.format(i) for i in range(1,14)]
        return url_list
    def parse_url(self,url):
        response=requests.get(url,headers=self.headers)
        return response.content.decode()
    def get_content(self,html_str):
        e_html=etree.HTML(html_str)
        e_html_div=e_html.xpath('//div[@id="content-left"]/div')
#        print(e_html_div)
        content_list=[]
        for e in e_html_div:
            item={}
            #用这个三元推导式是为了判断列表中的元素是否不为零,因为如果为零会出现错误
            #str.strip() 可以消除字符串中首尾出现的字符,默认为空格
            item['author']=e.xpath('.//h2/text()')[0].strip() if len(e.xpath('.//h2/text()'))>0 else None
            item['content']=e.xpath('.//div[@class="content"]/span//text()')
            item['content']=[i.strip() for i in item['content']]
            item['img']=e.xpath('.//img/@src')
            item['img']=[i.strip() for i in item['img']]
            content_list.append(item)
            return content_list
    def save_content(self,html_str):
        for content in self.get_content(html_str):
            with open("quishi.txt","a",encoding="utf-8") as f:
                print("保存成功")
                f.write(json.dumps(content,ensure_ascii=False))
                f.write('\n')
      
    def run(self):
        #根据url的规律,构造url_list
        for url in self.get_url_list():
            
            html_str=self.parse_url(url)
        #对每个url发送请求,获取响应 
        
            self.save_content(html_str)  
        #提取数据   
        #保存
if __name__ =='__main__':
    quishi=QIUSHISPIDER()
    quishi.run()        
        
        

上手的第二个程序-手机版豆瓣

json
import json
import paser
class Doubanspider:
    #初始化方法,初始化变量
    def __init__(self):
        self.url="https://m.douban.com/rexxar/api/v2/subject_collection/tv_american/items?os=ios&for_mobile=1&start={}&count=18&loc_id=108288&_=1581225562659"
    #提取数据,得到的是一个列表
    def get_needcontent(self,get_response):
        dict_url=json.loads(get_response)
        needcontent=dict_url['subject_collection_items']
        total=dict_url["total"]
        return needcontent,total
    #保存数据到一个文本里面,注意这是以追加的方式打开
    def save_content(self,needcontent):
        with open("Douban.txt","",encoding="utf-8") as f:
            for content in needcontent:
                f.write(json.dumps(content,ensure_ascii=False))
                f.write('\n')
        print("保存成功")
    #实现主程序
    def run(self):
        total=100
        num=0
        #应该加上18
        while num<total+18:
        #1,获取start_url
            url=self.url.format(num)
            print(url)
        #2.发送请求,获取响应
            get_response=paser.parse_url(url)
        #3.提取所需的数据
            needcontent,total=self.get_needcontent(get_response)
        #4.保存
            self.save_content(needcontent)
        #5.构造下一页数据,循环2-4
            num=num+18
#测试程序
if __name__ =='__main__':
    #实例化一个方法
    doban=Doubanspider()
    doban.run()

上手的第一个爬虫程序–下载小说

import requests as res
#再见了正则,拥抱我的SP,哈哈哈哈
from bs4 import BeautifulSoup as bs
import re
#download a website 必须加引号 注意headers是字典
url='http://www.booksky.cc/299933.html'  
headers={"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36"}
#使用get发送请求为了更真实模拟浏览器加上headers
#获取网页源码
response=res.get(url,headers=headers)
#这时候获得的请求其实只是数字,需要将网页编码方式改成utf-8
#必须要设置正确的编码和文本属性 编码也要打上引号
response.encoding='utf-8'
#这时候我们就获得了html字符串
html=response.text
#print(html)
#将网页内容解析到sp里面,sp是bs类的对象
sp=bs(html,"html.parser")
#获取标题
ti=sp.title.text[0:8]
#print(ti)
#再获取每一章的信息
cha_info_list=re.findall(r'<li class="hide"><a href="(.*?)" title="(.*?)" target="_blank">',html,re.S)

#新建一个文件,保存小说内容
with open('{}.txt'.format(ti),'w',encoding='utf-8') as f:
    #循环每一个章节,分别去下载
    for cha in cha_info_list:
#        cha_url=cha[0]
#        cha_ti =cha[1]  不优雅
         cha_url,cha_ti=cha
         cha_url="http://www.booksky.cc{}".format(cha_url)
#         print(cha_url,cha_ti)
         #接下来就可以下载章节内容了
         cha_response=res.get(cha_url,headers=headers)
         cha_response.encoding='utf-8'
         cha_response_html=cha_response.text
#         sp1=bs(cha_response_html,"html.parser")
#         cha_con=sp1.text
#         cha_temp=re.findall(r'Sitemap(.*?) })();',cha_con,re.S)
#         print(cha_temp)#这个地方本来是想要尝试一下bs的,可以是可以但是后面又多了一些东西,我也搞不掉,所以使用正则
         cha_ti=re.findall(r'<title>(.*?)</title>',cha_response_html,re.S)[0]
         cha_con=re.findall(r'<div class="content" id="chaptercontent">(.*?)</div>',cha_response_html,re.S)[0]
#         清洗数据
         cha_con=cha_con.replace(' ','')
         cha_con=cha_con.replace('<br/>','')
         cha_con=cha_con.replace('&nbsp;','')
         
         f.write(cha_ti)
         f.write(cha_con)
         f.write('\n\n\n')

不满意的地方:

这是一本连载小说,所以应该去检查是否更新?
到底该怎么把bs用的更好?
有时候下载书的章节时,要求换页怎么处理?
一开始去晋江下载书时出现的乱码该怎么解决?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值