利用Python爬蟲爬取京東商品的簡要信息

1、前言html

  本文適合有必定Python基礎的同窗學習Python爬蟲,無基礎請點擊:慕課網——Python入門
  申明:實例的主體框架來自於慕課網——Python開發簡單爬蟲node

  語言:Python2python

  IDE:VScode

2、何爲爬蟲正則表達式

  傳統爬蟲從一個或若干初始網頁的URL開始,得到初始網頁上的URL,而後下載隊列中的URL地址對應的網頁。解析後抓取網頁內容,不斷從當前頁面上抽取新的URL放入隊列,直到知足系統的必定中止條件。同時,它還會根據必定的搜索策略獲取咱們所需的信息並保存下來。最後爲了展現咱們爬到的數據,每每還會用HTML的表格或記事本保存咱們所須要的數據。
  簡單來講,爬蟲就是一門用來從互聯網上自動獲取咱們所需數據的技術。

3、JD商品詳情頁的網頁分析瀏覽器

  入口URL選擇爲JD某商品詳情頁:https://item.jd.com/4224129.htmlapp

  咱們須要分析的內容主要有:框架

  3.1詳情頁上指向的其餘URLide

    咱們打開https://item.jd.com/4224129.html,發現網頁上還有不少指向其餘商品的連接。學習

    

    

    經過鼠標右鍵,查看元素,咱們能夠發現商品頁面上的以上連接均爲如下格式: //item.jd.com/數字.html測試

    

    分析到此,咱們就知道抓取網頁內容時,從當前頁面上抽取新的URL的方法了。

 

  3.2商品名稱、價格

  同理,咱們在商品名稱和價格處點擊鼠標右鍵查看元素

  

      


4、簡單爬蟲框架

  1.爬蟲總調度程序

    即咱們的main文件,以入口URL爲參數爬取全部相關頁面
    
  2.URL管理器

    維護待爬取和已爬取的URL列表


  3.HTML下載器

    主要功能是下載指定的url,這裏用到了urllib2

  4.HTML解析器
    主要功能是獲取網頁上所需的URL和內容,用到BeautifulSoup

    正則表達式的基礎知識能夠參見

    re模塊(正則表達式) - 人生不如戲 - 博客園

    另外安利一個網站,在寫正則表達式的時候能夠先測試,很實用

    正則表達式在線測試


  5.輸出程序

    將爬取到的數據寫入HTML文件中,利用HTML的table展現

5、源碼

  1.爬蟲總調度程序

import url_manager, html_downloader, html_parser, html_outputer

class SpiderMain(object):

    def __init__(self):
        self.urls = url_manager.UrlManager()
        self.downloader = html_downloader.Html_DownloaDer()
        self.parser = html_parser.HtmlParser()
        self.outputer = html_outputer.HtmlOutputer()

    #爬蟲調度程序
    def craw(self, root_url):
        count = 1
        #入口URL添加進URL管理器 
        self.urls.add_new_url(root_url)
        #啓動循環,獲取待扒取的URL,而後交給下載器下載頁面,調用解析器解析頁面
        while self.urls.has_new_url():
            try:
                new_url = self.urls.get_new_url()
                print 'craw',count, ':' ,new_url
                html_cont = self.downloader.download(new_url)

                #獲得新的URL列表和內容
                new_urls, new_data = self.parser.parse(new_url,html_cont)

                #新的URL存到URL管理器,同時進行數據的收集
                self.urls.add_new_urls(new_urls)
                self.outputer.collect_data(new_data)

                if count == 10:
                    break
                count = count +1
            except:
                print 'craw dailed'
        #調用output_html展現爬取到的數據
        self.outputer.output_html()


if __name__ == "__main__":
    #入口URL
    root_url = "https://item.jd.com/4224129.html"
    obj_spider = SpiderMain()
    #啓動爬蟲
    obj_spider.craw(root_url)


  2.URL管理器

