Ximore

导航

可恶 开始了,一次简单的网页爬取!但是忘记整理正则了。

终于是走上了这条路。

本来是想爬斗鱼里我的关注,结果光是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.就想到这些了。

 

posted on 2020-03-27 21:59  Ximore  阅读(85)  评论(0编辑  收藏  举报