学习目标:
python学习二十一 —数据抓取以及相关事项
学习内容:
1、简单的文字数据抓取(认识cookie、小说简介、小说内容、京东商品信息)
2、简单的图片数据抓取
1、简单的文字数据抓取
1、cookie的认识
- session机制采用的是在服务端保持状态的方案,而cookie机制则是在客户端保持状态的方案,cookie又叫会话跟踪机制
- 常见的是持久cookie:当我们在网站中,首次访问或者登陆就会生成cookie,即便跳转页面或者关闭浏览器再打开你依然是登陆状态
- cookie的集中常见属性:document.cookie=“key=value;expires=失效时间;path=路径;secure;(secure表安全级别)”
常见的cookie生成:用户名生成、用户IP生成、匿名生成(方便服务器传递一些信息)
2、获取页面源码的简单方法
- 注意获取网页内容的编码方式
import requests
import re
source = requests.get("https://www.23us.com/").content.decode('gbk')
demo = re.compile('<p class="ul1">\[(.*?)\]《<a class="poptext" href=".*?" target="_blank">(.*?)</a>》<\/p><p class="ul2"><a href=".*?" target="_blank">(.*?)</a></p><p>(.*?)</p>(.*?)</li>')
lists = demo.findall(source)
print(lists)
输出:
[('其他类型', '电影系统逍遥游', '第931章 佩恩来袭', '渔歌飘渺', '01-20'), ('都市言情', '都市极品医神', '第5212章 叶辰的布局!(八更!求月票!)', '风会笑', '01-20'), ('玄幻魔法', '八符', '第二百四十八章 弹指间灰飞烟灭', '噬君', '01-20'), ('玄幻魔法', '凡神物语', '第542章 重构', '商城', '01-20'), ('其他类型', '大明元辅', '第180章 税改大幕拉开', '云无风', '01-20'), ('历史军事', '朝为田舍郎', '第四百七十七章 潼关换将', '贼眉鼠眼', '01-20'), ('玄幻魔法', '灵龙传奇', '第461章:争先恐后', '悲伤的牧羊人', '01-20'), ('都市言情', '我有一个大世界', '第五百七十章 送快递的', '沉入太平洋', '01-20'), ('网游动漫', '英雄联盟之兼职主播', '第1423章 一改常态的SZ', '永远的黄昏', '01-20'), ('其他类型', '篮坛之锋芒逼人', '770开会开会开会!未知更动人!', '爱吃鱼的芒果', '01-20'), ('武侠修真', '最强昆仑掌门', '第一千零九十二章 观音泪与鬼泣剑', '阅读能力', '01-20'), ('其他类型', '我有一座八卦炉', '第七四二章 我李靖不死,你休想踏入陈塘关半步', '雪人不吃素', '01-20'), ('都市言情', '当医生遇上不正经系', '594、丧心病狂', '魔鬼藤', '01-20'), ('都市言情', '重生之跨国巨头', '第八百三十四章 后摩尔时代的芯片行业', '地球不安静', '01-20'), ('其他类型', '氪金剑仙李太白', '第210章 新罗北斗剑宗', '蜀山徐公', '01-20'), ('其他类型', '戏闹初唐', '第二五三二章', '活着就', '01-20'), ('其他类型', '平成骑士的旅行', '第511章 所有异虫都由我打倒!', '滴滴咯', '01-20'), ('历史军事', '无敌升级王', '第3671章 谈一谈', '可爱内内', '01-20'), ('玄幻魔法', '巅峰仙道', '第一千六百五十章 突破第三阵(二更)', '寒梅惊雪', '01-20'), ('其他类型', '皇天战尊', '第八百三十二章 暗衣剑客', '策马笑天下', '01-20'), ('其他类型', '我有一群地球玩家', '第一千四百八十五章:牧云姬的选择(下)', '第七个魔方', '01-20'), ('其他类型', '快穿之专业打脸指南', '第一千七百四十二章 牛皮吹破天之后5', '凤栖桐', '01-20'), ('其他类型', '都市极品医神', '第一千七百一十一章 安心去吧', '十万伏特', '01-20'), ('武侠修真', '一世符仙', '第一千二百零八章 解决', '玉菩提', '01-20'), ('其他类型', '绝世靓仔', '第五百九十二章天晴雨停你又行?', '纳肉', '01-20'), ('都市言情', '无敌神婿', '第三百四十五章 你有血光之灾', '小生水蓝色', '01-20'), ('网游动漫', '网游三国之真实世界', '第三百二十章 初战边章', '又又果子', '01-20'), ('其他类型', '天官之路', '第643章 现在的我已经完全不是以前的我', '戴铃铛的老猫', '01-20'), ('其他类型', '游戏王者', '第五十五章 战纪灵(上)', '伍玥初柒', '01-20'), ('历史军事', '汉世祖', '第38章 湖南无战事', '芈黍离', '01-20')]
3、获取的数据入mysql库
- 在mysql库建立相关字段的数据表
- 引入python的mysql相关的包
- 建立连接
- 遍历获取的数据依次入库
import requests
import re
# 引mysql包
import pymysql
# 建立mysql连接
connects = pymysql.connect(database='zhuaqu', user='root', password='1234', host='127.0.0.1', charset='utf8')
cursor = connects.cursor()
source = requests.get("https://www.23us.com/").content.decode('gbk')
demo = re.compile('<p class="ul1">\[(.*?)\]《<a class="poptext" href=".*?" target="_blank">(.*?)</a>》<\/p><p class="ul2"><a href=".*?" target="_blank">(.*?)</a></p><p>(.*?)</p>(.*?)</li>')
lists = demo.findall(source)
print(lists)
# 遍历数据并依次入库
for a, b, c, d, e in lists:
sql = 'insert into books(types,bookname,new_chapter,author,update_time) values("{}","{}","{}","{}","{}")'.format(a, b, c, d, e)
# 执行sql语句
cursor.execute(sql)
#向mysql提交数据
connects.commit()
connects.close()
4、抓取小说内容并导入到本地文件
- 根据网页链接样式决定抓取方式
总的章节
点进每个章节
- 所以需要在总章节获取到所有章节的地址,然后再分别获取各个章节里面的内容
在总的章节页面内每个tr标签分为四个td标签需要获取td中的每章的链接
获取到每章的连接之后,再分别获取章节名在h1标签中和章节内容在dd标签中
import requests
import re
# 获取到总章节的页面
source = requests.get('https://www.23us.com/html/72/72982/').content.decode('gbk')
# 正则匹配到每章节的地址
demo = re.compile('<a href="(\d+\.html)">.*?</a>')
lists = demo.findall(source)
# 遍历列表中每个章节的地址
for i in lists:
# 把每章节的地址加到网址的后面,以便直接获取到每章的内容
hrefs = 'https://www.23us.com/html/72/72982/'+i
source1 = requests.get(hrefs).content.decode('gbk')
# 正则匹配每章章名和文字内容
demo = re.compile('<h1>(.*?)</h1>.*?<dd id="contents".*?>(.*?)</dd>', re.S)
lists = demo.findall(source1)
# 匹配的章名和文字在列表中为两个元素a,b
print(lists)
for a, b in lists:
# 指定写入文件的地址,后面的yyt.txt实际对于代码而言不是文件,只是匹配内容写入的地址
op = open('F:\\yyt.txt', 'a+')
# 替换掉文字中的 和<br />特殊字符
b = b.replace(' ', ' ').replace('<br />', '\n')
# 用\n换行来分开章节名和章节内容
op.write('\n'+a+'\n'+b)
op.close()
2、简单的图片数据抓取
1、利用xpath抓取分组的图片
抓取图片时用到了xpath:
- 用xpath读取到了整个图片组的展示页面的xpath:
//*[@id="home"]
- 用xpath读取到了第一组图片组的xpath:
//*[@id="home"]/div/div[2]/a[1]
- 用xpath读取到了第一组图片组标题的xpath:
//*[@id="home"]/div/div[2]/a[1]/div[1]/text()
- 用xpath读取到了第一组第一张图片的xpath:
//*[@id="home"]/div/div[2]/a[1]/div[2]/div[1]
- 可以注意到a之前的都为公共部分,a[1]、a[2]…分别指第一组和第二组图片组:
//*[@id="home"]/div/div[2]/a
import requests
import re
# 用xpath时引用的包
from lxml import etree
# 在系统创建文件夹时引用的包
import os
# 去除特殊字符时引用的包
from string import punctuation
# 利用header头部模仿浏览器访问网站
headers = {
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36'
}
#设置遍历出的page网站翻页
for page in range(1,6):
# 获取到网站第二页的数据
source = requests.get('https://www.doutula.com/article/list/?page='+str(page), headers=headers).text
# 提取出获取图组时xpath的公共部分
base = etree.HTML(source).xpath('//*[@id="home"]/div/div[2]/a')
# 在base中取出每一组图片组
for b in base:
# 利用图片组获取到图片具体位置
pic = b.xpath('div[2]/div/img/@data-original')
# 利用图片组获取到图片组标题
title = b.xpath('div[1]/text()')[0]
# 去除title的特殊字符
title = re.sub('\W', '', title)
# 判断该文件夹是否存在
if os.path.isdir(title):
pass
else:
# 不存在就创建这个文件夹
os.mkdir(title)
# 判断是有图片的链接
if len(pic) != 0:
# 遍历图片的链接
for img in pic:
# 根据下划线拆分图片的连接取最后一段就是图片的名字(http://img.doutula.com/production/uploads/image/2017/10/17/20171017455259_KEfwXW.jpg)
pic_name = img.split('_')[-1]
# 访问并读取遍历到的图片
pic_content = requests.get(img, headers=headers).content
# 将读取到的图片分别存入创建的对应文件及里
op = open(title+'/'+pic_name, 'wb')
# 写入读取的文件
op.write(pic_content)
op.close()
2、利用xpath抓取单张图片
import requests
import re
from lxml import etree
headers = {
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36'
}
source = requests.get('https://www.doutula.com/article/list/?page=2', headers=headers).text
base = etree.HTML(source).xpath('//*[@id="home"]/div/div[2]/a[1]/div[2]/div[1]/img/@data-original')
# 注意此处读取第一组图片时,在相同的字段@data-original有四个读取的结果属于列表,所以应取出第一个元素为第一张图片
pic = requests.get(base[0], headers=headers).content
op = open('F:\\pycharm\\lx\\1.gpj', 'wb')
op.write(pic)
op.close()