class UrlManager(object):
    def __init__(self):
        #未爬取URL列表,已爬取URL列表
        self.new_urls = set()
        self.old_urls = set()

    #判斷管理器中是否有新的待扒取的URL
    def has_new_url(self):
        return len(self.new_urls) != 0

    #獲取一個新的待扒取的URL
    def get_new_url(self):
        #pop方法:獲取列表中的一個URL並移除它
        new_url = self.new_urls.pop()
        self.old_urls.add(new_url)
        return new_url

    #向管理器添加一個新的URL
    def add_new_url(self, url):
        if url is None:
            return
        #發現新的未添加的URL,則加入待扒取URL列表
        if url not in self.new_urls and url not in self.old_urls:
            self.new_urls.add(url)

    #向管理器添加批量個新的URL
    def add_new_urls(self, urls):
        if urls is None or len(urls) == 0:
            return
        for url in urls:
            self.add_new_url(url)


  3.HTML下載器

import urllib2

class Html_DownloaDer():
    def download(self, url):
        if url is None:
            return None
        #調用urllib2庫的urlopen方法獲取 類文件對象(fd) response
        """ response = urllib2.urlopen(url)"""


        #調用urllib2庫的Request方法建立request對象
        request = urllib2.Request(url)

        #添加數據
        request.add_data('a')

        #添加htp和header(假裝成瀏覽器)
        request.add_header('User-Agent','Mozilla/5.0')

        #發送請求獲取結果
        response = urllib2.urlopen(request)


        #獲取狀態碼,200表示成功
        if response.getcode() != 200:
            return None

        return response.read()


  4.HTML解析器

from bs4 import BeautifulSoup
import re
import urlparse

class HtmlParser(object):
    def _get_new_urls(self, page_url, soup):
        new_urls = set()
        #獲取全部的連接
        #格式如:<a target="_blank" title="華爲(HUAWEI)..." href="//item.jd.com/12943624333.html">
        links = soup.find_all('a',href = re.compile(r"//item.jd.com/\d+\.htm"))

         #遍歷轉化爲完整的URL
        for link in links:
            new_url = link['href']
            new_full_url = urlparse.urljoin(page_url,new_url)
            #將結果存到一個新的列表裏
            new_urls.add(new_full_url)
        
        return new_urls

    def _new_data(self, page_url, soup):
        res_data = {}
        
        #URL
        res_data['url'] = page_url

        #匹配標題
        #<div class="sku-name">華爲(HUAWEI) MateBook X 13英寸超輕薄微邊框筆記本(i5-7200U 4G 256G 拓展塢 2K屏 指紋 背光 office)灰</div>
        title_node = soup.find('div',class_ = "sku-name")
        res_data['title'] = title_node.get_text()

        #匹配價格
        #<div class="dd">
        #<span class="p-price"><span>¥</span><span class="price J-p-7430495">4788.00</span></span>
        """下載的網頁源碼無價格信息<span class="price J-p-7430495"></span></span>!!!!!"""                                                                                                 
        price_node = soup.find('span',class_ = re.compile(r"price\sJ\-p\-\d+"))
        res_data['price'] =price_node.get_text()

        return res_data

    def parse(self, page_url, html_cont):
        if page_url is None or html_cont is None:
            return

        soup = BeautifulSoup(html_cont,'html.parser')
        new_urls = self._get_new_urls(page_url,soup)
        _new_data = self._new_data(page_url,soup)

        return new_urls, _new_data


  5.輸出程序

class HtmlOutputer(object):
    def __init__(self):
        self.datas = []

    def collect_data(self,data):
        if data is None:
            return
        self.datas.append(data)

    def output_html(self):
        fout = open('output.html','w')

        fout.write("<html>")
        fout.write("<head>")
        fout.write('<meta charset="UTF-8">')        
        fout.write("<body>")
        fout.write("<table>")
        #python默認編碼是ascii,中文可能會亂碼,故加上encode('utf-8')
        for data in self.datas:
            fout.write("<tr>")
            fout.write("<td>%s</td>" % data['url'])
            fout.write("<td>%s</td>" % data['title'].encode('utf-8'))
            fout.write("<td>%s</td>" % data['price'].encode('utf-8'))
            fout.write("</tr>")

        fout.write("</table>")
        fout.write("</body>")
        fout.write("</head>")
        fout.write("</html>")


6、待解決問題

  關於我爬取不到價格的問題...

  調試中發現我已爬取到了對應的內容,惟獨少了價格...一度扎心啊...

  

  在 Python爬蟲——實戰一:爬取京東產品價格(逆向工程方法) - CSDN博客  上看到如下論述

  可是...我查看源碼的時候真的是有價格的啊...求大神解惑

 

ps:第一次寫博客,思路不是很清晰,歡迎學習交流指正。

相關文章
相關標籤/搜索