문제 설명
Python2.7에서 효과적인 크롤러를 만드는 방법 (How to make an effective crawler in Python2.7)
사용 가능한 각 제품의 가격과 정보를 얻기 위해 몇 겹의 옷을 크롤링하고 있지만 실제 알고리즘을 사용하면 완료하는 데 며칠이 걸리고 각 제품의 서로 다른 링크를 가져옵니다. 예를 들어 제품에 5가지 색상에 대한 5개의 링크가 있는 경우 5개의 링크가 있으며, 예를 들어 다음과 같이 92k 항목의 데이터베이스와 5k 제품만 있습니다.
https://i.gyazo.com/410d4faa33e2fbccf8979c5399856dd3.png
i.gyazo.com/b6118e67205d153272df001fb5efcfc8.png" rel="nofollow">https://i.gyazo.com/b6118e67205d153272df001fb5efcfc8.png 제품 ID
다른 링크입니다.그래서 저는 아이디어와 이를 개선하기 위해 구현하는 방법을 원합니다. 예를 들어 제품 ID가 있으므로 해당 ID가 포함된 링크 하나를 이미 방문한 경우 다시는 거기에 들어가고 싶지 않습니다. 그리고 모든 웹을 크롤링하고 싶지만 제품이 포함된 웹사이트만 방문하고 싶습니다... 하지만 그 두 가지 아이디어를 구현하는 방법을 모르겠습니다./
현재 내 코드는 다음과 같습니다(너무 느림 그리고 너무 많이 반복됨):
import urllib
import urlparse
from itertools import ifilterfalse
from urllib2 import URLError, HTTPError
from bs4 import BeautifulSoup
urls = {"http://www.kiabi.es/"}
visited = set()
def get_html_text(url):
try:
return urllib.urlopen(current_url.encode('ascii','ignore')).read()
except (IOError,URLError, HTTPError, urllib.ContentTooShortError):
print "Error getting " + current_url
urls.add(current_url)
def find_internal_links_in_html_text(html_text, base_url):
soup = BeautifulSoup(html_text, "html.parser")
links = set()
for tag in soup.findAll('a', href=True):
url = urlparse.urljoin(base_url, tag['href'])
domain = urlparse.urlparse(base_url).hostname
if domain in url:
links.add(url)
return links
def is_url_already_visited(url):
return url in visited
while urls:
try:
word = '#C'
current_url = urls.pop()
print "Parsing", current_url
if word in current_url:
print "Parsing", current_url
htmltext= urllib.urlopen(current_url).read()
soup= BeautifulSoup(htmltext)
[get the product info and save it into a sql database]
html_text = get_html_text(current_url)
visited.add(current_url)
found_urls = find_internal_links_in_html_text(html_text, current_url)
new_urls = ifilterfalse(is_url_already_visited, found_urls)
urls.update(new_urls)
except Exception:
pass
예를 들어, 해당 크롤러에서 "#C"라는 단어를 사용하여 제품 페이지라는 것을 알고 정보를 얻을 수 있지만 어떻게 해당 URL에 내가 이미 방문한 제품 ID가 있는지 구별하기 위해 관련 없는 URL을 피하는 방법을 모릅니다. 그렇기 때문에 프로그램이 너무 느리고 동일한 링크를 많이 가져옵니다.
감사합니다. 돕다,
참조 솔루션
방법 1:
I would recommend using Scrapy. My answer is based on its great features.
Quoting your doubts:
I don't know how to avoid irrelevant urls
Answer: To avoid visiting irrelevant URLs you should use a Crawler with certain logic based on your use case. That said, you could use CrawlSpider and define your own Crawling rules where each Rule defines a certain behaviour for crawling the site so you won't visit irrelevant URLs.
Here is an example: http://doc.scrapy.org/en/latest/topics/spiders.html#crawlspider‑example
...but I don't know how to distinguish if that url has a product ID that I already visited...
Answer: By default, Scrapy uses RFPDupeFilter
as its DUPEFILTER_CLASS
which is used to detect and filter duplicate requests. RFPDupeFilter
filters based on request fingerprint using the scrapy.utils.request.request_fingerprint
function.
This is a Scrapy log output sample for duplicated requests:
2015‑11‑23 14:26:48 [scrapy] DEBUG: Filtered duplicate request: <GET http://doc.scrapy.org/en/latest/topics/request‑response.html> ‑ no more duplicates will be shown (see DUPEFILTER_DEBUG to show all duplicates)
Here is a Scrapy tutorial if you haven't worked with it yet: http://doc.scrapy.org/en/latest/intro/tutorial.html
(by Joel Sánchez López、Andrés Pérez‑Albela H.)