了解python常用模块和Scrapy框架

本文记录了一些python常用模块和Scrapy框架的简单利用,最后还写了一个爬取糗事百科图片的小例子。学习爬虫的目的主要是想锻炼一下自己的编程能力,因为真的很菜,后面还会不断加强练习。

python常用模块

random

此模块提供了随机数获取相关方法:

  • random.random():获取[0.0,1.0)范围的浮点数
  • random.randint(a,b):获取[a,b]范围内的一个整数
  • random.uniform(a,b):获取[a,b]范围内的一个浮点数
  • random.shuffle(x):把参数指定的数据中的元素打乱混洗,参数必须是一个可变的数据类型
  • ramdom.sample(x,k):从x中随机抽取k个数据,组成一个列表返回。
    1586935637208

    time

    #获取时间戳#时间戳:从时间元年(1970.1.1 00:00:00)到现在经过的秒数

print(time.time())

#获取格式化时间对象

print(time.gmtime())
print(time.localtime())
print(time.gmtime(1)) #时间元年过一秒后,对应的时间对象

格式化时间对象和字符串之间的转换

s = time.strftime(“year:%Y %m %d %H:%M:%S”)
print(s)

吧时间字符串转换成时间对象

time_obj = time.strptime(“2020 10 10”,”%Y %m %d”)
print(time_obj)

1
2
3
4
5
6
7
import timeprint(time.time())
print(time.gmtime())
print(time.localtime())
print(time.gmtime(1))
s= time.strftime("year:%Y %m %d %H:%M:%S")print(s)
time_obj = time.strptime("2020 10 10","%Y %m %d")
print(time_obj)

1586935683083
#暂停当前程序,睡眠xxx秒

time.sleep(3)

1
2
3
4
import time
for x in range(5):
print(time.strftime('%Y %m %d %H:%M:%S'))
time.sleep(3)

datatime

1
2
3
4
5
6
7
8
9
10
11
import datetime
#date 类
d = datetime.date(2020,10,10)
print(d)
#time类
b = datetime.time(10,42,32)
print(b)
#time 类的属性
print(b.hour)
print(b.minute)
print(b.second)

运行结果:

1
2
3
4
5
2020-10-10
10:42:32
10
42
32
1
2
3
import datetime
c = datetime.datetime(2020,11,11,11,11,11)
print(c)

1586938317494

时间运算,只能和date,datetime,timedelta进行运算

1
2
3
4
import datetime
c = datetime.datetime(2020,11,11,11,11,11)
b = datetime.timedelta(seconds=6)
print(b+c)

1586940858265

练习:计算某一年的二月份有多少天
方法:首先创建出指定的年份的3月1日,然后往前走一天

1
2
3
4
5
import datetime
year = int(input("输入年份:"))
d = datetime.date(year,3,1)
td = datetime.timedelta(days=1)
print(d-td)

1586941302815

OS

OS: 和操作系统相关的操作

1
2
3
4
5
6
7
import os
#删除文件
os.remove("a.txt")
#从命名
os.rename('a.txt','b.txt')
#删除目录
os.removedirs('aa')
os.mkdir 创建目录
os.rmdir 删除目录
os.rename 重命名
os.remove 删除文件
os.getcwd 获取当前工作路径
os.walk 遍历目录
os.path.join 连接目录与文件名
os.path.split 分割文件名与目录
os.path.abspath 获取绝对路径
os.path.dirname 获取路径
os.path.basename 获取文件名或文件夹名
os.path.splitext 分离文件名与扩展名
os.path.isfile 判断给出的路径是否是一个文件
os.path.isdir 判断给出的路径是否是一个目录

sys

和python解释器相关的模块

1
2
3
import sys
print("The list of command line arguments:\n", sys.argv)
print("第一个参数名:",sys.argv[1])

C:\Users\华硕\PycharmProjects\python\python安全应用编程>python sys.py a1 a2 a3
The list of command line arguments:
[‘sys.py’, ‘a1’, ‘a2’, ‘a3’]
第一个参数名: a1

1
2
3
4
5
6
7
8
9
模块方法    解释说明
sys.argv 传递到Python脚本的命令行参数列表,第一个元素是程序本身路径
sys.executable 返回Python解释器在当前系统中的绝对路径
sys.exit([arg]) 程序中间的退出,arg=0为正常退出
sys.path 返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值
sys.platform 返回操作系统平台名称,Linux是linux2,Windows是win32
sys.stdout.write(str) 输出的时候把换行符\n去掉
val = sys.stdin.readline()[:-1] 拿到的值去掉\n换行符
sys.version 获取Python解释程序的版本信息

json

javascript对象标记语言,与序列化和反序列化相关
序列化

