Heim  >  Artikel  >  Backend-Entwicklung  >  Eine Kurzanleitung zum Starten eines Python-Crawlers von Grund auf

Eine Kurzanleitung zum Starten eines Python-Crawlers von Grund auf

阿神
阿神Original
2017-01-23 16:45:241272Durchsuche

Vorwort

Der Hauptinhalt dieses Artikels: Schreiben Sie in kürzester Zeit den einfachsten Crawler, der die Titel von Forumbeiträgen crawlen und Inhalte posten kann.

Zielgruppe dieses Artikels: Neulinge, die noch nie über Reptilien geschrieben haben.


Erste Schritte

0. Vorbereitung

Dinge, die Sie vorbereiten müssen: Python, Scrapy, eine IDE oder ein beliebiges Textbearbeitungstool.

1. Die technische Abteilung hat studiert und beschlossen, dass Sie den Crawler schreiben werden.

Erstellen Sie nach Belieben ein Arbeitsverzeichnis und erstellen Sie dann über die Befehlszeile ein Projekt. Der Projektname lautet miao und kann durch einen beliebigen Namen ersetzt werden.

scrapy startproject miao

Dann erhalten Sie die folgende Verzeichnisstruktur, die von Scrapy

Eine Kurzanleitung zum Starten eines Python-Crawlers von Grund auf

im Spiders-Ordner erstellt wurde. Erstellen Sie eine Python-Datei, z. B. miao.py, als Crawler-Skript. Der Inhalt ist wie folgt:

import scrapy
class NgaSpider(scrapy.Spider):
    name = "NgaSpider"
    host = "http://bbs.ngacn.cc/"
    # start_urls是我们准备爬的初始页
    start_urls = [
        "http://bbs.ngacn.cc/thread.php?fid=406",
    ]
    # 这个是解析函数,如果不特别指明的话,scrapy抓回来的页面会由这个函数进行解析。
    # 对页面的处理和分析工作都在此进行,这个示例里我们只是简单地把页面内容打印出来。
    def parse(self, response):
        print response.body

2. Probieren Sie es aus?

Wenn Sie die Befehlszeile verwenden, ist es das:

cd miao
scrapy crawl NgaSpider

Sie können sehen, dass das Reptil seitdem die erste Seite Ihres interstellaren Bereichs ausgedruckt hat Es findet keine Verarbeitung statt, daher wird eine Mischung aus HTML-Tags und JS-Skripten zusammen gedruckt.


Analyse

Als nächstes müssen wir die Seite analysieren, die wir gerade erfasst haben. Aus diesem HTML und js extrahierte Duili die Seite Titel des Beitrags auf dieser Seite. Tatsächlich ist das Parsen einer Seite eine mühsame Aufgabe, und es gibt viele Methoden. Hier stellen wir nur xpath vor.

0. Warum probieren Sie nicht den magischen XPath aus?

Schauen Sie sich das Ding an, das Sie gerade geschnappt haben, oder öffnen Sie die Seite manuell mit dem Chrome-Browser und drücken Sie F12. Sie können siehe Seitenstruktur. Jeder Titel wird tatsächlich von einem solchen HTML-Tag umschlossen. Beispiel:

<a href=&#39;/read.php?tid=10803874&#39; id=&#39;t_tt1_33&#39; class=&#39;topic&#39;>[合作模式] 合作模式修改设想</a>

Sie können sehen, dass href die Adresse des Beitrags ist (natürlich muss die Forumsadresse vorangestellt werden) und der in diesem Tag eingeschlossene Inhalt der Titel des Beitrags ist .
Also haben wir die absolute Positionierungsmethode von xpath verwendet, um den Teil mit class='topic' zu extrahieren.

1. Sehen Sie sich die Wirkung von xpath an

Fügen Sie oben ein Zitat hinzu:

from scrapy import Selector

