爬虫.....

HTTP请求

GET

最常见的一种请求方式,当客户端要从服务器中读取文档

POST

用于提交数据, 当采用 POST 方式向指定位置提交数据时,数据被包含在请求体中,服务器接收到这些数据后可能会建立新的资源、也可能会更新已有的资源。

HTTP 的 八大请求方式_http请求方式_roseLin...的博客-CSDN博客

HTTP请求的几种类型_http类型_菜瓜_牛顿的博客-CSDN博客

 请求格式

请求行:

 

 请求头:

Host+路径组成一个完整的网址

User-Agent用来告知服务器,客户端的信息

 Accept是告诉服务器想接收什么数据

 请求体:

告诉其他信息,一般在POST里面,GET里一般是空的

篡改请求头

由代码发出的请求的 User-Agent被标注为

有些网站只服务于真人,因此可以加上headers参数,伪装真实用户

head = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36"
}
result = re.get('https://www.bilibili.com/', headers=head)

*如何找到本机真实User-Agent?

浏览器内F12 - NetWork - 选择一项拉到底 

 响应格式

状态行

版本 状态码 状态消息 

HTTP状态码汇总(常见)_IT萌萌熊的博客-CSDN博客

响应头

响应体

if 响应类型 is HTML:

爬取豆瓣Top250

先成功访问再说

import requests as re

head = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36"
}
result = re.get('https://movie.douban.com/top250', headers=head)

if result.ok:
    print(result.text)  # success

 学亿点HTML基础

🐒🐒🐒🐒🐒🐒🐒🐒🐒🐒🐒🐒🐒🐒🐒🐒🐒🐒🐒🐒🐒🐒🐒🐒🐒🐒🐒🐒🐒🐒🐒

网页解析库 Beautiful Soup

from bs4 import BeautifulSoup

BeautifulSoup将网页转化成树状结构

 先练习爬一下片名

 思路:只要中文片名,需要找到每个div class="hd"下的第一个<span class=“title”>

from bs4 import BeautifulSoup as bs
import requests as re

head = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36"
}
content = re.get('https://movie.douban.com/top250', headers=head).text

soup = bs(content, "html.parser")

hds = soup.findAll('div', attrs={'class': 'hd'})
for h in hds:
    names = h.findAll('span', attrs={'class': 'title'})
    print(names[0])
'''
<span class="title">肖申克的救赎</span>
<span class="title">霸王别姬</span>
<span class="title">阿甘正传</span>
<span class="title">泰坦尼克号</span>
。。。。。
'''

遍历所有页,取出250个

其实加个for循环就行了

from bs4 import BeautifulSoup as bs
import requests as re

head = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36"
    }
index = 0  # 记录页数,一次加25
cnt = 1  # 记录No.12345
while index != 250:
    content = re.get('https://movie.douban.com/top250?start='+str(index), headers=head).text
    soup = bs(content, "html.parser")
    hds = soup.findAll('div', attrs={'class': 'hd'})
    for h in hds:
        names = h.findAll('span', attrs={'class': 'title'})
        print('No.'+str(cnt), end=' ')
        print(names[0].string)  # 每一个hd里面的第一个span
        cnt += 1
    index += 25

'''
No.1 肖申克的救赎
No.2 霸王别姬
No.3 阿甘正传
No.4 泰坦尼克号
No.5 这个杀手不太冷
No.6 千与千寻
。。。。。
'''

指定搜索内容

可直接通过修改url

干百度翻译

获取请求形式

三个sug包分别是d, do, dog,可以看出请求URL

 响应头是个json

import requests as re
head = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36"
}
data = {'kw': 'rose'}
result = re.post('https://fanyi.baidu.com/langdetect', data=data, headers=head)
# json返回的是对象,确认响应是对象才能用
print(result.json())

爬KFC餐厅名称

URL:肯德基餐厅信息查询

请求完局部刷新,阿贾克斯请求,就抓包XHR

