python爬虫学习笔记

来源:互联网 发布:手机护眼软件 编辑:程序博客网 时间:2024/06/05 13:25

关注的专栏:http://blog.csdn.net/column/details/15321.htmlinclude

他的个人博客:http://cuijiahua.com/


一、网络爬虫简介

网络爬虫,也叫网络蜘蛛(Web Spider)。它根据网页地址(URL)爬取网页内容,而网页地址(URL)就是我们在浏览器中输入的网站链接。比如:https://www.baidu.com/,它就是一个URL。

1.1、审查元素

在浏览器的地址栏输入URL地址,在网页处右键单击,找到检查(不同浏览器的叫法不同,Chrome浏览器叫做检查,Firefox浏览器叫做查看元素)

浏览器就是作为客户端从服务器端获取信息,然后将信息解析,并展示给我们的。我们可以在本地修改HTML信息,为网页"整容",但是我们修改的信息不会回传到服务器,服务器存储的HTML信息不会改变。刷新一下界面,页面还会回到原本的样子。

1.2、练习实例

第一步:

根据URL,获取网页的HTML信息。在Python3中,可以使用urllib.request和requests进行网页爬取。

  • urllib库是python内置的,只要安装了Python就可以使用这个库。

  • requests库是第三方库。

requests库强大好用,本文使用requests库获取网页的HTML信息。requests库的github地址:https://github.com/requests/requests

(1)requests安装

在cmd中,使用如下指令(二选一)安装requests库:

  • pip install requests

  • easy_install requests


# -*- coding:UTF-8 -*-    import requests    if __name__ == '__main__':        target = 'http://gitbook.cn/'        req = requests.get(url=target)  #向服务器发起GET请求,requests.get()方法就是从服务器获取数据        print(req.text)
1.3、爬虫实例1:小说下载(静态)

小说网站《笔趣看》URL:http://www.biqukan.com/    下载《一念永恒》

步骤1:获取HTML

#/usr/bin/env.python  # -*- coding:UTF-8 -*-  import requests    if __name__ == '__main__':       target = 'http://www.biqukan.com/1_1094/5403177.html'       req = requests.get(url=target)       print(req.text)  

步骤2:解析HTML信息,提取感兴趣的内容

方法:正则表达式、Xpath、Beautiful Soup

Beautiful Soup指令安装(二选一):

  • pip install beautifulsoup4

  • easy_install beautifulsoup4

# -*- coding:UTF-8 -*-      from bs4 import BeautifulSoup      import requests            if __name__ == "__main__":          target = 'http://www.biqukan.com/1_1094/5403177.html'          req = requests.get(url = target)          html = req.text          bf = BeautifulSoup(html)          texts = bf.find_all('div', class_ = 'showtxt')           #find_all匹配的返回的结果是一个列表   print(texts[0].text.replace('\xa0'*8,'\n\n'))         #使用text属性,提取文本内容,滤除br标签,replace方法,剔除空格,替换为回车进行分段 
整合代码:

#/usr/bin/env.python  # -*- coding:UTF-8  from bs4 import BeautifulSoup  import requests, sys    class downloader(object):      def __init__(self):          self.server = 'http://www.biqukan.com/'          self.target = 'http://www.biqukan.com/1_1094/'          self.names = []  # 存放章节名          self.urls = []  # 存放章节链接          self.nums = 0  # 章节数         # 函数说明:获取下载链接      def get_download_url(self):          req = requests.get(url=self.target)          html = req.text          div_bf = BeautifulSoup(html)          div = div_bf.find_all('div', class_='listmain')          a_bf = BeautifulSoup(str(div[0]))          a = a_bf.find_all('a')          self.nums = len(a[15:])  # 剔除不必要的章节,并统计章节数          for each in a[15:]:              self.names.append(each.string)              self.urls.append(self.server + each.get('href'))      #    函数说明:获取章节内容      def get_contents(self, target):          req = requests.get(url=target)          html = req.text          bf = BeautifulSoup(html)          texts = bf.find_all('div', class_='showtxt')          texts = texts[0].text.replace('\xa0' * 8, '\n\n')          return texts        """     函数说明:将爬取的文章内容写入文件     Parameters:         name - 章节名称(string)         path - 当前路径下,小说保存名称(string)         text - 章节内容(string)     """        def writer(self, name, path, text):          write_flag = True          with open(path, 'a', encoding='utf-8') as f:              f.write(name + '\n')              f.writelines(text)              f.write('\n\n')      if __name__ == "__main__":      dl = downloader()      dl.get_download_url()      print('《一年永恒》开始下载:')      for i in range(dl.nums):          dl.writer(dl.names[i], '一念永恒.txt', dl.get_contents(dl.urls[i]))          sys.stdout.write("  已下载:%.3f%%" % float(i / dl.nums) + '\r')          sys.stdout.flush()      print('《一年永恒》下载完成')</span></pre><span style="font-size:18px"><br>  