Ändern Sie die Parse-Funktion in:

 def parse(self, response):
        selector = Selector(response)
        # 在此,xpath会将所有class=topic的标签提取出来,当然这是个list
        # 这个list里的每一个元素都是我们要找的html标签
        content_list = selector.xpath("//*[@class=&#39;topic&#39;]")
        # 遍历这个list,处理每一个标签
        for content in content_list:
            # 此处解析标签,提取出我们需要的帖子标题。
            topic = content.xpath(&#39;string(.)&#39;).extract_first()
            print topic
            # 此处提取出帖子的url地址。
            url = self.host + content.xpath(&#39;@href&#39;).extract_first()
            print url

Führen Sie es erneut aus und Sie können die Titel und URLs aller Beiträge auf der ersten Seite des interstellaren Bereichs Ihres Forums sehen.


Rekursiv

Als nächstes müssen wir den Inhalt jedes Beitrags erfassen. Sie müssen hier Pythons Yield verwenden.

yield Request(url=url, callback=self.parse_topic)

Hier weisen Sie Scrapy an, diese URL zu crawlen und dann die gecrawlte Seite mit der angegebenen parse_topic-Funktion zu analysieren.

An dieser Stelle müssen wir eine neue Funktion definieren, um den Inhalt eines Beitrags zu analysieren.

Der vollständige Code lautet wie folgt:

import scrapy
from scrapy import Selector
from scrapy import Request
class NgaSpider(scrapy.Spider):
    name = "NgaSpider"
    host = "http://bbs.ngacn.cc/"
    # 这个例子中只指定了一个页面作为爬取的起始url
    # 当然从数据库或者文件或者什么其他地方读取起始url也是可以的
    start_urls = [
        "http://bbs.ngacn.cc/thread.php?fid=406",
    ]

    # 爬虫的入口,可以在此进行一些初始化工作,比如从某个文件或者数据库读入起始url
    def start_requests(self):
        for url in self.start_urls:
            # 此处将起始url加入scrapy的待爬取队列,并指定解析函数
            # scrapy会自行调度,并访问该url然后把内容拿回来
            yield Request(url=url, callback=self.parse_page)

    # 版面解析函数,解析一个版面上的帖子的标题和地址
    def parse_page(self, response):
        selector = Selector(response)
        content_list = selector.xpath("//*[@class=&#39;topic&#39;]")
        for content in content_list:
            topic = content.xpath(&#39;string(.)&#39;).extract_first()
            print topic
            url = self.host + content.xpath(&#39;@href&#39;).extract_first()
            print url
            # 此处,将解析出的帖子地址加入待爬取队列,并指定解析函数
            yield Request(url=url, callback=self.parse_topic)
         # 可以在此处解析翻页信息,从而实现爬取版区的多个页面

    # 帖子的解析函数,解析一个帖子的每一楼的内容
    def parse_topic(self, response):
        selector = Selector(response)
        content_list = selector.xpath("//*[@class=&#39;postcontent ubbcode&#39;]")
        for content in content_list:
            content = content.xpath(&#39;string(.)&#39;).extract_first()
            print content
        # 可以在此处解析翻页信息,从而实现爬取帖子的多个页面

Bisher kann dieser Crawler die Titel aller Beiträge auf der ersten Seite Ihres Forums crawlen und die erste Seite jedes Beitrags crawlen . Inhalt auf jeder Etage. Das Prinzip des Crawlens mehrerer Seiten ist dasselbe. Achten Sie lediglich darauf, die URL-Adresse der Seite zu analysieren, die Beendigungsbedingung festzulegen und die entsprechende Seitenanalysefunktion anzugeben.


Pipelines - Pipelines

Hier ist die Verarbeitung des gecrawlten und analysierten Inhalts, den Sie in lokale Dateien schreiben können und Datenbanken über Pipes.

0. Definieren Sie ein Element

Erstellen Sie eine items.py-Datei im Miao-Ordner.

from scrapy import Item, Field
class TopicItem(Item):
    url = Field()
    title = Field() 
    author = Field()  
    
class ContentItem(Item):
    url = Field() 
    content = Field()
    author = Field()

Hier definieren wir zwei einfache Klassen, um die Ergebnisse unseres Crawlings zu beschreiben.

1. Schreiben Sie eine Verarbeitungsmethode

Suchen Sie die Datei „pipelines.py“ im Ordner „Miao“, der zuvor automatisch generiert wurde.

Wir können hier eine Verarbeitungsmethode erstellen.

class FilePipeline(object):

    ## 爬虫的分析结果都会由scrapy交给此函数处理
    def process_item(self, item, spider):
        if isinstance(item, TopicItem):            ## 在此可进行文件写入、数据库写入等操作
            pass
        if isinstance(item, ContentItem):            ## 在此可进行文件写入、数据库写入等操作
            pass
        ## ... 
        return item

2. Rufen Sie diese Verarbeitungsmethode im Crawler auf.

Um diese Methode aufzurufen, müssen wir sie nur im Crawler aufrufen. Die ursprüngliche Inhaltsverarbeitungsfunktion kann beispielsweise geändert werden in:

    def parse_topic(self, response):
        selector = Selector(response)
        content_list = selector.xpath("//*[@class=&#39;postcontent ubbcode&#39;]")        for content in content_list:
            content = content.xpath(&#39;string(.)&#39;).extract_first()            ## 以上是原内容
            ## 创建个ContentItem对象把我们爬取的东西放进去
            item = ContentItem()
            item["url"] = response.url
            item["content"] = content
            item["author"] = "" ## 略
            ## 这样调用就可以了
            ## scrapy会把这个item交给我们刚刚写的FilePipeline来处理
            yield item

3 Geben Sie dies an die Konfigurationsdatei-Pipeline

Suchen Sie die Datei „settings.py“ und fügen Sie

ITEM_PIPELINES = {            &#39;miao.pipelines.FilePipeline&#39;: 400,
        }

hinzu, um sie im Crawler aufzurufen „

yield item

wird von dieser FilePipeline verarbeitet. Die folgende Zahl 400 stellt die Priorität dar.
Sie können hier mehrere Pipelines konfigurieren, um die Elemente nacheinander entsprechend der Priorität an jedes Element zu übergeben. Das Ergebnis jeder Verarbeitung wird zur Verarbeitung an die nächste Pipeline übergeben.
Sie können mehrere Pipelines wie folgt konfigurieren:

ITEM_PIPELINES = {
            &#39;miao.pipelines.Pipeline00&#39;: 400,
            &#39;miao.pipelines.Pipeline01&#39;: 401,
            &#39;miao.pipelines.Pipeline02&#39;: 402,
            &#39;miao.pipelines.Pipeline03&#39;: 403,
            ## ...
        }


Middleware – Middleware

Über Middleware können wir einige Änderungen an den Anforderungsinformationen vornehmen. Beispielsweise können häufig verwendete Einstellungen wie UA, Proxy, Anmeldeinformationen usw. über Middleware konfiguriert werden.

0.Middleware-Konfiguration

ähnelt der Pipeline-Konfiguration. Fügen Sie den Namen von Middleware zu Setting.py hinzu, z. B.

DOWNLOADER_MIDDLEWARES = {
            "miao.middleware.UserAgentMiddleware": 401,
            "miao.middleware.ProxyMiddleware": 402,
        }

1. Habe die Website kaputt gemacht, um UA zu überprüfen, ich möchte UA ändern

某些网站不带UA是不让访问的。在miao文件夹下面建立一个middleware.py

import random


agents = [
    "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/532.5 (KHTML, like Gecko) Chrome/4.0.249.0 Safari/532.5",
    "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US) AppleWebKit/532.9 (KHTML, like Gecko) Chrome/5.0.310.0 Safari/532.9",
    "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/534.7 (KHTML, like Gecko) Chrome/7.0.514.0 Safari/534.7",
    "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/534.14 (KHTML, like Gecko) Chrome/9.0.601.0 Safari/534.14",
    "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.14 (KHTML, like Gecko) Chrome/10.0.601.0 Safari/534.14",
    "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.20 (KHTML, like Gecko) Chrome/11.0.672.2 Safari/534.20",
    "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534.27 (KHTML, like Gecko) Chrome/12.0.712.0 Safari/534.27",
    "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/13.0.782.24 Safari/535.1",
]


class UserAgentMiddleware(object): 

    def process_request(self, request, spider):
        agent = random.choice(agents)
        request.headers["User-Agent"] = agent

这里就是一个简单的随机更换UA的中间件,agents的内容可以自行扩充。

2.破网站封IP,我要用代理

比如本地127.0.0.1开启了一个8123端口的代理,同样可以通过中间件配置让爬虫通过这个代理来对目标网站进行爬取。同样在middleware.py中加入:

class ProxyMiddleware(object):
    def process_request(self, request, spider): 
        # 此处填写你自己的代理
        # 如果是买的代理的话可以去用API获取代理列表然后随机选择一个
        proxy = "http://127.0.0.1:8123"
        request.meta["proxy"] = proxy

很多网站会对访问次数进行限制,如果访问频率过高的话会临时禁封IP。如果需要的话可以从网上购买IP,一般服务商会提供一个API来获取当前可用的IP池,选一个填到这里就好。


一些常用配置

在settings.py中的一些常用配置

# 间隔时间,单位秒。指明scrapy每两个请求之间的间隔。
DOWNLOAD_DELAY = 5 

# 当访问异常时是否进行重试
RETRY_ENABLED = True 
# 当遇到以下http状态码时进行重试
RETRY_HTTP_CODES = [500, 502, 503, 504, 400, 403, 404, 408]
# 重试次数
RETRY_TIMES = 5

# Pipeline的并发数。同时最多可以有多少个Pipeline来处理item
CONCURRENT_ITEMS = 200
# 并发请求的最大数
CONCURRENT_REQUESTS = 100
# 对一个网站的最大并发数
CONCURRENT_REQUESTS_PER_DOMAIN = 50
# 对一个IP的最大并发数
CONCURRENT_REQUESTS_PER_IP = 50
我就是要用Pycharm

如果非要用Pycharm作为开发调试工具的话可以在运行配置里进行如下配置:
Configuration页面:
Script填你的scrapy的cmdline.py路径,比如我的是

/usr/local/lib/python2.7/dist-packages/scrapy/cmdline.py

然后在Scrpit parameters中填爬虫的名字,本例中即为:

crawl NgaSpider

最后是Working diretory,找到你的settings.py文件,填这个文件所在的目录。
示例:

Eine Kurzanleitung zum Starten eines Python-Crawlers von Grund auf

按小绿箭头就可以愉快地调试了。

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