import requests as re

head = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36"
}
para = {'cname': '',
        'pid': '',
        'keyword': '上海',
        'pageIndex': '1',
        'pageSize': '10'}
result = re.post('https://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=keyword', params=para, headers=head)
# json返回的是对象,确认响应是对象才能用
print(result.text)

XPath

python爬虫之xpath解析(附实战)_python爬取数据返回空列表_猛男技术控的博客-CSDN博客

xpath解析原理:
- 1 .实例化一个etree的对象,且需要将被解析的页面源码数据加载到该对象中。
- 2.调用etree对象中的xpath方法结合着xpath表达式实现标签的定位和内容的捕获。

浏览器内可以直接获取xpath路径

爬58二手房

from lxml import etree
import requests as re

head = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36"
}
url = 'https://sh.58.com/ershoufang/'
result = re.get(url=url, headers=head).text
# print(result)
tree = etree.HTML(result)
div_list = tree.xpath('/html/body/div[1]/div/div/section/section[3]/section[1]/section[2]/div')
# print(div_list)
for house in div_list:
    # ['     假一罚万 万科有山 豪装下叠 拎包入住 南北双花园']加个[0]只取内容文字
    # ./ 从当前标签路径开始往下解析
    name = house.xpath('./a/div[2]/div[1]/div[1]/h3//text()')[0]
    print(name)
    

爬壁纸天堂

URL:Top Wallpapers - wallhaven.cc

先成功请求网址

from time import sleep
from lxml import etree
import requests as re

head = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36"
}
url = 'https://wallhaven.cc/toplist'
# 得到网站html内容
result = re.get(url=url, headers=head).text
# print(result) 

解析到图片列表

注意得到列表时,不能只得到列表总体对象,要访问到具体列表内容项目

# xpath解析网址图片列表
tree = etree.HTML(result)
# li即为一个个图片项,ul为整个图片列表,需要解析至li
img_list = tree.xpath('/html/body/main/div[1]/section[1]/ul/li')
print('已获取到源列表。。。')
# print(img_list)

开始循环访问列表

cnt = 1
for li in img_list[:3]:
    print('正在获取li[' + str(cnt) + ']...')
    big_img_url = li.xpath('./figure/a/@href')[0]  # 外面是缩略图,得到大图的网址url
    print('大图网址:' + big_img_url, end=' ')  # https://wallhaven.cc/w/rrowwm
    # 请求大图实际网址,并解析到图片源文件
    big_img_url_result = re.get(url=big_img_url, headers=head).text
    tree1 = etree.HTML(big_img_url_result)
    img_xp = tree1.xpath('/html/body/main/section/div[1]/img/@src')[0]
    print('大图资源:' + img_xp)  # https://w.wallhaven.cc/full/gp/wallhaven-gp9god.jpg
    
    # 请求图片源文件二进制数据,切分得到图片名字
    big_img = re.get(url=img_xp, headers=head).content
    name = str(img_xp).rsplit('/', 1)[-1].rsplit('-')[-1]  # /wallhaven-rrowwm.png -> rrowwm.png
    with open(fr'./{name}', 'wb') as f:
        f.write(big_img)
        print('save ' + name + '!')
        sleep(0.5) # 访问慢一点
    cnt += 1 # 计数器++
成品打包

https://download.csdn.net/download/qq_58551342/87976931

解决验证码

本质就是根据图片ORC识别

超级鹰验证码识别-专业的验证码云端识别服务,让验证码识别更快速、更准确、更强大

Cookie

why

        当登录请求发出后,在去爬取个人主页等信息,第二次的请求是不会记录之前登录的信息的,请求到的还是没有身份信息的网页,so,需要cookie

自动获取cookie—session

cookie有生命周期,所以不能写死

session用于请求的发送,如果过程中产生了cookie,可以存在session对象中

获取登录请求页时使用session对象即可