1.4、爬虫实例1:图片下载(动态)


图片网址:https://unsplash.com/

html规定,图片统统给我放到<img>标签中,<img>标签有很多属性,有alt、src、class、style属性,其中src属性存放的就是我们需要的图片保存地址,我们根据这个地址就可以进行图片的下载。(并不可以!!!),该网站为动态加载,动态加载有一部分的目的就是为了反爬虫。动态网站使用动态加载常用的手段就是通过调用JavaScript来实现的

1、抓包工具:帮我们分析。Fiddler。URL:http://www.telerik.com/fiddler

2、浏览器自带的Network

json格式存储传输的数据,json格式是一种轻量级的数据交换格式,起到封装数据的作用,易于人阅读和编写,同时也易于机器解析和生成

整合代码:

# -*- coding:UTF-8 -*-import requests, json, time, sysfrom contextlib import closingclass get_photos(object):    def __init__(self):        self.photos_id = []        self.download_server = 'https://unsplash.com/photos/xxx/download?force=trues'        self.target = 'http://unsplash.com/napi/feeds/home'        self.headers = {'authorization': 'your Client-ID'}    """    函数说明:获取图片ID        """    def get_ids(self):        req = requests.get(url=self.target, headers=self.headers, verify=False)        html = json.loads(req.text)        next_page = html['next_page']        for each in html['photos']:            self.photos_id.append(each['id'])        time.sleep(1)        for i in range(4):            req = requests.get(url=next_page, headers=self.headers, verify=False)            html = json.loads(req.text)            next_page = html['next_page']            for each in html['photos']:                self.photos_id.append(each['id'])            time.sleep(1)    """    函数说明:图片下载    Parameters:        无    Returns:        无    Modify:        2017-09-13    """    def download(self, photo_id, filename):        headers = {            'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.79 Safari/537.36'}        target = self.download_server.replace('xxx', photo_id)        with closing(requests.get(url=target, stream=True, verify=False, headers=self.headers)) as r:            with open('%d.jpg' % filename, 'ab+') as f:                for chunk in r.iter_content(chunk_size=1024):                    if chunk:                        f.write(chunk)                        f.flush()if __name__ == '__main__':    gp = get_photos()    print('获取图片连接中:')    gp.get_ids()    print('图片下载中:')    for i in range(len(gp.photos_id)):        print('  正在下载第%d张图片' % (i + 1))        gp.download(gp.photos_id[i], (i + 1))


1.5、爬虫实例1:VIP视频下载


编写代码的时候注意一个问题,就是我们需要使用requests.session()保持我们的会话请求。简单理解就是,在初次访
问服务器的时候,服务器会给你分配一个身份证明。我们需要拿着这个身份证去继续访问,如果没有这个身份证明,
服务器就不会再让你访问。这也就是这个服务器的反爬虫手段,会验证用户的身份。


现在梳理一下编程思路:
用正则表达式匹配到key、time、url等信息。
根据匹配的到信息发POST请求,获得一个存放视频信息的url。
根据这个url获得视频存放的地址。
根据最终的视频地址,下载视频。

整合代码:

