python爬虫

1.爬虫的基本流程

  • 用urllib或是requests库把网页的HTML代码拉到本地
  • 用HTMLParser,Xpath,BeautifulSoup等库解析HTML代码,找到想要的东西

2.HTMLParser

廖雪峰的网站看资料

3.urllib

廖雪峰的网站看资料

4.requests

菜鸟教程看资料

#GET方法
import requests
HTML=requests.get("网址",headers={"User-Agent":"浏览器头"})
data=HTML.content.decode()#utf-8的HTML代码

开VPN后爬虫可能会遇到问题,需要加入一下的代码

#先加入如下代码

import urllib3
urllib3.disable_warnings()#加载request.get()前面

#之后任意选下面一种方法
# 压根儿不用这么麻烦,直接两种方式: 
# 方法一:
session = requests.Session()
session.trust_env = False
response = session.get('网址') 
 
# 方法二:(多人亲测可以直接结局这个问题)
proxies = { "http": None, "https": None}
requests.get("网址", proxies=proxies)
 

request可能不太稳定,但用起来比urllib舒服,大概吧。

5.Xpath

看收藏夹下面的博客

from lxml import etree
Xpath=etree.HTML(data)#把html代码晒进去
res=Xpath.xpath("xpath语法")#按xpath语法找到你想要的内容,以列表的形式返回

6.正则表达式

使用正则表达式爬虫时注意加上re.S的参数,不然可能什么都匹配不到

import re
data=re.findall(parttern,string,re.S)

不建议用正则表达式匹配原因如下

  • 你在网页看到的HTML和爬虫拉到本地的HTML格式稍有不同
  • 正则表达式语法很严格,如果写错了会什么都匹配不到
  • 匹配起来太慢了,无法灵活运用HTML的结构
  • 出错了也不知道要怎么修

7.把数据写入文件中

# 直接按正常的文件操作即可,根据报错调参

# 1.写HTML格式(默认utf-8)
f=open("Test.text","w",encoding="utf-8")
f.write(HTML)
f.close()

# 2.写普通的数据
f=open("Test.text","w")
f.write(data)#data要是字符串才行,如果用了str强转,需要在open时加encoding参数
#中文数据要先encoding='utf-8',或者直接在vscode里面用utf-8看

如果要下载图片和视频,那么将二进制数据写入文件中即可,注意修改后缀名

8.BeautifulSoup

与Xpath的最大区别是能够把HTML结构切割出来,Xpath只能切割文本或是属性的值

from bs4 import BeautifulSoup
soup=BeautifulSoup(网页内容,'解析方法lxml或是htmlparser')#生成一个解析器
data=soup.find_all("标签名",class_="类名",id="id名字")# 返回所有符合要求的html结构,列表形式
for obj in data:
	print(obj.string)#打印文本内容
	print(obj["class"])#打印class的属性值,是一个列表
	print(obj.name)#标签的名字

BS很简单和Xpath差不多,就是多了个类。find_all后返回的是一个列表,列表中的每个元素都可以看作一个soup同样可以调用find_all

9.获取cookie

cookie是一个登入凭证,有了cookie登入网页就不需要输入密码了

  • cookie的获取方法:
  1. 点击F12进入控制台
  2. 点击网络
  3. ctrl+r
  4. 选择一个类型为document的请求(默认是首个)
  5. 在header下面代开request header,找到cookie并复制粘贴

10.客户端渲染和服务器渲染

爬虫爬到的是网页的HTML源代码,不是元素下面的代码,元素下面的代码是经过浏览器渲染过的。检查爬虫爬到的网页是否正确查看网页的源代码即可,而不是去看元素,元素是用来解析的

服务器渲染

客户端发送请求时,服务器直接返回一个完整的HTML文件,此时返回的HTML文件和元素下面的html代码完全一样。即获得的是一个已经经过整合的HTML结构和HTML数据

客户端渲染

客户端发送请求时,服务器返回一个没有任何具体内容的HTML文件,客户端接收到这个HTML文件后再自动向服务器再发起一次请求,服务器向客户端传送数据。客户端经过两次请求后获得html结构和html数据,自动在本地整合,最后得到元素下面的源代码。在客户端渲染的情况下,排重爬到的网页源代码和网页元素下面得到代码不一样。
典型例子

  • bilibili
  • 微博热搜
    爬虫爬出奇奇怪怪的东西,第一反应是这个网站是服务器渲染,这时候只需要在network下面找到对应数据的url再爬一次就好了

11.session

requests.session()的方法获得一个session的对象

session的意思是会话的意思。使用session能够自动获取cookie。session和requests的区别是多了一个cookie的属性,能够直接自动存储cookie。

import requests
sess=requests.session()
sess.post(url,data=data)#登入网页
sess.get(url)#从网页中爬取信息

用post还是get在浏览器中看请求的类型,而不是自己决定

12.Post的使用方法