session = re.session()
result1 = session.post(url=login_url, headers=head)
result2 = session.get(url=user_url, headers=head)

代理(破解封ip)

反爬:封ip

反反爬:代理

代理、正向代理与反向代理_lgily-1225的博客-CSDN博客

result = re.get(url=url, headers=head, proxies={'https': 'ip:port'})

exchange(DN, CS)你甜美有bug知道吗?

线程池

多县城、多进程

进程和线程关系及区别_线程和进程的关系和区别_yaosiming2011的博客-CSDN博客

  • 可以单独为阻塞操作开启线程或进程
  • 无法无限制开999999999个

线程池、进程池

  • 可以降低系统对进程或者线程创建和销毁的一个频率,从而很好的降低系统的开销。
  • 池中线程进程有上限

Pool模板代码

import time
from multiprocessing.dummy import Pool
from time import sleep


def op(url):
    print('start '+ url)
    sleep(2)
    print('end')

url_list = ['111',
            '222',
            '333',
            '444']

start = time.time()
# 实例化一个线程池
pool = Pool(3)
pool.map(op, url_list)
end = time.time()

print(str(end-start)+'s')

pool.close()  # 关闭线程池
pool.join()  # 等子线程结束再结束主线程

'''
start 111
start 222
start 333
end
end
start 444
end
end
4.028931379318237s
'''

单线程+异步协程

什么牛马协程,不用了!

 协程(概念节)

什么是协程_测试狗一枚的博客-CSDN博客

早期greenlet协程

 asyncio

python3.4+

 - async and await

python3.5+

意义

遇到IO等待时间,再去干点别的事(下载就是网络IO的一种形式)

异步编程

事件循环

# 生成一个事件循环
loop = asyncio.get_event_loop()
# 任务放到循环里
loop.run_until_complete(task)

协程函数

定义一个协程函数,执行协程函数得到一个携程对象

async def func():
    pass

result = fun()

执行创建协程对象,协程函数内的语句不会执行

  想要运行,要将协程对象交给事件循环

import asyncio

async def func():
    print('jntm')
result = func()

# # 生成一个事件循环
# loop = asyncio.get_event_loop()
# # 任务放到循环里
# loop.run_until_complete(result)

asyncio.run(result)  # python 3.7新功能,一行搞定

await

await+可等待的对象(携程对象,Task对象)> IO等待

async def other():
    print('other()')  # 2
    await asyncio.sleep(2)  # 3
    print('other end')  # 4

async def fun():
    print('fun')  # 1
    resp = await other()
    print('end: ', resp)  # 5

loop = asyncio.get_event_loop()
loop.run_until_complete(fun())

使劲理解await和loop相互作用,task好几个时,函数里有await,切到其它函数

import asyncio
import time

import requests


async def test2(i):
    print('test', i)
    await asyncio.sleep(2)
    r = requests.get(i)
    print(i, r)

url = ["https://segmentfault.com/p/1210000013564725",
       "https://www.jianshu.com/p/83badc8028bd",
       "https://www.baidu.com/"]

loop = asyncio.get_event_loop()
task = [asyncio.ensure_future(test2(i)) for i in url]
start = time.time()
loop.run_until_complete(asyncio.wait(task))
endtime = time.time() - start
print(endtime)
loop.close()
'''
test https://segmentfault.com/p/1210000013564725
test https://www.jianshu.com/p/83badc8028bd
test https://www.baidu.com/
https://segmentfault.com/p/1210000013564725 <Response [200]>
https://www.jianshu.com/p/83badc8028bd <Response [403]>
https://www.baidu.com/ <Response [200]>
2.6141810417175293
'''

Future

这个不会用

selenium

  • 便捷获取动态加载数据
  • 模拟登录

下载对应浏览器驱动

selenium之 chromedriver与chrome版本映射表(更新至v2.46)_selenium版本对应chrome_huilan_same的博客-CSDN博客

实例化一个浏览器对象