1
2
3
4
5
6
7
import json
a = json.dumps((1,2,3,4,5,5)) #把指定的字符串转换为json格式字符串
print(a)
print(type(a))
res = json.dumps(10.5)
print(res)
print(type(res))

1587043014158

反序列化

1
2
3
4
5
import json
res = json.dumps([2,5,6])
lst = json.loads(res)
print(type(lst))
print(lst)

1587043470016

1
2
3
4
5
6
#从文件中反序列化
import json
with open('b.txt',encoding='utf-8') as f:
res = json.load(f)
print(res)
print(type(res))

pickle

将python中所有的数据类型直接转换成字节串—序列化
将字节串转换成python中数据类型—反序列化

1
2
3
4
5
6
7
import pickle
bys = pickle.dumps((1,2,3,4,5))
print(type(bys))
print(bys)
res = pickle.loads(bys)
print(type(res))
print(res)

1587093368730

1
2
3
4
#吧pickle序列化后的内容写入文件中
import pickle
with open('c.txt',mode='wb') as f:
pickle.dump([1,2,3,4,5,60],f)
1
2
3
4
5
#从文件中反序列化
import pickle
with open('c.txt',mode='rb') as f:
res = pickle.load(f)
print(res)

pickle常用场景:和json一样,一次写入,一次读取
json不是所有的字符串都能序列化,并且不能多次对同一个文件序列化

hashlib

给一个数据加密的三大步骤

1.获取一个加密对象
2.使用加密对象的update进行加密,update方法可以调用多次
3.通过hexdigest获取加密结果,或者使用digest(),后者获取的是字节串

1
2
3
4
5
6
7
8
9
10
import hashlib
#获取一个加密对象
m = hashlib.md5()
#使用加密对象的update进行加密
m.update('asdds'.encode('utf-8'))
#通过hexdigest获取加密结果
res = m.hexdigest()
res2 = m.digest()
print(res)
print(res2)

1587045300562

例子:注册登录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import hashlib
def get_md5(username,password):
m = hashlib.md5()
m.update(username.encode('utf-8'))
m.update(password.encode('utf-8'))
return m.hexdigest()
def register(username,password):
#加密
res = get_md5(username,password)
#写入文件
with open('login',mode='at',encoding='utf-8') as f:
f.write(res)
f.write(‘\n’)
def login(username,password):
#获取当前登录信息的加密结果
res = get_md5(username,password)
#读取文件,和其中的数据进行比较
with open('login',mode='rt',encoding='utf-8') as f:
for line in f:
if res == line.strip():
return True
else:
return False
while True:
op = int(input('1.注册 2.登录 3.退出'))
if op == 1:
username = input('请输入用户名')
password = input('请输入密码')
register(username,password)
if op == 2:
username = input('请输入用户名')
password = input('请输入密码')
res = login(username,password)
if res:
print('登陆成功')
else:
print('登录失败')
if op == 3:
break

1587047252371

bs4.BeautifulSoup

导入模块

from bs4 import BeautifulSoup

#创建一个beautifulsoup对象

soup = BeautifulSoup(html)

创建 beautifulsoup 对象

1
2
3
4
5
6
import requests
from bs4 import BeautifulSoup
res = requests.get("http://cyzcc.vip")
html = res.text
soup = BeautifulSoup(html,'lxml')
print(soup)

我们还可以用本地 HTML 文件来创建对象,例如

soup = BeautifulSoup(open(‘index.html’),’lxml’)

1
2
3
4
import requests
from bs4 import BeautifulSoup
soup = BeautifulSoup(open('index.html'),'lxml')
print(soup.prettify())

1587087583702

常用方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
print(soup.a)
# 拿到soup中的第一个a标签



print(soup.a.name)
# 获取a标签的名称


print(soup.a.string)
# 获取a标签的文本内容


print(soup.a.text)
# 获取a标签的文本内容


print(soup.a["href"])
# 获取a标签的href属性的值

print(soup.a.get("href"))
# 查找第一个a标签的href的属性

print(soup.a.attrs)
# 获取a标签的所有的属性,返回一个字典



print(soup.find("a"))
# 查找第一个a标签


print(soup.find_all("a"))
# 查找所有的a标签


print(soup.find_all(id="a1"))
# 查找所有的的id为a1的标签


print(soup.find_all(class_="sistex"))
# 这里需要注意,如果需要通过class去查找,则需要一个下划线


print(soup.find_all(["a","p","br"]))
# 查找所有的啊标签,p标签和br标签


soup.find("a").attrs["class"] ="2b"
# 修改某个标签的属性值

delsoup.find(id="a1").attrs["class"]
# 删除某个标签的class属性

1587088448436

1
2
3
4
# 找到标签内的文本为story的文本内容
print(soup.find_all(text='story'))
# 找到标签内的文本含有story的文本内容
print(soup.find_all(text=re.compile(r'.*?story.*?')))

XPath表达式

xpath表达式效率比正则表达式高,但是功能比正则表达式少

1
2
3
4
5
/   逐层提取
text() 提取标签下面的文本
//标签名div 提取所有名为div的标签
//标签名[@属性='属性值'] 提取属性为xx的标签
@属性名 代表取某个属性值

实例:
提取标题

/html/head/title/text()

提取所有div标签

//div

提取div标签中<div class='tools'>标签

div[@class=’tools’]

在Urllib模块下使用XPath表达式

1
2
3
4
5
6
7
8
9
10
11
#在Urllib模块下使用XPath表达式
import urllib.request
from lxml import etree
data=urllib.request.urlopen("http://www.baidu.com").read().decode("utf-8","ignore")
treedata=etree.HTML(data)
title=treedata.xpath("//title/text()")
if(str(type(title))=="<class 'list'>"):
pass
else:
title=[i for i in title]
print(title[0])

Scrapy框架

scrapy常用指令

1587089962889

fetch命令

  fetch命令主要用来显示爬虫爬取的过程,如果在scrapy项目目录之外使用该命令,则会调用scrapy默认的爬虫来进行网页的爬取,如果在scrapy的某个项目目录内使用该命令,则会调用该项目中的爬虫来进行网页的爬取

scrapy fetch http://www.baidu.com

1587346595821

  –headers 控制显示对象的爬虫爬取网站的头信息

  –nolog 控制不显示日志信息

  –logfile==FILE 存储日志文字信息

  –spider=SPIDER 控制使用哪个爬虫

  –loglevel=LEVEL控制日志级别

    日志等级常见值:

      CRITICAL   发生严重的错误

      ERROR    发生了必须立即处理的错误

      WARNING 出现一些警告信息

      INFO 输出一些提示信息

      DEBUG 输出一些调试信息,常用于开发阶段

runspider命令

  可以实现不依托scrapy的爬虫项目,直接运行一个爬虫文件运行独立的爬虫文件

在scrapy里创建一个独立的爬虫文件:

1
2
3
4
5
6
7
from scrapy.spiders import Spider
class FirstSpider(Spider):
name = "First"
allowed_domains = ["baidu.com"] #允许的域名
start_urls = ["http://www.baidu.com"] #开始的网址
def parse(self, response): #定义一个回调函数
pass

使用runspider运行:

scrapy runspider book.py

1587352324661

setting命令

  查看scrapy对应的配置信息,如果在项目目录内使用,查看的是对应项目的配置信息,如果在项目外使用查看的是scrapy默认配置信息
查看设置文件某一项的设置信息:

scrapy settings –get BOT_NAME

1587352752912

shell命令

  shell命令可以启动scrapy的交互终端,scrapy的交互终端经常在开发以及跳水的时候用到,使用scrapy的交互终端可以实现在不启动scrapy爬虫的情况下,对网站响应进行调试
1587354524402

startproject命令

  用于创建项目
再cmd中输入scrapy startproject firstspider [parm]1587345780960

version命令

  通过version命令可以直接显示scrapy的版本相关信息
1587355817193

view命令

  实现下载某个网页并用浏览器查看的功能
1587355912357

genspider

创建爬虫文件

scrapy genspider -l

查看又那些爬虫模板

1587361444742

scrapy genspider -t 模板名 文件名 域名

scrapy genspider -t basic firstspider cyzcc.vip

1587362020076

check

测试爬虫文件
scrapy check firstspider
1587362259064

crawl

运行爬虫文件(项目中的)
scrapy check firstspider

–onlog

不显示日志

list

查看当前项目下又那些可用的爬虫文件
scrapy list
1587362414480

大致流程

首先从intens.py定义目标,然后运行spiders文件,进入pipelines进行数据处理,然后进行下一次爬取。

爬取当当网商品

爬取商品名称、链接、评论数1587364478448

先创建一个爬虫项目

scrapy startproject dangdang

然后创建一个爬虫模板

scrapy genspider -t basic dd dangdang.com

1587369012879

之后定义item.py
创建我们需要爬取的东西

1
2
3
4
5
6
7
8
9
import scrapy