看B站百度翻译爬虫的视频,或是自己的代码

post提交数据的格式是json,json的参数在network->playload下面看,中文是负载

13.AJAX技术

简单的来说就是客户端渲染,AJAX的最主要特点是页面源代码和元素下方的代码不一样,爬虫抓到的是js脚本

使用selenium避开js脚本

selenium是一个用来模拟浏览器行为的驱动工具,使用selenium爬虫时会自动打开你的浏览器进行运作
参考连接

	browser.page_source#获取当前页面源代码
	browser.current_url#获取当前页面的url
	m
	element=browser.find_element(By.xxx,"名字或属性值")#查找元素

使用百度搜索bilibili

from selenium import webdriver
from selenium.webdriver.common.by import By
import  time
browser = webdriver.Edge()
browser.get('https://www.baidu.com')
time.sleep(2)
searchbox=browser.find_element(By.ID,"kw")
searchbox.send_keys("bilibili")
button=browser.find_element(By.ID,"su")
time.sleep(2)
button.click()
time.sleep(3)
print(browser.page_source)
print(browser.current_url)

使用无头浏览器时需要增加如下代码

from selenium.webdriver.edge.options import Options
opt=Options()
opt.add_argument("--headless")
opt.add_argument("--disable-gpu")
browser=webdriver.Edge(options=opt)

一般的步骤

  1. 声明browser对象
  2. 用browser.find_element找到元素
  3. 操作元素

14.多进程和多线程爬虫

和普通的多线程和多进程完全一样,就是把run里面的内容变成爬虫程序。多进程才能提高效率,多线程不一定比单线程块

15.代理

修改proxy里面的http和https两个键的值,详情看书,这部分比较麻烦

16.参数与表单

  • ?后面的都是参数,再负载中的字符串参数中显示,再requests中对应params。一般get的是params
  • 表单,一般来说post对应的是data,再负载中查看

以爬取百度的搜索结果为例:

import requests
from bs4 import BeautifulSoup

url = "https://www.baidu.com/s"
param = {
    "wd": "我爱python",#关键字
    "pn":0#页数,0表示第一页,10表示第二页,以此类推
}
header = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.134 Safari/537.36 Edg/103.0.1264.71",
    "Cookie": "自己的cookie"
}
req = requests.get(url, params=param, headers=header)
soup = BeautifulSoup(req.text, "lxml")
reslist = soup.find_all("div", class_="result c-container xpath-log new-pmd")#搜索结果必然显示在这个盒子里面(除了视频,广告,百科,贴吧)
for obj in reslist:
    # print(obj.find_all('div',class_="c-container")[0].find_all("a"))
    print(obj.find_all('div',class_="c-container")[0].find_all("a")[0].text)#搜索结果的标题

协程

单线程中的异步操作,效率比多线程要高,用于下载图片或是视频,文本,频繁进行IO操作时用协程

import requests
import asyncio
import aiohttp
from bs4 import BeautifulSoup
import re

regular = re.compile("com/(.*?).html")


def getPageUrl():
    url = "https://xiyouji.5000yan.com/"
    head = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.134 Safari/537.36 Edg/103.0.1264.71"
    }
    req = requests.get(url, headers=head)
    soup = BeautifulSoup(req.text, 'lxml')
    liList = soup.find_all('li', class_="menu-item")
    pageList = []
    for obj in liList:
        page = obj.find_all('a')[0]['href']
        pageList.append(page)
    pageList.pop(0)
    pageList.pop(0)
    pageList.pop(0)
    pageList.pop(0)
    print(pageList)
    return pageList


async def download(url):
    head = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.134 Safari/537.36 Edg/103.0.1264.71"
    }
    async  with aiohttp.ClientSession() as req:
        async with req.get(url, headers=head) as res:
            content = await res.content.read()
            soup = BeautifulSoup(content, 'lxml')
            head = soup.find_all('h2', class_="grap--h2")[0].text
            text = soup.find_all('div', class_='grap')[0].text
            name = re.findall(regular, url)[0]
            with open(str(name) + ".txt", "w", encoding='utf-8') as f:
                f.write(head)
                f.flush()
                f.write("\n")
                f.flush()
                f.write(text)
    print("write" + str(head) + "OK")
    
async def main(pageList):
    task = []
    for url in pageList:
        fun = download(url)
        task.append(asyncio.create_task(fun))
    await asyncio.wait(task)


if __name__ == '__main__':
    url = getPageUrl()
    #下面这段时解决Loop错误的必须
    result = main(url)
    loop = asyncio.get_event_loop()
    loop.run_until_complete(result)

	# python3.10在windows上面用如下代码替换loop的那两行
	asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
	asyncio.run(main())

需要注意的点

  • 多进程爬虫时程序有问题时不会报错,这点很坑爹
  • 文件名和网址一定要写对,不要传送一个列表进去爬
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值