Maison >développement back-end >Tutoriel Python >Python explore les données de l'encyclopédie Baidu

Python explore les données de l'encyclopédie Baidu

高洛峰
高洛峰original
2017-02-15 15:13:251373parcourir

Stratégie d'exploration

Python抓取百度百科数据
Déterminer l'objectif : Déterminer quelle partie des données de quelles pages de quel site Web explorer. Cet exemple capture le titre et l'introduction de la page d'entrée Python de l'Encyclopédie Baidu et de la page d'entrée associée à Python.
Objectif de l'analyse : analyser le format de l'URL à crawler et limiter la portée du crawl. Analysez le format des données à capturer. Dans cet exemple, nous devons analyser le format des balises où se trouvent les deux données, titre et introduction. Analysez le format de l'encodage de la page à analyser. Dans la section Analyseur de page Web, vous devez spécifier l'encodage de la page Web avant de pouvoir effectuer une analyse correcte.
Écrire du code : dans la partie analyseur de page Web, vous devez utiliser les résultats obtenus en analysant la cible.
Exécuter le robot : effectuez la capture de données.

Objectifs de l'analyse

1. Format de l'URL
Entrez dans la page d'entrée Python de l'Encyclopédie Baidu Les liens vers les entrées associées sur la page sont relativement uniformes, pour la plupart /view/xxx.htm.
Python抓取百度百科数据

2. Format des données
Le titre est situé dans la sous-balise h1 sous la classe lemmaWgt-lemmaTitle-title, et l'introduction est située sous la classe lemma-summary.
Python抓取百度百科数据
Python抓取百度百科数据

3. Format d'encodage
Affichez le format d'encodage de la page, qui est utf-8.
Python抓取百度百科数据

Après l'analyse ci-dessus, les résultats sont les suivants :
Python抓取百度百科数据

Écriture du code

Structure du projet

Dans sublime Next, créez un nouveau dossier baike-spider comme répertoire racine du projet.
Créez un nouveau spider_main.py en tant que planificateur principal du robot d'exploration.
Créez un nouveau url_manger.py en tant que gestionnaire d'URL.
Créez un nouveau html_downloader.py en tant que téléchargeur HTML.
Créez un nouveau html_parser.py comme analyseur HTML.
Créez un nouveau html_outputer.py comme outil d'écriture de données.
La structure finale du projet est la suivante :
Python抓取百度百科数据

spider_main.py

# coding:utf-8
import url_manager, html_downloader, html_parser, html_outputer

class SpiderMain(object):
    def __init__(self):
        self.urls = url_manager.UrlManager()
        self.downloader = html_downloader.HtmlDownloader()
        self.parser = html_parser.HtmlParser()
        self.outputer = html_outputer.HtmlOutputer()

    def craw(self, root_url):
        count = 1
        self.urls.add_new_url(root_url)
        while self.urls.has_new_url():
            try:
                new_url = self.urls.get_new_url()
                print('craw %d : %s' % (count, new_url))
                html_cont = self.downloader.download(new_url)
                new_urls, new_data = self.parser.parse(new_url, html_cont)
                self.urls.add_new_urls(new_urls)
                self.outputer.collect_data(new_data)

                if count == 10:
                    break

                count = count + 1
            except:
                print('craw failed')

        self.outputer.output_html()


if __name__=='__main__':
    root_url = 'http://baike.baidu.com/view/21087.htm'
    obj_spider = SpiderMain()
    obj_spider.craw(root_url)

url_manger.py

# coding:utf-8
class UrlManager(object):
    def __init__(self):
        self.new_urls = set()
        self.old_urls = set()

    def add_new_url(self, url):
        if url is None:
            return
        if url not in self.new_urls and url not in self.old_urls:
            self.new_urls.add(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)

    def has_new_url(self):
        return len(self.new_urls) != 0

    def get_new_url(self):
        new_url = self.new_urls.pop()
        self.old_urls.add(new_url)
        return new_url

html_downloader.py

# coding:utf-8
import urllib.request

class HtmlDownloader(object):
    def download(self, url):
        if url is None:
            return None
        response = urllib.request.urlopen(url)
        if response.getcode() != 200:
            return None
        return response.read()

html_parser.py