from selenium import webdriver
bro = webdriver.Chrome(executable_path='D:\Google\chromedriver_win32\chromedriver.exe')

获取页面

bro.get('url')
page = bro.page_source

一些操作

from time import sleep
from selenium import webdriver

bro = webdriver.Chrome(executable_path='D:\Google\chromedriver_win32\chromedriver.exe')
bro.get('https://www.taobao.com/')

input = bro.find_element_by_xpath('//*[@id="q"]')
input.send_keys('蔡徐坤')
sleep(2)

# 滚动操作
bro.execute_script('window.scrollTo(0, document.body.scrollHeight/2)')
sleep(2)
# click
yes_button = bro.find_element_by_xpath('//*[@id="J_TSearchForm"]/div[1]/button')
yes_button.click()
sleep(2)
# get again
bro.get('https://www.baidu.com')
sleep(2)
# back
bro.back()
sleep(2)
# 前进
bro.forward()

bro.close()

iframe处理

示例网站:菜鸟教程在线编辑器

直接定位iframe中的内容,会显示如下错误(没有这样一个标签)

selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"xpath","selector":"//*[@id="draggable"]"}
  (Session info: chrome=114.0.5735.134)

要先切换脚本的作用域,再在iframe新域中定位标签

bro.switch_to.frame('iframeResult')  # 标签id
div = bro.find_element_by_xpath('/html/body/div[2]')

动作链

action = ActionChains(bro)
# 点击且长安
action.click_and_hold(div)

for i in range(5):
    # x,y方向拖动像素,perform立即执行
    action.move_by_offset(20,0).perform()
    sleep(1)

action.release()

QQ空间登录

from time import sleep
from allpath import dirver_path
from selenium import webdriver
from lxml import etree

bro = webdriver.Chrome(executable_path=dirver_path)
bro.get('https://qzone.qq.com/')
# 切换到iframe
bro.switch_to.frame('login_frame')
# 点击密码登录
ex_div = bro.find_element_by_xpath('//*[@id="switcher_plogin"]')
ex_div.click()
# 获取账号密码域并输入
zhanghao = bro.find_element_by_xpath('//*[@id="u"]')
zhanghao.send_keys('xxxxxxxxxx')
sleep(0.5)
mima = bro.find_element_by_xpath('//*[@id="p"]')
mima.send_keys('xxxxxxxxxxxx')
sleep(0.5)
# 点击登录
denglu = bro.find_element_by_xpath('/html/body/div[1]/div[5]/div/div[1]/div[3]/form/div[4]/a/input')
denglu.click()

成功登录!

无头浏览器(就是看不见浏览器)

from selenium.webdriver.chrome.options import Options

op = Options()
op.add_argument(argument='--headless')
op.add_argument('--disable-gpu')

bro = webdriver.Chrome(executable_path=dirver_path, chrome_options=op)

假装自己不是selenium

# 伪装自己不是selenium
from selenium.webdriver import ChromeOptions
op2 = ChromeOptions()
op2.add_experimental_option('excludeSwitches', ['enable-automation'])

Scrapy框架

pip install scrapy -i https://pypi.tuna.tsinghua.edu.cn/simple 

准备工作

终端内操作

建项目

scrapy startproject firstScrapy(自己取个项目名)

 

 创建爬虫源文件

>> scrapy genspider 文件名 www.baidu.com(随便跟个url,之后能改)

文件创建在了spiders文件夹下 

修改文件

import scrapy


class MyfileSpider(scrapy.Spider):
    name = 'myfile'
    # 限定下面哪个基本域名可以请求,不用得了
    # allowed_domains = ['www.baidu.com']
    start_urls = ['https://www.baidu.com/']

    # 解析数据
    def parse(self, response):
        print(response)

修改一个小配置

setting.py中

 执行文件

>scrapy crawl myfile [--nolog(不要日志信息)]

*修改日志等级

setting中加入 LOG_LEVEL = 'ERROR'

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值