# -*- coding:utf-8 -*-from tkinter.filedialog import askdirectoryfrom MyQR.myqr import runfrom urllib import request, parsefrom bs4 import BeautifulSoupimport tkinter.messagebox as msgboximport tkinter as tkimport webbrowserimport reimport jsonimport osimport typesimport requestsimport time"""类说明:爱奇艺、优酷等实现在线观看以及视频下载的类Parameters:width - tkinter主界面宽height - tkinter主界面高Returns:无Modify:2017-05-09"""class APP:    def __init__(self, width=500, height=300):        self.w = width        self.h = height        self.title = ' VIP视频破解助手'        self.root = tk.Tk(className=self.title)        self.url = tk.StringVar()        self.v = tk.IntVar()        self.v.set(1)        # Frame空间        frame_1 = tk.Frame(self.root)        frame_2 = tk.Frame(self.root)        frame_3 = tk.Frame(self.root)        # Menu菜单        menu = tk.Menu(self.root)        self.root.config(menu=menu)        filemenu = tk.Menu(menu, tearoff=0)        moviemenu = tk.Menu(menu, tearoff=0)        menu.add_cascade(label='菜单', menu=filemenu)        menu.add_cascade(label='友情链接', menu=moviemenu)        filemenu.add_command(label='使用说明', command=lambda: webbrowser.open(            'http://blog.csdn.net/c406495762/article/details/71334633'))        filemenu.add_command(label='关于作者', command=lambda: webbrowser.open('http://blog.csdn.net/c406495762'))        filemenu.add_command(label='退出', command=self.root.quit)        # 各个网站链接        moviemenu.add_command(label='网易公开课', command=lambda: webbrowser.open('http://open.163.com/'))        moviemenu.add_command(label='腾讯视频', command=lambda: webbrowser.open('http://v.qq.com/'))        moviemenu.add_command(label='搜狐视频', command=lambda: webbrowser.open('http://tv.sohu.com/'))        moviemenu.add_command(label='芒果TV', command=lambda: webbrowser.open('http://www.mgtv.com/'))        moviemenu.add_command(label='爱奇艺', command=lambda: webbrowser.open('http://www.iqiyi.com/'))        moviemenu.add_command(label='PPTV', command=lambda: webbrowser.open('http://www.bilibili.com/'))        moviemenu.add_command(label='优酷', command=lambda: webbrowser.open('http://www.youku.com/'))        moviemenu.add_command(label='乐视', command=lambda: webbrowser.open('http://www.le.com/'))        moviemenu.add_command(label='土豆', command=lambda: webbrowser.open('http://www.tudou.com/'))        moviemenu.add_command(label='A站', command=lambda: webbrowser.open('http://www.acfun.tv/'))        moviemenu.add_command(label='B站', command=lambda: webbrowser.open('http://www.bilibili.com/'))        # 控件内容设置        group = tk.Label(frame_1, text='请选择一个视频播放通道:', padx=10, pady=10)        tb1 = tk.Radiobutton(frame_1, text='通道一', variable=self.v, value=1, width=10, height=3)        tb2 = tk.Radiobutton(frame_1, text='通道二', variable=self.v, value=2, width=10, height=3)        label1 = tk.Label(frame_2, text="请输入视频链接:")        entry = tk.Entry(frame_2, textvariable=self.url, highlightcolor='Fuchsia', highlightthickness=1, width=35)        label2 = tk.Label(frame_2, text=" ")        play = tk.Button(frame_2, text="播放", font=('楷体', 12), fg='Purple', width=2, height=1, command=self.video_play)        label3 = tk.Label(frame_2, text=" ")        # download = tk.Button(frame_2, text = "下载", font = ('楷体',12), fg = 'Purple', width = 2, height = 1, command = self.download_wmxz)        QR_Code = tk.Button(frame_3, text="手机观看", font=('楷体', 12), fg='Purple', width=10, height=2,                            command=self.QR_Code)        label_explain = tk.Label(frame_3, fg='red', font=('楷体', 12),                                 text='\n注意:支持大部分主流视频网站的视频播放!\n此软件仅用于交流学习,请勿用于任何商业用途!')        label_warning = tk.Label(frame_3, fg='blue', font=('楷体', 12), text='\n建议:将Chrome内核浏览器设置为默认浏览器\n作者:Jack_Cui')        # 控件布局        frame_1.pack()        frame_2.pack()        frame_3.pack()        group.grid(row=0, column=0)        tb1.grid(row=0, column=1)        tb2.grid(row=0, column=2)        label1.grid(row=0, column=0)        entry.grid(row=0, column=1)        label2.grid(row=0, column=2)        play.grid(row=0, column=3, ipadx=10, ipady=10)        label3.grid(row=0, column=4)        # download.grid(row = 0, column = 5,ipadx = 10, ipady = 10)        QR_Code.grid(row=0, column=0)        label_explain.grid(row=1, column=0)        label_warning.grid(row=2, column=0)    """    函数说明:jsonp解析    Parameters:        _jsonp - jsonp字符串    Returns:        _json - json格式数据    Modify:        2017-05-11    """    def loads_jsonp(self, _jsonp):        try:            _json = json.loads(re.match(".*?({.*}).*", _jsonp, re.S).group(1))            return _json        except:            raise ValueError('Invalid Input')    """    函数说明:视频播放    """    def video_play(self):        # 视频解析网站地址        port_1 = 'http://www.wmxz.wang/video.php?url='        port_2 = 'http://www.vipjiexi.com/tong.php?url='        # 正则表达是判定是否为合法链接        if re.match(r'^https?:/{2}\w.+$', self.url.get()):            if self.v.get() == 1:                # 视频链接获取                ip = self.url.get()                # 视频链接加密                ip = parse.quote_plus(ip)                # 浏览器打开                webbrowser.open(port_1 + self.url.get())            elif self.v.get() == 2:                # 链接获取                ip = self.url.get()                # 链接加密                ip = parse.quote_plus(ip)                # 获取time、key、url                get_url = 'http://www.vipjiexi.com/x2/tong.php?url=%s' % ip                # get_url_head = {                # 'User-Agent':'Mozilla/5.0 (Linux; Android 4.1.1; Nexus 7 Build/JRO03D) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166  Safari/535.19',                # 'Referer':'http://www.vipjiexi.com/',                # }                # get_url_req = request.Request(url = get_url, headers = get_url_head)                # get_url_response = request.urlopen(get_url_req)                # get_url_html = get_url_response.read().decode('utf-8')                # bf = BeautifulSoup(get_url_html, 'lxml')                # a = str(bf.find_all('script'))                # pattern = re.compile('"api.php", {"time":"(\d+)", "key": "(.+)", "url": "(.+)","type"', re.IGNORECASE)                # string = pattern.findall(a)                # now_time = string[0][0]                # now_key = string[0][1]                # now_url = string[0][2]                 # #请求播放,获取Success = 1                # get_movie_url = 'http://www.vipjiexi.com/x2/api.php'                # get_movie_data = {                # 'key':'%s' % now_key,                # 'time':'%s' % now_time,                # 'type':'',                # 'url':'%s' % now_url                # }                # get_movie_head = {                # 'User-Agent':'Mozilla/5.0 (Linux; Android 4.1.1; Nexus 7 Build/JRO03D) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166  Safari/535.19',                # 'Referer':'http://www.vipjiexi.com/x2/tong.php?',                # 'url':'%s' % ip,                # }                # get_movie_req = request.Request(url = get_movie_url, headers = get_movie_head)                # get_movie_data = parse.urlencode(get_movie_data).encode('utf-8')                # get_movie_response = request.urlopen(get_movie_req, get_movie_data)                # 请求之后立刻打开                webbrowser.open(get_url)        else:            msgbox.showerror(title='错误', message='视频链接地址无效,请重新输入!')    """    函数说明:视频下载,通过无名小站抓包(已经无法使用)    """    def download_wmxz(self):        if re.match(r'^https?:/{2}\w.+$', self.url.get()):            # 视频链接获取            ip = self.url.get()            # 视频链接加密            ip = parse.quote_plus(ip)            # 获取保存视频的url            get_url = 'http://www.sfsft.com/index.php?url=%s' % ip            head = {                'User-Agent': 'Mozilla/5.0 (Linux; Android 4.1.1; Nexus 7 Build/JRO03D) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166  Safari/535.19',                'Referer': 'http://www.sfsft.com/index.php?url=%s' % ip            }            get_url_req = request.Request(url=get_url, headers=head)            get_url_response = request.urlopen(get_url_req)            get_url_html = get_url_response.read().decode('utf-8')            bf = BeautifulSoup(get_url_html, 'lxml')            a = str(bf.find_all('script'))            pattern = re.compile("url : '(.+)',", re.IGNORECASE)            url = pattern.findall(a)[0]            # 获取视频地址            get_movie_url = 'http://www.sfsft.com/api.php'            get_movie_data = {                'up': '0',                'url': '%s' % url,            }            get_movie_req = request.Request(url=get_movie_url, headers=head)            get_movie_data = parse.urlencode(get_movie_data).encode('utf-8')            get_movie_response = request.urlopen(get_movie_req, get_movie_data)            get_movie_html = get_movie_response.read().decode('utf-8')            get_movie_data = json.loads(get_movie_html)            webbrowser.open(get_movie_data['url'])        else:            msgbox.showerror(title='错误', message='视频链接地址无效,请重新输入!')    """    函数说明:生成二维码,手机观看    """    def QR_Code(self):        if re.match(r'^https?:/{2}\w.+$', self.url.get()):            # 视频链接获取            ip = self.url.get()            # 视频链接加密            ip = parse.quote_plus(ip)            url = 'http://www.wmxz.wang/video.php?url=%s' % ip            words = url            images_pwd = os.getcwd() + '\Images\\'            png_path = images_pwd + 'bg.png'            qr_name = 'qrcode.png'            qr_path = images_pwd + 'qrcode.png'            run(words=words, picture=png_path, save_name=qr_name, save_dir=images_pwd)            top = tk.Toplevel(self.root)            img = tk.PhotoImage(file=qr_path)            text_label = tk.Label(top, fg='red', font=('楷体', 15), text="手机浏览器扫描二维码,在线观看视频!")            img_label = tk.Label(top, image=img)            text_label.pack()            img_label.pack()            top.mainloop()        else:            msgbox.showerror(title='错误', message='视频链接地址无效,请重新输入!')    """    函数说明:tkinter窗口居中    """    def center(self):        ws = self.root.winfo_screenwidth()        hs = self.root.winfo_screenheight()        x = int((ws / 2) - (self.w / 2))        y = int((hs / 2) - (self.h / 2))        self.root.geometry('{}x{}+{}+{}'.format(self.w, self.h, x, y))    """    函数说明:loop等待用户事件    """    def loop(self):        self.root.resizable(False, False)  # 禁止修改窗口大小        self.center()  # 窗口居中        self.root.mainloop()if __name__ == '__main__':    app = APP()  # 实例化APP对象    app.loop()  # loop等待用户事件




原创粉丝点击