# coding:utf-8
from bs4 import BeautifulSoup
import re
from urllib.parse import urljoin

class HtmlParser(object):
    def _get_new_urls(self, page_url, soup):
        new_urls = set()
        # /view/123.htm
        links = soup.find_all('a', href=re.compile(r'/view/\d+\.htm'))
        for link in links:
            new_url = link['href']
            new_full_url = urljoin(page_url, new_url)
            # print(new_full_url)
            new_urls.add(new_full_url)
        #print(new_urls)
        return new_urls

    def _get_new_data(self, page_url, soup):
        res_data = {}
        # url
        res_data['url'] = page_url
        # <dd class="lemmaWgt-lemmaTitle-title"> <h1>Python</h1>
        title_node = soup.find('dd', class_='lemmaWgt-lemmaTitle-title').find('h1')
        res_data['title'] = title_node.get_text()
        # <p class="lemma-summary" label-module="lemmaSummary">
        summary_node = soup.find('p', class_='lemma-summary')
        res_data['summary'] = summary_node.get_text()
        # print(res_data)
        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')
        # print(soup.prettify())
        new_urls = self._get_new_urls(page_url, soup)
        new_data = self._get_new_data(page_url, soup)
        # print('mark')
        return new_urls, new_data

html_outputer.py

# coding:utf-8
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', encoding='utf-8')

        fout.write('<html>')
        fout.write('<body>')
        fout.write('<table>')

        for data in self.datas:
            fout.write('<tr>')
            fout.write('<td>%s</td>' % data['url'])
            fout.write('<td>%s</td>' % data['title'])
            fout.write('<td>%s</td>' % data['summary'])
            fout.write('</tr>')

        fout.write('</table>')
        fout.write('</body>')
        fout.write('</html>')

        fout.close()

Exécuter

Sur la ligne de commande, exécutez python spider_main.py.

Problème d'encodage

Description du problème : UnicodeEncodeError : le codec 'gbk' ne peut pas encoder le caractère 'xa0' en position...

Lors de l'écriture d'un fichier en utilisant Python, ou Lors de l'écriture de flux de données réseau dans des fichiers locaux, vous rencontrerez ce problème dans la plupart des cas. Il existe de nombreux articles similaires sur Internet expliquant comment résoudre ce problème, mais il ne s'agit que d'encodage et de décodage. Est-ce la véritable cause de ce problème ? Non. Plusieurs fois, nous utilisons le décodage et l'encodage, et essayons divers encodages, tels que utf8, utf-8, gbk, gb2312, etc. Nous avons essayé tous les encodages, mais l'erreur persiste, ce qui est frustrant.

Lors de l'écriture de scripts python sous Windows, le problème de codage est très grave. Lors de l'écriture de flux de données réseau dans des fichiers, nous rencontrerons plusieurs encodages :
1. #encoding='XXX'
L'encodage ici (c'est-à-dire le contenu de la première ligne du fichier python) fait référence au python. script L'encodage du fichier lui-même n'a pas d'importance. Tant que l'encodage de XXX et le fichier lui-même sont les mêmes, tout ira bien.
Par exemple, différents encodages peuvent être définis dans le menu "Format" du bloc-notes. Dans ce cas, vous devez vous assurer que l'encodage défini dans le menu est le même que l'encodage XXX. S'il est différent, une erreur se produira. être signalé.

2. Encodage du flux de données réseau
Par exemple, si vous obtenez une page Web, alors l'encodage du flux de données réseau est l'encodage de la page Web. Besoin d'utiliser le décodage pour décoder en codage Unicode.

3. Encodage du fichier cible
Écrire le flux de données réseau dans un nouveau fichier Le code d'écriture du fichier est le suivant :

fout = open('output.html','w')
fout.write(str)

Sous Windows, l'encodage par défaut de. les nouveaux fichiers sont gbk , l'interpréteur python utilisera le codage gbk pour analyser notre flux de données réseau str. Cependant, str est décodé en codage Unicode, ce qui entraînera un échec d'analyse et les problèmes ci-dessus. La solution est de changer l'encodage du fichier cible :

fout = open('output.html','w', encoding='utf-8')

运行结果

Python抓取百度百科数据
Python抓取百度百科数据

更多Python抓取百度百科数据 相关文章请关注PHP中文网!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn