Heim  >  Artikel  >  Backend-Entwicklung  >  Zeichnen Sie die Erfahrung beim Schreiben eines Crawlers in Python auf

Zeichnen Sie die Erfahrung beim Schreiben eines Crawlers in Python auf

高洛峰
高洛峰Original
2016-11-21 17:05:001429Durchsuche

Es gibt mittlerweile viele Möglichkeiten, Webcrawler zu schreiben, wie Node.js oder Go oder sogar PHP. Der Grund, warum ich mich für Python entschieden habe, ist, dass es viele Tutorials gibt und man es systematisch lernen kann, weil man es nur wissen muss Wie man den HTML-Selektor zum Crawlen verwendet, möchte ich auch einige häufige Fallstricke beim Crawling-Prozess sowie einige Vorsichtsmaßnahmen kennenlernen, z. B. kleine Tricks wie das Ändern des Browser-Headers.

Die Codekommentare sind sehr detailliert. Tatsächlich müssen Sie nur den Quellcode direkt lesen.

Der Zweck dieses Crawlers ist sehr einfach. Er crawlt eine Immobilien-Website und lädt ein Bild des Immobiliennamens und -preises herunter (einfach die Datei-Download-Funktion testen), um die Immobilienpreisentwicklung zu analysieren Um den Druck auf den Server der anderen Partei nicht zu erhöhen, habe ich mich nur für das Crawlen von 3 Seiten entschieden.

Lassen Sie mich über einige Wissenspunkte sprechen, die beachtet werden müssen:

#Denken Sie daran, die gesendeten Header zu ändern
Ich habe gehört, dass standardmäßig Header mit Python-Informationen gesendet werden , was sehr seltsam ist Es ist leicht, von der anderen Website als Crawler-Roboter erkannt zu werden, was zur Blockierung der IP führt. Daher ist es am besten, Ihr Crawler-Programm eher wie einen Menschen zu gestalten, aber dieser Code kann nur als allgemeiner Code dienen Verschleierung. Wenn es wirklich Websites gibt, die Crawler verhindern wollen, lügen Sie jedoch auch:

headers = {"User-Agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit 537.36 (KHTML, like Gecko) Chrome",
                "Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"},

#html-Selektor, ich verwende Pyquery anstelle von Beautifulsoup
Viele Bücher empfehlen Beautifulsoup , aber als Person, die an Jquery gewöhnt ist, ist die Syntax von beautifulsoup wirklich ein bisschen langwierig, und es scheint, dass es fortgeschrittene und komplexe CSS-Auswahlmodi wie „First-Child“ nicht unterstützt, oder es unterstützt es möglicherweise , aber ich konnte es nicht finden und ich habe die Dokumentation nicht sehr sorgfältig gelesen.

Dann habe ich online nach Informationen gesucht und festgestellt, dass viele Leute die Pyquery-Bibliothek empfohlen haben. Ich habe sie selbst verwendet und festgestellt, dass sie wirklich komfortabel ist, also habe ich sie entschlossen übernommen.

#Crawler-Idee
Die Idee ist eigentlich ganz einfach:
1. Suchen Sie die Auflistungsseite einer bestimmten Immobilie und analysieren Sie die URL-Struktur der zweiten und dritten Seite Auf jeder Auflistungsseite werden die URLs aller Listeneintragsinformationen in der set()-Sammlung von Python gespeichert. Der Grund für die Verwendung von set besteht darin, doppelte URL-Informationen zu entfernen.
3. Rufen Sie die Detailseite auf, indem Sie die URL des Hauses abrufen und dann zu wertvollen Feldinformationen wie Bildern und Text gelangen.
4. Derzeit drucke ich die Daten nur einfach aus und speichere die erhaltenen Daten nicht im lokalen JSON- oder CSV-Format.

Das Folgende ist das vollständige Code:

#获取页面对象
from urllib.request import urlopen
from urllib.request import urlretrieve
from pyquery import PyQuery as pq
#修改请求头模块,模拟真人访问
import requests
import time
#引入系统对象
import os

#你自己的配置文件,请将config-sample.py重命名为config.py,然后填写对应的值即可
import config

#定义链接集合,以免链接重复
pages = set()
session = requests.Session()
baseUrl = 'http://pic1.ajkimg.com'
downLoadDir = 'images'

#获取所有列表页连接
def getAllPages():
    pageList = []
    i = 1
    while(i < 2):
        newLink = &#39;http://sh.fang.anjuke.com/loupan/all/p&#39; + str(i) + &#39;/&#39;
        pageList.append(newLink)
        i = i + 1
    return pageList

def getAbsoluteURL(baseUrl, source):
    if source.startswith("http://www."):
        url = "http://"+source[11:] 
    elif source.startswith("http://"):
        url = source
    elif source.startswith("www."):
        url = "http://"+source[4:] 
    else:
        url = baseUrl+"/"+source 
    if baseUrl not in url:
        return None 
    return url

#这个函数内部的路径按照自己的真实情况来写,方便之后的数据导入
def getDownloadPath(baseUrl, absoluteUrl, downloadDirectory): 
    path = absoluteUrl.replace("www.", "")
    path = path.replace(baseUrl, "")
    path = downloadDirectory+path
    directory = os.path.dirname(path)
    if not os.path.exists(directory): 
        os.makedirs(directory)
    return path

#获取当前页面的所有连接
def getItemLinks(url):
    global pages;
    #先判断是否能获取页面
    try:
        req = session.get(url, headers = config.value[&#39;headers&#39;])
    #这个判断只能判定是不是404或者500的错误,如果DNS没法解析,是无法判定的
    except IOError as e:
        print(&#39;can not reach the page. &#39;)
        print(e)
    
    else: 
        h = pq(req.text)
        #获取第一页的所有房子模块
        houseItems = h(&#39;.item-mod&#39;)
        #从模块中提取我们需要的信息,比如详情页的URL,价格,略缩图等
        #我倾向只获取详情页的URL,然后在详情页中获取更多的信息
        for houseItem in houseItems.items():
            houseUrl = houseItem.find(&#39;.items-name&#39;).attr(&#39;href&#39;)
            #print(houseUrl)
            pages.add(houseUrl)
        
#获取详情页的各种字段,这里可以让用户自己编辑
def getItemDetails(url):
    #先判断是否能获取页面
    try:
        req = session.get(url, headers = config.value[&#39;headers&#39;])
    #这个判断只能判定是不是404或者500的错误,如果DNS没法解析,是无法判定的
    except IOError as e:
        print(&#39;can not reach the page. &#39;)
        print(e)
    else:
        time.sleep(1)
        h = pq(req.text)

        #get title
        housePrice = h(&#39;h1&#39;).text() if h(&#39;h1&#39;) != None else &#39;none&#39;

        #get price
        housePrice = h(&#39;.sp-price&#39;).text() if h(&#39;.sp-price&#39;) != None else &#39;none&#39;

        #get image url
        houseImage = h(&#39;.con a:first-child img&#39;).attr(&#39;src&#39;)
        houseImageUrl = getAbsoluteURL(baseUrl, houseImage)
        if houseImageUrl != None:
            urlretrieve(houseImageUrl, getDownloadPath(baseUrl, houseImageUrl, downLoadDir))     
        # if bsObj.find(&#39;em&#39;,{&#39;class&#39;,&#39;sp-price&#39;}) == None:
        #     housePrice = &#39;None&#39;
        # else:
        #     housePrice = bsObj.find(&#39;em&#39;,{&#39;class&#39;,&#39;sp-price&#39;}).text;
        # if bsObj.select(&#39;.con a:first-child .item img&#39;)== None:
        #     houseThumbnail = &#39;None&#39;
        # else:
        #     houseThumbnail = bsObj.select(&#39;.con a:first-child .item img&#39;);

        


#start to run the code
allPages = getAllPages()

for i in allPages:
    getItemLinks(i)
#此时pages 应该充满了很多url的内容
for i in pages:
    getItemDetails(i)
#print(pages)


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