可恶 开始了,一次简单的网页爬取!但是忘记整理正则了。
终于是走上了这条路。
本来是想爬斗鱼里我的关注,结果光是cookie和刷新方式的问题就给我干住了,显示的网页源码一直有问题,等日后再解决了。
换了一个简单的思路 也不算是真做了爬虫 只是把网页源码筛选做了一个list数组并显示出来主要信息。
import re import time import requests from bs4 import BeautifulSoup import json import io def scp_num(): print('爬取开始') time.sleep(1) url = 'https://www.douyu.com/g_TVgame' print('目标为:',url) time.sleep(1) print('获取地址...') time.sleep(1) print(url) time.sleep(1) headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:74.0) Gecko/20100101 Firefox/74.0' } res = requests.get(url) print('目标网址编码方式为:',res.encoding) soup1 = BeautifulSoup(res.text,'html.parser') soup = soup1.encode() #print(res.text) #print(soup) print('缓存完成') time.sleep(1) return soup def save(): res = scp_num() print('尝试命名文件,') time.sleep(1) with io.open(f'主机游戏.txt','wb') as fw : fw.write(res) fw.close() print('写入完成已关闭') time.sleep(1) # def write_to_file(content): # with open('结果.txt', 'a', encoding='utf-8') as f: # f.write(json.dumps(content, ensure_ascii=False) + '\n') # f.close()
#这一段是在网上找到的一个保存写入的方法,也没用上。
def sheike(): with io.open(f'主机游戏.txt','r',encoding = 'utf-8') as f : res = f.read() #print(res) m = re.findall('title=\"(.{1,200})\">.{1,200}<\/h3><\/div><div class=\".{1,100}\">.{1,100}<\/use><\/svg>(.{1,100})</span>.{1,100}<\/use><\/svg>(.{1,100})<\/h2><\/div><\/div><\/a><a href=\"\/(\d{1,100})\"',res, re.M|re.I) #print(m) for i in range(0,119): wz = 'https://www.douyu.com/'+m[i][3] print('房间名:',m[i][0],' 人气值:',m[i][1],' 主播名:',m[i][2],' 房间号:',m[i][3],' 网址:',wz) time.sleep(0.2) if __name__ == '__main__': save() sheike()
以上全部代码。
接下来,一段一段解释。
def scp_num(): print('爬取开始') time.sleep(1) url = 'https://www.douyu.com/g_TVgame' print('目标为:',url) time.sleep(1) print('获取地址...') time.sleep(1) print(url) time.sleep(1) headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:74.0) Gecko/20100101 Firefox/74.0' } res = requests.get(url) print('目标网址编码方式为:',res.encoding) soup1 = BeautifulSoup(res.text,'html.parser') soup = soup1.encode() #print(res.text) #print(soup) print('缓存完成') time.sleep(1) return soup
这里,采用了beautifulsoup,甚至本来就用不到这么多,只是刚开始有备无患,加了点简单的文字print,看起来比较好看。
def save(): res = scp_num() print('尝试命名文件,') time.sleep(1) with io.open(f'主机游戏.txt','wb') as fw : fw.write(res) fw.close() print('写入完成已关闭')
保存网页源代码,在根目录生成了一个叫做‘主机游戏.txt’的文本,保存了爬取目标的所有网页源码。(是不是还挺傻的)
我感觉所有爬取做到这一步基本已经结束了。能够把 含有 需要内容的 html 保存成 一个 txt文件,接下来就没什么难度了。
def sheike(): with io.open(f'主机游戏.txt','r',encoding = 'utf-8') as f : res = f.read() #print(res) m = re.findall('title=\"(.{1,200})\">.{1,200}<\/h3><\/div><div class=\".{1,100}\">.{1,100}<\/use><\/svg>(.{1,100})</span>.{1,100}<\/use><\/svg>(.{1,100})<\/h2><\/div><\/div><\/a><a href=\"\/(\d{1,100})\"',res, re.M|re.I) #print(m) for i in range(0,119): wz = 'https://www.douyu.com/'+m[i][3] print('房间名:',m[i][0],' 人气值:',m[i][1],' 主播名:',m[i][2],' 房间号:',m[i][3],' 网址:',wz) time.sleep(0.2)
所有函数和类都是我瞎取的名字奥,我就争取我自己能看懂。
这一部分用到了很关键的,研究了很久的 正则表达式。
正则表达式里面的东西零零散散的,在网上找了很久,突然想起来接下来再写一篇把这些列出来好了。
m = re.findall('title=\"(.{1,200})\">.{1,200}<\/h3><\/div><div class=\".{1,100}\">.{1,100}<\/use><\/svg>(.{1,100})</span>.{1,100}<\/use><\/svg>(.{1,100})<\/h2><\/div><\/div><\/a><a href=\"\/(\d{1,100})\"',res, re.M|re.I)
是不是显而易见?
放屁!平心而论,我写完了自己看我都看不懂。
re模块的findall 可以找出来所有符合表达式的字符串,并存入m这个list数组里。
到这一步可以print试一下,会输出大概是[(xxx,xxx,xxx,xxx),(xxx,xxx,xxx,xxx),(xxx,xxx,xxx,xxx),(xxx,xxx,xxx,xxx),......]这样的内容。
正则表达式书写问题等最后讨论。
这里学了一个yield,但是没学会,所以我换了一个方式。
因为m是一个n行4列的list(n在我这里等于120,因为我数了在这个网址下获得的只是前120名的信息),每一列都是一类数据值——人气,房间号之类的,所以我就直接用for in循环了。
这就算是结束了。
正则的问题:
m = re.findall('title=\"(.{1,200})\">.{1,200}<\/h3><\/div><div class=\".{1,100}\">.{1,100}<\/use><\/svg>(.{1,100})</span>.{1,100}<\/use><\/svg>(.{1,100})<\/h2><\/div><\/div><\/a><a href=\"\/(\d{1,100})\"',res, re.M|re.I)
#再放一遍这个
所有的‘\’是转译,就是说'\/'对应了'/',这样,在正则就可以识别了(双引号也需要转译)。
()里是要输出的内容。
'.'在正则里匹配所有字符,因为房间名、主播名等可能就很复杂,所以可以采用这个方式(我也不会别的了)。
接下来是'{}'是什么?
代表前面这个匹配了多少次。'.{1,10}'就是以'.'的形式匹配了1或者10次,我就随便写了个100、200的省得超额。
剩下的就显而易见了。如果还看不懂——
这是我笔记的一段,正则匹配大概就跟找规律差不多,找到怎么精确提取出所需元素就可以了。
这个是原文,不知道为啥复制过来就成图片了,对照一下应该也差不多。
看懂了怎么写的,就很简单了,每个地方对应上,万无一失了,剩下的Python就给解决了。
# -*- coding: utf-8 -*- """ Created on Fri Mar 27 21:16:46 2020 @author: Ximore """ import re import time import requests from bs4 import BeautifulSoup import json import io def scp_num(): print('爬取开始') time.sleep(1) url = 'https://www.douyu.com/g_TVgame' print('目标为:',url) time.sleep(1) print('获取地址...') time.sleep(1) print(url) time.sleep(1) headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:74.0) Gecko/20100101 Firefox/74.0' } res = requests.get(url) print('目标网址编码方式为:',res.encoding) soup1 = BeautifulSoup(res.text,'html.parser') soup = soup1.encode() #print(res.text) #print(soup) print('缓存完成') time.sleep(1) return soup def save(): res = scp_num() print('尝试命名文件,') time.sleep(1) with io.open(f'主机游戏.txt','wb') as fw : fw.write(res) fw.close() print('写入完成已关闭') time.sleep(1) # def write_to_file(content): # with open('结果.txt', 'a', encoding='utf-8') as f: # f.write(json.dumps(content, ensure_ascii=False) + '\n') # f.close() def sheike(): with io.open(f'主机游戏.txt','r',encoding = 'utf-8') as f : res = f.read() #print(res) m = re.findall('title=\"(.{1,200})\">.{1,200}<\/h3><\/div><div class=\".{1,100}\">.{1,100}<\/use><\/svg>(.{1,100})</span>.{1,100}<\/use><\/svg>(.{1,100})<\/h2><\/div><\/div><\/a><a href=\"\/(\d{1,100})\"',res, re.M|re.I) #print(m) with open('结果.txt', 'w', encoding='utf-8') as f: for i in range(0,119): wz = 'https://www.douyu.com/'+m[i][3] print('房间名:',m[i][0],' 人气值:',m[i][1],' 主播名:',m[i][2],' 房间号:',m[i][3],' 网址:',wz) time.sleep(0.2) f.write('房间名:'+m[i][0]+' 人气值:'+m[i][1]+' 主播名:'+m[i][2]+' 房间号:'+m[i][3]+' 网址:'+wz + '\n') f.close() if __name__ == '__main__': save() sheike()
(补一个 保存了 结果.txt 写入了输出)
1.此外,在写的过程中遇到了一个
pattern = re.compile(
这个看网上的大佬们说,在常用的match、search、findall里面是包含的,我没看re模块,大概的理解就是,这个是用不上的,嗯,就是可以不学的那种,如果想了解 可在re模块的py文件里找到(大概)。
2.所有的time模块和time.sleep都可以删除,除了最后的输出之外,其他输出也可以删除,一开始是用于调试,后来就给自己看看图一乐。
3.如果想把最后的结果保存了也简单(我觉得,但是没试)。可以直接写入list数组m,也可以把遍历之后的结果写进去,参照上面的保存网页源代码。
4.就想到这些了。