Heim  >  Artikel  >  Backend-Entwicklung  >  Python crawlt die Daten der Baidu-Enzyklopädie

Python crawlt die Daten der Baidu-Enzyklopädie

高洛峰
高洛峰Original
2017-02-15 15:13:251363Durchsuche

Crawling-Strategie

Python抓取百度百科数据
Bestimmen Sie das Ziel: Bestimmen Sie, welcher Teil der Daten welcher Seiten welcher Website gecrawlt werden soll. Dieses Beispiel erfasst den Titel und die Einleitung der Python-Einstiegsseite der Baidu-Enzyklopädie und der Python-bezogenen Einstiegsseite.
Analyseziel: Analysieren Sie das Format der zu crawlenden URL und begrenzen Sie den Crawling-Bereich. Analysieren Sie das Format der zu erfassenden Daten. In diesem Beispiel müssen wir das Format der Tags analysieren, in denen sich die beiden Daten, Titel und Einleitung, befinden. Analysieren Sie das Format der zu crawlenden Seitenkodierung. Im Abschnitt „Webseiten-Parser“ müssen Sie die Webseitenkodierung angeben, bevor eine korrekte Analyse durchgeführt werden kann.
Code schreiben: Im Webseiten-Parser-Teil müssen Sie die durch die Analyse des Ziels erhaltenen Ergebnisse verwenden.
Crawler ausführen: Datenerfassung durchführen.

Analyseziele

1. URL-Format
Die Links zu verwandten Einträgen auf der Seite sind relativ einheitlich, meist /view/xxx.htm.
Python抓取百度百科数据

2. Datenformat
Der Titel befindet sich im h1-Untertag unter der Klasse lemmaWgt-lemmaTitle-title und die Einleitung befindet sich unter der Klasse lemma-summary.
Python抓取百度百科数据
Python抓取百度百科数据

3. Kodierungsformat
Sehen Sie sich das Seitenkodierungsformat an, das utf-8 ist.
Python抓取百度百科数据

Nach der obigen Analyse sind die Ergebnisse wie folgt:
Python抓取百度百科数据

Code-Schreiben

Projektstruktur

In sublime Erstellen Sie als Nächstes einen neuen Ordner „Baike-Spider“ als Projektstammverzeichnis.
Erstellen Sie eine neue Datei „spider_main.py“ als Crawler-Master-Scheduler.
Erstellen Sie eine neue url_manger.py als URL-Manager.
Erstellen Sie eine neue html_downloader.py als HTML-Downloader.
Erstellen Sie eine neue Datei html_parser.py als HTML-Parser.
Erstellen Sie eine neue html_outputer.py als Werkzeug zum Schreiben von Daten.
Die endgültige Projektstruktur ist wie folgt:
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()

Ausführen

Führen Sie in der Befehlszeile python spider_main.py aus.

Kodierungsproblem

Problembeschreibung: UnicodeEncodeError: Der Codec „gbk“ kann das Zeichen „xa0“ an Position nicht kodieren ...

Beim Schreiben einer Datei mit Python oder Beim Schreiben von Netzwerkdatenströmen in lokale Dateien tritt dieses Problem in den meisten Fällen auf. Es gibt viele ähnliche Artikel im Internet, die sich mit der Lösung dieses Problems befassen, aber sie sind nichts anderes als Codierung und Decodierung. Ist dies die wahre Ursache dieses Problems? NEIN. Oft verwenden wir Dekodieren und Kodieren und probieren verschiedene Kodierungen aus, z. B. utf8, utf-8, gbk, gb2312 usw. Wir haben alle Kodierungen ausprobiert, aber der Fehler tritt immer noch auf, was frustrierend ist.

Beim Schreiben von Python-Skripten unter Windows ist das Codierungsproblem sehr ernst. Beim Schreiben von Netzwerkdatenströmen in Dateien werden wir auf mehrere Kodierungen stoßen:
1. #encoding='XXX'
Die Kodierung hier (dh der Inhalt der ersten Zeile der Python-Datei) bezieht sich auf Python script Die Kodierung der Datei selbst spielt keine Rolle. Solange die Codierung von XXX und der Datei selbst identisch sind, ist alles in Ordnung.
Im Menü „Format“ von Notepad++ können beispielsweise verschiedene Kodierungen eingestellt werden. In diesem Fall müssen Sie sicherstellen, dass die im Menü eingestellte Kodierung mit der Kodierung XXX übereinstimmt gemeldet werden.

2. Kodierung des Netzwerkdatenstroms
Wenn Sie beispielsweise eine Webseite erhalten, ist die Kodierung des Netzwerkdatenstroms die Kodierung der Webseite. Zum Dekodieren in die Unicode-Kodierung muss Dekodieren verwendet werden.

3. Kodierung der Zieldatei
Schreiben Sie den Netzwerkdatenstrom in eine neue Datei. Der Dateischreibcode lautet wie folgt:

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

Unter Windows ist die Standardkodierung von Neue Dateien sind gbk. Der Python-Interpreter verwendet die gbk-Kodierung, um unseren Netzwerkdatenstrom str zu analysieren. Allerdings handelt es sich bei str um eine dekodierte Unicode-Kodierung, was zu einem Fehler beim Parsen und den oben genannten Problemen führt. Die Lösung besteht darin, die Kodierung der Zieldatei zu ändern:

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

运行结果

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

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

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn