1) urllib2+BeautifulSoup은 Google 검색 링크를 캡처합니다
최근 Google 검색 결과 처리가 필요한 프로젝트에 참여했으며 이전에 웹 페이지 처리와 관련된 Python 도구를 배웠습니다. 실제 애플리케이션에서는 웹 페이지를 크롤링하기 위해 urllib2 및 beautifulsoup를 사용합니다. 그러나 Google 검색 결과를 크롤링할 때 Google 검색 결과 페이지의 소스 코드를 직접 처리하면 많은 "더티" 링크가 얻어지는 것으로 나타났습니다.
"타이타닉 제임스"를 검색한 결과는 아래 사진을 보세요:
사진에서 빨간색으로 표시된 것은 필요하지 않으며, 파란색으로 표시된 항목은 캡처되어 처리되어야 합니다.
물론 이런 '더티 링크'는 룰 필터링을 통해 걸러낼 수 있지만, 프로그램의 복잡도가 높아질 것입니다. 찡그린 얼굴로 필터링 규칙을 작성하던 중이었습니다. 같은 반 친구가 Google이 관련 API를 제공해야 한다는 점을 상기시켜 주었고 저는 갑자기 이해하게 되었습니다.
(2) Google Web Search API + 멀티스레딩
문서에는 Python을 사용하여 검색하는 예가 나와 있습니다.
그림의 빨간색은 필요하지 않습니다. 파란색은 캡처 및 처리가 필요하다고 표시된 것입니다.
물론 이런 '더티 링크'는 룰 필터링을 통해 걸러낼 수 있지만, 프로그램의 복잡도가 높아질 것입니다. 찡그린 얼굴로 필터링 규칙을 작성하던 중이었습니다. 같은 반 친구가 Google이 관련 API를 제공해야 한다는 점을 상기시켜 주었고 저는 갑자기 이해하게 되었습니다.
(2) Google Web Search API + 멀티스레딩
문서에서는 Python을 사용하여 검색하는 예를 제공합니다.
import simplejson # The request also includes the userip parameter which provides the end # user's IP address. Doing so will help distinguish this legitimate # server-side traffic from traffic which doesn't come from an end-user. url = ('https://ajax.googleapis.com/ajax/services/search/web' '?v=1.0&q=Paris%20Hilton&userip=USERS-IP-ADDRESS') request = urllib2.Request( url, None, {'Referer': /* Enter the URL of your site here */}) response = urllib2.urlopen(request) # Process the JSON string. results = simplejson.load(response) # now have some fun with the results... import simplejson # The request also includes the userip parameter which provides the end # user's IP address. Doing so will help distinguish this legitimate # server-side traffic from traffic which doesn't come from an end-user. url = ('https://ajax.googleapis.com/ajax/services/search/web' '?v=1.0&q=Paris%20Hilton&userip=USERS-IP-ADDRESS') request = urllib2.Request( url, None, {'Referer': /* Enter the URL of your site here */}) response = urllib2.urlopen(request) # Process the JSON string. results = simplejson.load(response) # now have some fun with the results..
실제 애플리케이션에서는 다음과 같을 수 있습니다. Google 크롤링에 필요 웹 페이지가 많기 때문에 크롤링 작업을 공유하려면 멀티스레딩이 필요합니다. Google Web Search API 사용에 대한 자세한 참조 소개는 여기를 참조하세요(표준 URL 인수는 여기에 소개되어 있습니다). 또한 URL의 rsz 매개변수는 8보다 작은 값이어야 합니다(8 포함). 8보다 크면 오류가 보고됩니다.
(3) 코드 구현
코드 구현에는 여전히 문제가 있지만 실행할 수 있고 견고성이 좋지 않으며 개선이 필요하다는 점을 전문가 모두가 지적해 주셨으면 합니다. 실수(파이썬 초보자)에게 감사하겠습니다.
#-*-coding:utf-8-*- import urllib2,urllib import simplejson import os, time,threading import common, html_filter #input the keywords keywords = raw_input('Enter the keywords: ') #define rnum_perpage, pages rnum_perpage=8 pages=8 #定义线程函数 def thread_scratch(url, rnum_perpage, page): url_set = [] try: request = urllib2.Request(url, None, {'Referer': 'http://www.sina.com'}) response = urllib2.urlopen(request) # Process the JSON string. results = simplejson.load(response) info = results['responseData']['results'] except Exception,e: print 'error occured' print e else: for minfo in info: url_set.append(minfo['url']) print minfo['url'] #处理链接 i = 0 for u in url_set: try: request_url = urllib2.Request(u, None, {'Referer': 'http://www.sina.com'}) request_url.add_header( 'User-agent', 'CSC' ) response_data = urllib2.urlopen(request_url).read() #过滤文件 #content_data = html_filter.filter_tags(response_data) #写入文件 filenum = i+page filename = dir_name+'/related_html_'+str(filenum) print ' write start: related_html_'+str(filenum) f = open(filename, 'w+', -1) f.write(response_data) #print content_data f.close() print ' write down: related_html_'+str(filenum) except Exception, e: print 'error occured 2' print e i = i+1 return #创建文件夹 dir_name = 'related_html_'+urllib.quote(keywords) if os.path.exists(dir_name): print 'exists file' common.delete_dir_or_file(dir_name) os.makedirs(dir_name) #抓取网页 print 'start to scratch web pages:' for x in range(pages): print "page:%s"%(x+1) page = x * rnum_perpage url = ('https://ajax.googleapis.com/ajax/services/search/web' '?v=1.0&q=%s&rsz=%s&start=%s') % (urllib.quote(keywords), rnum_perpage,page) print url t = threading.Thread(target=thread_scratch, args=(url,rnum_perpage, page)) t.start() #主线程等待子线程抓取完 main_thread = threading.currentThread() for t in threading.enumerate(): if t is main_thread: continue t.join()