2020-07-16

2020-07-17  本文已影响0人  杜宇_8141

爬虫学习一

我的系统环境是ubuntu20.04,使用python3.8。

1.了解网页结构

2.爬虫框架

2.1整体框架

以爬取豆瓣top250影片信息为例

 # -*- coding:utf-8 -*-
import urllib.request as ur
from bs4 import BeautifulSoup#网页解析获取数据
import re#正则表达式,进行文字匹配
import urllib.request,urllib.error#制定URL,获取数据
import xlwt#用于保存成excel
import sqlite3#进行SQLite数据库操作
def main() :
    baseurl = "https://movie.douban.com/top250?start="
    datalist = getData(baseurl)
    savepath = "./Top250.xls"
    saveData(datalist,savepath)
    

findLink = re.compile(r'<a href="(.*?)">')
#影片图片的规则
findImgSrc = re.compile(r'<img.*src="(.*?)"',re.S)#re.S让换行符包含在字符中
#影片片名
findTitle = re.compile(r'<span class="title">(.*)</span>')
#影片评分
findRating = re.compile(r'<span class="rating_num" property="v:average">(.*)</span>')
#评价人数
findJudge = re.compile(r'<span>(\d*)人评价</span>')
#找到概况
findInq = re.compile(r'<span class="inq">(.*)</span>')
#找到影片的相关内容
findBd = re.compile(r'<p class="">(.*?)</p>',re.S)
def getData(baseurl) :
    datalist = []
    for i in range(0,10) :
        url = baseurl + str(i*25)
        html = askURL(url)
        soup = BeautifulSoup(html,"html.parser")
        for item in soup.find_all('div',class_='item') :
            data = []
            item = str(item)
            link = re.findall(findLink,item)[0]
            data.append(link)
            imgSrc = re.findall(findImgSrc,item)[0]
            data.append(imgSrc)
            titles = re.findall(findTitle,item)
            if (len(titles) == 2) :
                ctitle = titles[0]
                data.append(ctitle)
                otitle = titles[1].replace('/','')
                data.append(otitle)
            else :
                data.append(titles[0])
                data.append(' ')
            rating = re.findall(findRating,item)[0]
            data.append(rating)
            judgeNum = re.findall(findJudge,item)[0]
            data.append(judgeNum)
            inq = re.findall(findInq,item)
            if len(inq) != 0 :
                inq = inq[0].replace("。",'')
                data.append(inq)
            else :
                data.append(" ")
            bd = re.findall(findBd,item)[0]
            bd = re.sub('<br(\s+)?'," ",bd)
            bd = re.sub('/'," ",bd)
            data.append(bd.strip())
            datalist.append(data)
    print(len(datalist))    
    return datalist

def askURL(url) :
    headers = {"User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36"}#构建一个header,防止被发现是爬虫,User-Agent不要出现空格
    request = ur.Request(url=url,headers=headers)#构建一个请求
    response = ur.urlopen(request)#发送请求
    try :
        response = ur.urlopen(request)
        html = response.read().decode("utf-8")
    #    print(html)
        return html
    except urllib.error.URLError as e :
        if hasattr(e,"code") :
            print(e.code)
        if hasattr(e,'reason') :
            print(e.reason)

def saveData(datalist,savepath) :
    book = xlwt.Workbook(encoding = "utf-8",style_compression=0) #创建workbook对象
    sheet = book.add_sheet('doubanTop250',cell_overwrite_ok=True)#创建工作表
    col = ('电影详情链接','图片链接','影片中文名','影片外文名','评分','评价数','概况','相关信息')
    for i in range(0,8) :
        sheet.write(0,i,col[i])
    for i in range(0,250) :
        print("第%d条"%(i+1))
        data = datalist[i]
        for j in range(0,8) :
            sheet.write(i+1,j,data[j])
    book.save(savepath)
#影片详情链接的规则


if __name__ == "__main__" :
    main()                                                                                                                                                                                      

2.2抓取网页源代码

有的写法是import urllib,然后urllib.request.Request,但是这样会显示urllib没有request模块,应该是由于python版本的问题。User-Agent在浏览器的Request Headers中可以找到。

