Heim > Artikel > Backend-Entwicklung > Python crawlt die Daten der Baidu-Enzyklopädie
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.
1. URL-Format
Die Links zu verwandten Einträgen auf der Seite sind relativ einheitlich, meist /view/xxx.htm
.
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.
3. Kodierungsformat
Sehen Sie sich das Seitenkodierungsformat an, das utf-8 ist.
Nach der obigen Analyse sind die Ergebnisse wie folgt:
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:
# 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)
# 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
# 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()
# 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
# 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()
Führen Sie in der Befehlszeile python spider_main.py
aus.
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抓取百度百科数据 相关文章请关注PHP中文网!