class DangdangItem(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
title = scrapy.Field() #存储标题
link = scrapy.Field() #存储链接
comment = scrapy.Field() #存储评论数

1587369140655

接着编写我们的爬虫文件dangdang.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# -*- coding: utf-8 -*-
import scrapy
from dangdang.items import DangdangItem #导入dangdang下面的items.py里面的DangdangItem类

class DdSpider(scrapy.Spider):
name = 'dd'
allowed_domains = ['dangdang.com']
start_urls = ['http://category.dangdang.com/pg5-cid4008123.html'] #第一页

def parse(self, response): #自动爬取,所有的信息都在response里面
item = DangdangItem() #实例化一个类
item["title"] = response.xpath("//a[@name='itemlist-title']/@title").extract() #从response中通过xpath表达式获取相关信息并且extract解压
item["link"] = response.xpath("//a[@name='itemlist-title']/@href").extract()
item["comment"] = response.xpath("//a[@name='itemlist-review']/text()").extract()
#print(item['link'])
yield item #将item获得的数据提交到popelines.py

1587392020790

还需要将settings.py的ROBOTSTXT_OBEY = True改为ROBOTSTXT_OBEY = False
运行一下:

scrapy crawl dd –nolog

1587392216106

接着处理内容并写入文件中,在pipelines.py中编写,在此之前要在setting中开启

pipelines.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class DangdangPipeline(object):
def process_item(self, item, spider):
for i in range(0,len(item["title"])):
title = item["title"][i]
link = item["link"][i]
comment = item["comment"][i]
res = str(i)+":"+title+":"+link+":"+comment
print(res)
try:
with open("C:\\Users\\华硕\\Desktop\\dangdang.txt", 'a') as file_object:
file_object.write(res + "\n")
except Exception as err: #使用异常处理
print(err)
return item

1587394691297

最后处理多页
在dd.py里面编写:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import scrapy
from dangdang.items import DangdangItem #导入dangdang下面的items.py里面的DangdangItem类
from scrapy.http import Request #导入scrapy下的request模块
class DdSpider(scrapy.Spider):
name = 'dd'
allowed_domains = ['dangdang.com']
start_urls = ['http://category.dangdang.com/pg5-cid4008123.html'] #第一页

def parse(self, response): #自动爬取,所有的信息都在response里面
item = DangdangItem() #实例化一个类
item["title"] = response.xpath("//a[@name='itemlist-title']/@title").extract() #从response中通过xpath表达式获取相关信息并且extract解压
item["link"] = response.xpath("//a[@name='itemlist-title']/@href").extract()
item["comment"] = response.xpath("//a[@name='itemlist-review']/text()").extract()
#print(item['link'])
yield item #将item获得的数据提交到popelines.py
for i in range(1,81):
url = "http://category.dangdang.com/pg"+str(i)+"-cid4008123.html" #构造url
yield Request(url,callback=self.parse) #使用yield返回,并设置url和回调函数

最后在运行

1587396149614

用户代理池构建

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#用户代理池的构建
import urllib.request
import re
import random
uapools = [
"Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Win64; x64; Trident/6.0)",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:75.0) Gecko/20100101 Firefox/75.0"
]
def ua(uapools):
thisua = random.choice(uapools)
print(thisua)
headers = ("User-Agent",thisua)
opener = urllib.request.build_opener()
opener.addheaders=[header]
#安装为全局
urllib.request.install_opener(opener)
#在使用的时候直接调用ua(uapools)即可

使用代理池爬取糗事百科搞笑图片

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#用户代理池的构建
import urllib.request
import re
import random
import requests
uapools = [
"Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Win64; x64; Trident/6.0)",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:75.0) Gecko/20100101 Firefox/75.0"
]
def ua(uapools):
thisua = random.choice(uapools)
print(thisua)
headers = ("User-Agent",thisua)
opener = urllib.request.build_opener()
opener.addheaders=[headers]
#安装为全局
urllib.request.install_opener(opener)

for i in range(0,35):
ua(uapools)
url= "https://www.qiushibaike.com/imgrank/page/"+str(i)+"/"
res = requests.get(url = url).text
#print(res)
#print(url)
pat = '<img src="(.*?)" alt='
result=re.compile(pat).findall(res)
for j in range(len(result)):
imgurl = "https:"+result[j]
print(imgurl)
downloadimg = requests.get(imgurl)
#下载图片
dir = 'C:\\Users\\华硕\\PycharmProjects\\python\\picture\\gaoxiao\\'+str(i)+"_"+str(j)+'.jpg'
with open(dir,'wb') as f:
f.write(downloadimg.content)
f.close()

1587525885405

1587526178097

这个路图片路径是真的很难匹配,xpath和bs4都有点问题,最后还是正则表达式才匹配成功,所以以后要加强对这几个表达式的训练。这次练手先爬一些搞笑图片,下次爬妹子图片了,再下次…嘿嘿

文章作者:CyzCc
最后更新:2020年04月22日 13:04:28
原始链接:https://cyzcc.vip/2020/04/22/python-Common-modules&scrapy/
版权声明:转载请注明出处!
您的支持就是我的动力!
-------------    本文结束  感谢您的阅读    -------------