def askURL(url) :
    headers = {"User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36"}#构建一个header,防止被发现是爬虫,User-Agent不要出现空格
    request = ur.Request(url=url,headers=headers)#构建一个请求
    response = ur.urlopen(request)#发送请求
    try :
        response = ur.urlopen(request)
        html = response.read().decode("utf-8")
        print(html)
        return html
       
    except urllib.error.URLError as e : 
        if hasattr(e,"code") :
            print(e.code)
        if hasattr(e,'reason') :
            print(e.reason)

给askURL函数传入百度首页的URL:https://www.baidu.com,就会打印出百度首页的源代码,内容较多,这里就不展示了。注意,如果返回错误信息418,则说明对方服务器识别出爬虫。
将打印内容保存到baidu.html中,用chrome浏览器打开,会发现正是百度首页的界面

baidu.html

2.3网页解析

对于一个保存好的网页baidu.html,我们可以通过BeautifulSoup来进行解析

from bs4 import BeautifulSoup
file = open("./baidu.html","rb")
html = file.read()
bs = BeautifulSoup(html,"html.parser")
#print(bs.title)
#print(bs.a)
#print(bs.head)
#查找含标签"a"的分区
t_list = bs.find_all("a")
print(t_list) 
#函数法
def name_is_exists(tag) :
  return tag.has_attr("name")
t_list = bs.find_all(name_is_exists)
print(t_list)
#Kwargs参数,注意class_有下划线
#t_list = bs.find_all(id = "head")
t_list = bs.find_all(class_=True)
for item in t_list :
  print(item)
#text参数
t_list = bs.find_all(text = "hao123")
t_list = bs.find_all(text = ["hao123","地图",“贴吧”])
for item in t_list :
  print(item)
#limit参数,限制最多查找个数
t_list = bs.find_all("a",limit=3)
for item in t_list :
  print(item)
#CSS选择器
#t_list = bs.select('title') #通过标签来查找
#t_list = bs.select(".mnav") #通过类名来查找
#t_list = bs.select("#v1")#通过id来查找
#t_list = bs.select("a[class='bri'])#通过属性查找
#t_list = bs.select("head > title")#通过子标签
t_list = bs.select(".mnav ~ .bri")#通过兄弟标签
print(t_list[0].get_text())

2.4正则表达式提取信息

正则表达式能够精确提取信息,这里直接搬运一下常用操作符


常用操作符1 常用操作符2
举例,如何匹配aabbcc@126.com,可以用.*@126.com
Re库主要功能函数
修饰符
举例
import re
#创建模式对象
pat = re.compile("AA")
m = pat.search("ABCAADDCCAAA")
print(m)#默认返回第一个匹配到的位置
#输出结果<re.Match object; span=(3, 5), match='AA'>
#无模式对象匹配
#m = re.search("asd","Aasd")
#print(m)
print(re.findall("a","ASDaDFGAa"))
print(re.findall("[A-Z]+","ASDaDFGAa"))
#替换方法sub
print re.sub("a","A","abcdcasd"))
#找到所有'a',并将其替换为'A'

建议在正则表达式中,被比较的字符串前面加上r,如 r"\aabd-'",不用担心转义字符的问题。

2.5保存数据

def saveData(datalist,savepath) :
    book = xlwt.Workbook(encoding = "utf-8",style_compression=0) #创建workbook对象
    sheet = book.add_sheet('doubanTop250',cell_overwrite_ok=True)#创建工作表
    col = ('电影详情链接','图片链接','影片中文名','影片外文名','评分','评价数','概况','相关信息')
    for i in range(0,8) :
        sheet.write(0,i,col[i])
    for i in range(0,250) :
        print("第%d条"%(i+1))
        data = datalist[i]
        for j in range(0,8) :
            sheet.write(i+1,j,data[j])
    book.save(savepath)

最终得到这样一张excel表


保存结果

3.补充

3.1 get和post方法的区别

get请求:
一般情况下,只从服务器获取数据,并不会对服务器数据产生影响的时候用get请求;
如 :

response = urllib.request.urlopen("http://httpbin.org/get")
print(response.read().decode("utf-8"))

post请求:
向服务器发送数据(登录),上传文件等,会对服务器资源产生影响的时候用post请求

import urllib.parse
data = bytes(urllib.parse.urlencode({"hello":"world"}),encoding="utf-8")
response = urllib.request.urlopen("http://httpbin.org/post",data=data)
print(response.read().decode("utf-8"))
上一篇下一篇

猜你喜欢

热点阅读