1.爬虫复习
学习感言:最近马上找工作了,由于项目与看论文时学习东西是碎片化学习,只是会用,但是不知道怎么说,而且很久没有敲代码了,忘记了许多,感觉也生疏了许多。最近求职季,将数据结构与基础语法捡起来,期待找到一个好工作,这篇文章主要是讲的使用python进行爬虫。
爬虫:爬取网页数据的工具。
复习栏目:https://blog.csdn.net/Eastmount/article/details/108172132
python基本变量类型为:数字,字符串,列表,元祖,字典。
程序基本语句:for循环,while循环,if条件判断语句
2.准备
环境:win10,pycharm,python3.7
使用库:
Urllib,requests,urllib3,selenium,pyautogui,pprint,codecs,lxml,BeautifulSoup,MySQLdb
在上述库中有些事对立存在的,就是功能相同,但是有时候不知道自己适合使用哪一种,我再使用的时候同样存在着这一种疑惑,因此在这一篇文章解答自己疑惑,做一个笔记。
urllib
Python2.x 有这些库名可用: urllib,urllib2,urllib3,requests
Python3.x 有这些库名可用: urllib,urllib3,requests
python3中是将urllib于urllib2合并为urllib
urllib3增加线程安全连接池和文件post等支持,与urllib及urllib2的存在某些补充部分。
requests 是对urllib3的再次封装,可以直接构建常用的get和post请求并发起,使用更简洁方便。urllib一般要先构建get或者post请求,然后再发起请求。
**综上:**使用requests 进行http通信效果更好,使用pip install requests安装。
pprint是对print的输出美,使用pip install pprint安装。
**综上:**pprint比print好用
codecs是对python自带模块,兼容open()所有操作。用于解决python2的文件操作问题。如果希望代码同时兼容Python2和Python3,那么推荐用codecs.open。
Python3时codecs会出现open时使用的encoding和文件本身的encoding不一致读取文件会抛出异常,因此推荐使用open。
**综上:**open比codecs好用
数据库:
1,mysql-python也就是MySQLdb
2,PyMySQL,pymysql。支持jython,IronPython,CPython等;
3,mxODBC 和 mxODBC Connect
4,pyodbc
5,MySQL Connector/Python。这个是纯python实现的MySQL接口,由Oracle维护
6,mypysql。由c语言实现,目前还不能完全实现PEP249规范
7,PyPyODBC
8.轻量级数据库sqlite
常用库:mysql.connector, pymysql, MYSQLdb
mysql-connector是一个Python模块,它在Python中重新实现MySQL协议,它比较慢,但不需要C库,因此更便携。
MySQLdb是一个C模块,它使用MySQL客户端库中的MySQL协议实现相链接,它更快,但是需要C库才能工作。
MySQLdb只支持python 2.x 版本,mysqlclient 是MySQLdb的一个分支,解决了python 3.x 的兼容问题。pymysql纯Python实现的,安装简单(直接pip安装)
Python 3.6 下,pymysql 是最慢的,mysql-connector-python 很快,但是mysqlclient 更快,
综上:数据库选择使用mysqlclient 的MySQLdb,如果是少量数据可以选择使用sqlite,简单。
#-*-encoding:utf-8-*-
"""
# function/功能 :
# @File : 测试数据库速度.py
# @Time : 2021/7/9 17:21
# @Author : kf
# @Software: PyCharm
"""
import time
import MySQLdb
import mysql.connector
import pymysql
count=10000
sqlcode='select * from student2'
print('count:',count)
def demo():
s=time.time()
cursor=db.cursor()
for i in range(count):
cursor.execute(sqlcode)
result=cursor.fetchall()
print((time.time()-s))
db.close()
db=mysql.connector.connect(
host='localhost',
port = 3306,
user='kf',
passwd='123456',
db ='test')
print('mysql.connector')
demo()
db=pymysql.connect(
host='localhost',
port = 3306,
user='kf',
passwd='123456',
db ='test')
print('pymysql')
demo()
db=MySQLdb.connect(
host='localhost',
port = 3306,
user='kf',
passwd='123456',
db ='test')
print('MySQLdb')
demo()
count: 10000
mysql.connector
2.224727153778076
pymysql
2.162734031677246
MySQLdb
1.4283106327056885
DOM树解析:
lxml,BeautifulSoup
Beautiful Soup 4.4.0 文档 — Beautiful Soup 4.2.0 中文 文档
Document Object Model (DOM) 就是文档对象模型, 它使用对象的表示方式来表示对应的文档结构及其中的内容,是一种树结构。
性能 lxml >> BeautifulSoup
易用性 BeautifulSoup >> lxml
但是如果使用谷歌浏览器,lxml可以利用谷歌复制技术直接获取,同样简单。同时BeautifulSoup 在解析的时候会存在一定错误解析不出来,因此lxml相对来更易使用。
[外链图片转存中…(img-xjJmGznr-1625913868504)]
**综上:**选择lxml 库进行DOM解析与学习
Selenium特点是可以自动化操作鼠标和键盘,所以它更多的应用是自动化测试领域,通过自动操作网页,反馈响应的结果从而检测网站的健壮性和安全性。
PyAutoGUI是一个纯Python的GUI自动化工具,其目的是可以用程序自动控制鼠标和键盘操作,利用它可以实现自动化任务,再也不用担心有重复枯燥的任务了。
如果想通过浏览器进行爬虫,可以使用selenium,但是它相对于request来说速度慢。
综综上:使用request进行爬虫,lxml进行解析
3.开始项目1-豆瓣top250
步骤:
- 请求网页得到源代码
- 对源码进行解析
- 获得自己想要的信息
- 保存
网址:https://movie.douban.com/top250
目的:获取’排名’, ‘名称’, ‘链接’, ‘星级’, ‘评分’, ‘评价人数’
# coding:utf-8
import csv
import re
import requests
from lxml import etree
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
' (KHTML, like Gecko) Chrome/90.0.4430.85 Safari/537.36'
}
# 创建文件夹并打开
fp = open("./豆瓣top250.csv", 'a', newline='', encoding='utf-8')
writer = csv.writer(fp) # 写入
writer.writerow(('排名', '名称', '链接', '星级', '评分', '评价人数'))
# 循环遍历TOP250的URL
for page in range(0, 51, 25): # 226
print("正在获取第%s页" % page)
'''
//*[@id="content"]/div/div[1]/div[2]/a[2]
//*[@id="content"]/div/div[1]/div[2]/a[3]
'''
url = 'https://movie.douban.com/top250?start=%s&filter=' % page
# 请求源代码
reponse = requests.get(url=url, headers=headers).text
# 解析DOM树结构
html_etree = etree.HTML(reponse)
'''
//*[@id="content"]/div/div[1]/ol/li[1]
//*[@id="content"]/div/div[1]/ol/li[2]
//*[@id="content"]/div/div[1]/ol/li[1]/div/div[2]/div[2]/div
//*[@id="content"]/div/div[1]/ol/li[2]/div/div[2]/div[2]/div
//*[@id="content"]/div/div[1]/ol/li[3]/div/div[2]/div[2]/div/span[1]
//*[@id="content"]/div/div[1]/ol/li[1]/div/div[2]/div[1]/a/span[1]
//*[@id="content"]/div/div[1]/ol/li[1]/div/div[1]/em
//*[@id="content"]/div/div[1]/ol/li[1]
//*[@id="content"]/div/div[1]/ol/li[2]
//*[@id="content"]/div/div[1]/ol/li[1]/div/div[2]/div[1]/a/span[1]
'''
li = html_etree.xpath('//*[@class="grid_view"]/li')
# 定位节点 注意迭代xpath应用,使用相对路径
for item in li:
# 排名
rank = item.xpath('./div/div[1]/em/text()')[0]
# 电影名称
name = item.xpath('./div/div[2]/div[1]/a/span[1]/text()')[0]
# 链接 @ 表示获取属性值
dy_url = item.xpath('./div/div[2]/div[1]/a/@href')[0]
# 评分 正则表达式提取
rating = item.xpath('./div/div[2]/div[2]/div/span[1]/@class')[0]
# 只是得到数字
rating = re.sub(r'\D', "", rating)
if len(rating) == 2:
star = int(rating) / 10 # int()转化为数字
else:
star = rating
#评价的平均值
rating_num = item.xpath('./div/div[2]/div[2]/div/span[2]/text()')[0]
# 评价人数
content = item.xpath('./div/div[2]/div[2]/div/span[4]/text()')[0]
# 只是得到数字
content = re.sub(r'\D', "", content)
print(rank, name, dy_url, star, rating_num, content)
# 写入内容,一行写入
writer.writerow((rank, name, dy_url, star, rating_num, content))
fp.close()
4.项目2-得到百度词语
python request 获取 完整url_Python爬虫入门-用request获取相关网页信息_公文帮的博客-CSDN博客
1.观察链接得到url
2.得到标题信息
/text()获取指定标签下的文本内容,//text()获取指定标签下的文本内容,包括子标签下的文本内容
# coding:utf-8
import requests
from lxml import etree
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
' (KHTML, like Gecko) Chrome/90.0.4430.85 Safari/537.36'
}
sourceurl = 'https://baike.baidu.com/item/'
name = 'python'
url = sourceurl + name
# 请求源代码
reponse = requests.get(url=url, headers=headers)
print("正在爬取: " + reponse.request.url)
# 进行异常判断
reponse.raise_for_status()
# 解析DOM树结构
html_etree = etree.HTML(reponse.text)
'''
/html/body/div[3]/div[2]/div/div[1]/div[7]/dl[1]
'''
titli = html_etree.xpath('//dl[@class="lemmaWgt-lemmaTitle lemmaWgt-lemmaTitle-"]/dd/h1/text()')[0]
print('标题:', titli)
li = html_etree.xpath('//*[@class="basic-info J-basic-info cmn-clearfix"]/dl')
# 定位节点 注意迭代xpath应用,使用相对路径
for item in range(len(li)):
elem_name = li[item].xpath('./dt/text()')
elem_value = []
for i in range(1, len(elem_name) + 1):
tempList = []
temp = li[item].xpath('./dd[%d]' % i)
for xitem in temp:
# 对于每一个列表文本进行拼接
tempList += xitem.xpath('.//text()')
if len(tempList) == 1:
resStr = tempList[0]
else:
for i in range(len(tempList)):
resStr = ''.join(i for i in tempList)
resStr = resStr.replace('\n','')
elem_value.append(resStr)
# 构建字段成对输出
elem_dic = dict(zip(elem_name, elem_value))
for key in elem_dic:
print(key, elem_dic[key])
总结:在文字处理过程中存在许多问题,还是lxml读取有点生疏,写的东西也有一点糟糕,本来开始是打算详细写步骤的,但是后来因为不知道从何写起,因此最后直接黏贴代码了。